解决lldb调试时可能出现的personality set failed: Function not implemented

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

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 
#include 
#include 

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版本的:
解决lldb调试时可能出现的personality set failed: Function not implemented_第1张图片

Ubuntu的glibc是2.35的,比较新(目前最新的glibc是2.38),经过测试,没这样的问题,所以CentOS7的版本是太老了。
解决lldb调试时可能出现的personality set failed: Function not implemented_第2张图片
可能有读者想到了升级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即可:

解决lldb调试时可能出现的personality set failed: Function not implemented_第3张图片

不能每次都手动输入,为了方便可以将命令写入到~/.lldbinit文件中,每次lldb启动时自动执行。

转载请标明出处。

你可能感兴趣的:(Linux,#,C/C++,LLVM/Clang,ubuntu,centos,lldb,personality,Function,not,implemented,set,failed)