最近在尝试使用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:69DisableASLR函数报的错误,源码:

 1static void DisableASLR(int error_fd) {
 2#if defined(__linux__)
 3  const unsigned long personality_get_current = 0xffffffff;
 4  int value = personality(personality_get_current);
 5  if (value == -1)
 6    ExitWithError(error_fd, "personality get");
 7
 8  value = personality(ADDR_NO_RANDOMIZE | value);
 9  if (value == -1)
10    ExitWithError(error_fd, "personality set");
11#endif
12}

即执行personality(ADDR_NO_RANDOMIZE | value)失败,关于personalityA tour of Linux syscall personality有一个简单的介绍。

lldb报personality set failed: Function not implemented即是personality函数没有实现。可以写一个简单的程序:

 1#include <stdlib.h>
 2#include <iostream>
 3#include <sys/personality.h>
 4
 5static void ExitWithError(int error_fd,
 6	const char* operation) {
 7	int err = errno;
 8	std::cout << strerror(err) << std::endl;
 9	exit(1);
10}
11
12int main()
13{
14	int error_fd = 0;
15	const unsigned long personality_get_current = 0xffffffff;
16	int value = personality(personality_get_current);
17	if (value == -1)
18		ExitWithError(error_fd, "personality get");
19
20	value = personality(ADDR_NO_RANDOMIZE | value);
21	if (value == -1)
22		ExitWithError(error_fd, "personality set");
23	return 0;
24}

来进行测试。

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启动时自动执行。

转载请标明出处。