我有一个 PIC 共享库,它也有一个 main 函数
#include <dtest2.h>
#include <stdio.h>
extern const char elf_interpreter[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
int dtestfunc1(int x,int y) {
int i=0;
int sum = 0;
for(i=0;i<=x;i++) {
sum+=y;
sum+=dtestfunc2(x,y);
}
return sum;
}
int main (int argc, char const* argv[])
{
printf("starting sharedlib main\n");
int val = dtestfunc1(4,5);
printf("val = %d\n",val);
_exit(0);
}
此库链接到另一个共享库 libdtest2
,它具有从 dtestfunc1
调用的 dtestfunc2
的实现。
如果我使用
直接在 dtestfunc1 上运行 gdbgdb libdtest1.so
libdtest2.so 的符号未由 gdb 加载。因此,我无法进入 dtestfunc1
,如果我按 s,函数就会执行并退出。
如果我创建一个在共享库上调用 dlopen 的驱动程序,gdb 会在执行 dlopen 后正确加载符号并且一切正常。
- 为什么 gdb 在这两种情况下表现不同?
- 如果我直接在共享库上运行 gdb,如何手动将 gdb 指向共享库?
注意:这是一个玩具示例,它反射(reflect)了我在更大的共享库中遇到的问题。我所有的二进制文件和库都是使用 -ggdb3 标志编译的。
编辑:我的共享库是可运行的。我使用源代码中的外部定义添加了正确的解释器路径。我用 gcc -ggdb3 -O0 -shared -Wl,-soname,libdtest1.so.1 -ldtest2 -L/usr/lib -Wl,-e,main -o libdtest1.so.1.0 dtest1.o 编译了它
。
我可以运行它并且它执行得很好。运行共享库不是这里的问题。
最佳答案
Why is gdb behaving differently in both these cases?
因为你没有构建libdtest1.so
正确地让 GDB 使用它。
特别是,您的 libdtest1.so
缺少DT_DEBUG
在其动态部分中输入,您可以这样确认:
readelf -d libdtest1.so | grep DEBUG
你应该什么也看不到。在正确构建的可运行文件中 libdtest1.so
(您可以使用 -pie
标志构建),输出应如下所示:
0x00000015 (DEBUG) 0x0
运行时加载程序更新 DT_DEBUG
指向它的r_debug
结构,然后允许 GDB 找到其他加载的共享库。没有DT_DEBUG
, GDB 找不到它们。
更新:
After adding the pie flag my build command is
gcc -ggdb3 -O0 -pie -shared -Wl,-soname,libdtest1.so.1 -ldtest2 -L/usr/lib -Wl,-e,main -o libdtest1.so.1.0 dtest1.c -I.
The DEBUG section is still missing
术语:它不是 DEBUG
部分。这是一个DT_DEBUG
在 .dynamic
中输入部分。
它仍然缺失,因为 -shared
覆盖 -pie
.删除 -shared
来自链接行。
你也不需要 -Wl,-e,main
,您也不需要指定 .interp
-- GCC 将为您完成。
正确的链接命令:
gcc -ggdb3 -O0 -pie -rdynamic dtest1.c -I. -Wl,-soname,libdtest1.so.1 \
-L/usr/lib -ldtest2 -o libdtest1.so.1.0
(链接线上源和库的顺序很重要,你的顺序错了。)
额外奖励:您的主将收到正确的 argc
和 argv[]
,而不是你现在得到的虚假值。
关于c - 运行独立共享库时 gdb 不加载符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30946735/