最近在尝试使用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启动时自动执行。
转载请标明出处。