【问题标题】:Stepping out after stopping on catchpoint in GDB在 GDB 中的 catchpoint 处停止后退出
【发布时间】:2017-10-19 11:01:11
【问题描述】:

为了调试我的程序,我需要查看在加载共享库之后发生了什么。我使用 GDB 的 catch load 命令停止共享库事件。

我对共享库的理解如下:最初,PLT 入口指向一些加载库的代码。当它被调用时,库被加载并且 PLT 条目开始指向实际加载的库代码,这样下次调用 lib 时,我们只需跳转到它的代码而不重新加载。考虑到这一点,我希望捕获点位于从 PLT 调用的某个系统函数中,并且我希望我的代码位于堆栈中更高的位置。

但是,catchpoint 处的堆栈如下所示:

(gdb) bt #0 0x00007ffff7df0632 in ?? () from /lib64/ld-linux-x86-64.so.2 #1 0x00007ffff7dd8c2a in ?? () from /lib64/ld-linux-x86-64.so.2 #2 0x00007ffff7dd7c38 in ?? () from /lib64/ld-linux-x86-64.so.2 #3 0x000000000000000a in ?? () #4 0x00007fffffffde1e in ?? () // several frames without location info

此时,我想从开始加载共享库的位置继续执行我的代码。但是,我在堆栈中看不到我的代码。此外,我不明白框架#3 的含义。我无法超越该框架,因为 GDB 无法在堆栈上找到有效的返回地址(这很明显,因为0xa 绝对不是有效的返回地址)。

什么是0xa,为什么它在堆栈中? 有没有办法在我的代码中完全加载共享库后停止 GDB?

【问题讨论】:

  • 什么是"PLT"

标签: c++ c gdb shared-libraries


【解决方案1】:

我对共享库的理解告诉我们:最初 PLT 入口指向一些加载库的代码。当它被调用时,库被加载,PLT 条目开始指向实际加载的库代码,这样下次调用 lib 时,我们只需跳转到它的代码而不重新加载。

这种理解是错误的。

有两种情况需要考虑,它们都不涉及在调用库中的函数时加载库。

案例 #1:您的二进制文件直接链接到共享库,如下所示:

gcc main.c -lc  # links against libc.so.6

您可以通过readelf -d a.out | grep NEEDED 看到您的二进制文件直接链接到的一组库。

在这种情况下,动态加载器会在可执行文件开始运行之前加载所有库。

案例 #2:您通过 dlopen 动态添加新库。

在这种情况下,库是从 dlopen 实现中加载的。

您可能会感到困惑的是惰性 PLT 解析(它与库加载无关)。你可以阅读它here

【讨论】:

    猜你喜欢
    • 2017-06-07
    • 2013-07-20
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 2016-10-26
    • 2018-01-20
    • 2020-12-26
    • 2020-07-23
    相关资源
    最近更新 更多