为了调试我的程序,我需要在加载共享库之后看到发生了什么。我使用GDB的catch load
命令来停止共享库事件。
我对共享库的理解告诉我们:最初PLT条目指向一些加载lib的代码。当它被调用时,库被加载并且PLT条目开始指向实际加载的库代码,以便下次调用lib时我们只需跳转到它的代码而不重新加载。考虑到这一点,我希望catchpoint位于从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?
答案 0 :(得分:0)
我对共享库的理解告诉我们:最初PLT条目指向一些加载lib的代码。当它被调用时,库被加载并且PLT条目开始指向实际加载的库代码,以便下次调用lib时我们只需跳转到它的代码而不重新加载。
这种理解是不正确的。
有两种情况需要考虑,它们都不涉及在调用函数时加载库。
案例#1:您的二进制文件直接与共享库链接,如下所示:
gcc main.c -lc # links against libc.so.6
您可以使用readelf -d a.out | grep NEEDED
查看二进制文件直接链接的库集。
在这种情况下,在可执行文件开始运行之前,动态加载程序会加载所有库。
案例#2:您通过dlopen
动态添加新库。
在这种情况下,库是从dlopen
实现中加载的。
您可能感到困惑的是懒惰的PLT解析(其中没有与库加载有关)。你可以阅读它here。