为什么GDB只有在碰到`main`时才能解析这个符号?为什么valgrind不能解决它?
问题描述:
我正在尝试track down和issue,其中Valgrind无法解析通过某些库的函数的符号。我得到的输出是这样的:为什么GDB只有在碰到`main`时才能解析这个符号?为什么valgrind不能解决它?
==83597== 920 bytes in 1 blocks are possibly lost in loss record 750 of 864
==83597== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==83597== by 0x548EF93: myproject_malloc (mysourcefile.c:48)
==83597== by 0x4F13FD5: ??? (in /path/to/project/library-version.so)
==83597== by 0x54542FF: ??? (in /path/to/project/library-version.so)
==83597== by 0x4F536CA: ??? (in /path/to/project/library-version.so)
==83597== by 0x54542FF: ??? (in /path/to/project/library-version.so)
功能之一内library-version.so
是do_init()
。 library-version.so
通过LD_PRELOAD
加载。我发现当我在gdb下运行我的程序时,如果我在启动程序时尝试在do_init
处设置断点,它会抱怨找不到该符号,但如果我在main
处放置断点并等到它达到那个时间,然后它就起作用了。
例如:
(gdb) break do_init
Function "do_init" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) break main
Breakpoint 1 at 0x400b50: file runner.c, line 13.
(gdb) run
... a bunch of output from the stuff in LD_PRELOAD ...
Breakpoint 1, main (argc=1, argv=0x7fffffffe028) at myprogram.c:13
13 return do_some_stuff();
(gdb) break do_init
Breakpoint 2 at 0x7ffff7658de0: file my/library/initializer.c, line 25.
因此,这导致我两个问题:
它似乎
do_init
是越来越由动态链接拉入。我怎样才能找出发生的初始化过程的哪个步骤?这个项目中使用了许多库,它们用__attribute__((constructor))
定义函数,并且它们通过链接器脚本粘在一起。为什么Valgrind看不到动态链接器加载的符号像GDB那样?我99%确定没有任何东西是
dlclose
'd,我认为任何在LD_PRELOAD
之下的东西都会对Valgrind保持可见,无论如何。
答
原来因为一大堆正巧存在同时奇怪的配置选项,即包含在.text
部的library-version.so
程序节头用rwx权限,而不是RX权限标记。 Valgrind认为.text
部分不能在amd64机器上拥有rwx权限,因此它会在尝试加载调试符号时忽略它们。
我相信这是Valgrind中的一个错误,因为.text
部分的rwx权限根据相关标准完全有效;原来报告已经filed here,我已经扩大了。
@iharob其中?共享库或二进制文件? –
你是如何构建'library-version.so'的?它有调试符号吗? –
所有这些,是否有一个Makefile? –