解决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:69
的DisableASLR
函数报的错误,源码:
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)
失败,关于personality
,
A 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启动时自动执行。
转载请标明出处。
- 原文作者:Witton
- 原文链接:https://wittonbell.github.io/posts/2023/2023-08-13-解决lldb调试时可能出现的personality-set-failed-Function-not-implemented/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。