我在linux系统上运行了一个共享库(hlapi.so)。这个hlapi.so有很多模块(我的意思是.c文件)。其中一个名为hlapi.c,它定义了两个全局数据:
static int hlapiInitialized = FALSE;
static struct hlapi_data app_sp;
当然这个hlapi.c模块中还有很多其他代码。 hlapi.so将发布给根据我们的hlapi.so构建自己的应用程序(名为appbasehlapi)的客户。
现在我有一个核心转储,其客户解析的回溯显示核心在我们的代码中。但客户只能向我们提供核心转储文件。 appbasehlapi可执行文件不会与我们共享。所以在我手中,我只有核心转储文件+ hlapi.so。
为了调试这个核心,我通过命令加载核心转储文件
gdb --core=mycoredumpfile
然后在gdb中,我使用
set solib-search-path .
指定包含hlapi.so的文件夹,以便gdb可以从hlapi.so加载符号。然后我用:
print hlapiInitialized
print app_sp
解析模块中的全局数据。但输出值非常不正常。
我的问题是,如果我可以通过gdb解析hlapi.so中定义的全局数据而没有可执行文件?如果我通过gdb获得的输出是可信的? 我很感激任何评论。
顺便说一下,hlapi.so是用gcc选项构建的" -g -fPIC"。
答案 0 :(得分:0)
我调查了一段时间的问题,在我看来,我相信GDB可以在没有可执行文件的情况下解析全局变量。
在测试中,以下代码位于hlapi.cpp中:
static int hlapiInitialized = 0;
void hlapiInit()
{
if (hlapiInitialized == 0)
{
// do something else
}
hlapiInitialized = 1;
}
objdump显示它的汇编代码是:
00000000000009a2 <_Z9hlapiInitv>:
9a2: 55 push %rbp
9a3: 48 89 e5 mov %rsp,%rbp
9a6: c7 05 98 06 20 00 01 movl $0x1,0x200698(%rip) # 201048 <_ZL16hlapiInitialized>
9ad: 00 00 00
9b0: 90 nop
9b1: 5d pop %rbp
9b2: c3 retq
在运行应用程序期间,我会针对它生成核心转储。在gdb中,在指定solib-search-path之前,我得到:
(gdb) disas hlapiInit
No symbol table is loaded. Use the "file" command.
指定搜索路径后,输出为:
(gdb) disas hlapiInit
Dump of assembler code for function hlapiInit():
0x00007ffff7bd59a2 <+0>: push %rbp
0x00007ffff7bd59a3 <+1>: mov %rsp,%rbp
0x00007ffff7bd59a6 <+4>: movl $0x1,0x200698(%rip) # 0x7ffff7dd6048 <_ZL16hlapiInitialized>
0x00007ffff7bd59b0 <+14>: nop
0x00007ffff7bd59b1 <+15>: pop %rbp
0x00007ffff7bd59b2 <+16>: retq
End of assembler dump.
在比较hlapi.so和核心文件的输出之后,我们知道一旦共享库加载到进程中,全局变量的地址将被重新分配,并且全局变量的地址是明确的。因此,一旦拥有共享库的符号信息,gdb就可以映射变量。