【问题标题】:How to use the addr2line command in Linux?如何在 Linux 中使用 addr2line 命令?
【发布时间】:2011-11-30 17:01:22
【问题描述】:

我正在尝试在 Unix 中使用 addr2line 命令,但每次它给出的输出都与 ??:0 相同。我以 addr2line -e a.out 0x4005BDC 的身份发出命令。我在使用valgrind 工具运行这个 a.out 可执行文件以查找内存泄漏时得到了这个地址。我还使用-g 选项编译了源代码。

【问题讨论】:

    标签: c linux valgrind addr2line


    【解决方案1】:

    您也可以使用 gdb 代替 addr2line 来检查内存地址。在 gdb 中加载可执行文件并打印存储在该地址处的符号名称。 16 Examining the Symbol Table.

    (gdb) info symbol 0x4005BDC 
    

    【讨论】:

    • 好主意。此外,在 gdb 中使用该地址处的断点运行程序并获取回溯可以提供有关那里到底发生了什么的良好信息。
    • 另见 (gdb) 信息行 * 0x4005BDC
    • (库)代码地址在使用“-g”标志和不使用标志编译之间是相同还是不同?
    【解决方案2】:

    您需要为 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
    

    看看这是否能让你得到你的行号。

    【讨论】:

    • 等等,什么偏移量? addr2line 不只是从 symtab(或 dyntab)中获取地址吗?
    【解决方案3】:

    这正是您使用它的方式。但是,您拥有的地址可能与源代码中的某些内容不直接对应。

    例如:

    $ 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 会失败的其他情况是,如果您包含没有调试信息的库。

    【讨论】:

    • 在我的代码中,我使用的是 pthread 和 libconfing 库。我不知道这些库是否有调试信息。
    【解决方案4】:

    尝试添加-f 选项以显示函数名称:

    addr2line -f -e a.out 0x4005BDC
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-26
      • 2011-07-15
      • 2019-12-24
      • 2020-11-11
      • 1970-01-01
      • 2012-07-07
      • 2021-08-15
      • 2014-05-25
      相关资源
      最近更新 更多