我正在尝试在 Unix 中使用 addr2line 命令,但每次它都给出与 ??:0 相同的输出。我正在发出命令addr2line -e a.out 0x4005BDC
。我在使用valgrind
查找内存泄漏的工具运行此 a.out 可执行文件时得到了此地址。-g
我还用选项编译了源代码。
4 回答
您也可以使用 gdb 代替 addr2line 来检查内存地址。在 gdb 中加载可执行文件并打印存储在该地址处的符号名称。16 检查符号表。
(gdb) info symbol 0x4005BDC
您需要指定 addr2line 的偏移量,而不是虚拟地址 (VA)。大概如果您关闭了地址空间随机化,您可以使用完整的 VA,但在大多数现代操作系统中,地址空间是随机的以用于新进程。
给定 valgrind 的 VA 0x4005BDC
,在内存中找到进程或库的基地址。/proc/<PID>/maps
通过在程序运行时检查文件来做到这一点。感兴趣的行是text
您的进程段,可通过权限r-xp
和程序或库的名称来识别。
假设基础 VA 是0x0x4005000
。然后你会发现 valgrind 提供的 VA 和基本 VA: 之间的区别0xbdc
。然后,将其提供给 add2line:
addr2line -e a.out -j .text 0xbdc
看看这是否能让你得到你的行号。
这正是你使用它的方式。但是,您拥有的地址可能与源代码中的某些内容不直接对应。
例如:
$ cat t.c
#include <stdio.h>
int main()
{
printf("hello\n");
return 0;
}
$ gcc -g t.c
$ addr2line -e a.out 0x400534
/tmp/t.c:3
$ addr2line -e a.out 0x400550
??:0
0x400534
是main
我的地址。0x400408
也是 中的有效函数地址a.out
,但它是由 GCC 生成/导入的一段代码,没有调试信息。(在这种情况下,__libc_csu_init
您可以使用 . 查看可执行文件的布局readelf -a your_exe
。)
其他时候addr2line
会失败的情况是,如果您包含一个没有调试信息的库。
尝试添加-f
选项以显示函数名称:
addr2line -f -e a.out 0x4005BDC