最近在嘗試使用Visual Studio 2022遠程連接Linux進行C/C++的開發,由于CentOS風波不斷,所以現在的開發基本上都是使用ubuntu了,但是目前VS2022有一些BUG,就是遠程調試時,如果目標系統是ubuntu則會出現啟動調試器很慢的問題,基本上要超過20秒,甚至更久,筆者試過幾個ubuntu系統了,不管是實體機,虛擬機,還是容器,只要是ubuntu系統,都存在這樣的問題,向MS提了BUG了,官方還在考慮中,不知道是否修復,啥時候修復。
CentOS系統則不存在很慢的問題,所以筆者在容器中安裝了CentOS7,由于CentOS系統對軟件的更新是比較慢的,所以想要使用C++的新特性,比如C++17,甚至C++20則需要自己安裝新的編譯器和調試器。
筆者在CentOS7安裝了最新的GCC13.2、GDB13.2和llvm 16.0.6(包括clang、lld、lldb等)。使用下來GCC以及GDB都沒發現問題,clang/clang++編譯鏈接也沒發現問題,只有lldb在調試時報了personality set failed: Function not implemented
,查看lldb的源碼發現是在文件source\Host\posix\ProcessLauncherPosixFork.cpp:69
的DisableASLR
函數報的錯誤,源碼:
static void DisableASLR(int error_fd) {
#if defined(__linux__)const unsigned long personality_get_current = 0xffffffff;int value = personality(personality_get_current);if (value == -1)ExitWithError(error_fd, "personality get");value = personality(ADDR_NO_RANDOMIZE | value);if (value == -1)ExitWithError(error_fd, "personality set");
#endif
}
即執行personality(ADDR_NO_RANDOMIZE | value)
失敗,關于personality
,A tour of Linux syscall personality有一個簡單的介紹。
lldb報personality set failed: Function not implemented
即是personality
函數沒有實現。可以寫一個簡單的程序:
#include <stdlib.h>
#include <iostream>
#include <sys/personality.h>static void ExitWithError(int error_fd,const char* operation) {int err = errno;std::cout << strerror(err) << std::endl;exit(1);
}int main()
{int error_fd = 0;const unsigned long personality_get_current = 0xffffffff;int value = personality(personality_get_current);if (value == -1)ExitWithError(error_fd, "personality get");value = personality(ADDR_NO_RANDOMIZE | value);if (value == -1)ExitWithError(error_fd, "personality set");return 0;
}
來進行測試。
personality
函數的實現是在glibc中,CentOS7的glibc是2.17版本的:
Ubuntu的glibc是2.35的,比較新(目前最新的glibc是2.38),經過測試,沒這樣的問題,所以CentOS7的版本是太老了。
可能有讀者想到了升級glibc,可是可以,但是風險非常大,因為glibc是整個系統非常基礎的庫,一旦出問題,則會導致系統崩潰。筆者就在容器中嘗試升級到2.38,發現編譯不過報錯../sysdeps/x86_64/multiarch/memchr-evex-base.S:229: Error: no such instruction: vpcmpneqb (64 * 4)(%rdi),%zmm17,%k1'
,2.36、2.37都是這樣的錯。2.35在添加了參數--disable-werror
后編譯通過了,但是安裝后,常用的命令都不能使用了,不兼容,系統崩潰,不能再啟動。所以一定要慎重升級glibc庫,特別是物理機上。
在lldb源碼source\Commands\CommandObjectProcess.cpp:188
中有提到使用settings target.disable-aslr
來進行開關,即在lldb中先執行settings set target.disable-aslr 0
即可:
不能每次都手動輸入,為了方便可以將命令寫入到~/.lldbinit
文件中,每次lldb啟動時自動執行。
轉載請標明出處。