我在Linux系统上有一个共享库(hlapi.so)。此hlapi.o有许多模块(我的意思是.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.的文件夹,以便GDB可以从hlapi.so中加载符号。然后我使用:
print hlapiInitialized
print app_sp
在我们的模块中解析全局数据。但是输出值非常异常。
我的问题是,如果我可以通过GDB在没有可执行文件的情况下通过GDB解析全局数据?如果我通过GDB获得的输出可信吗?我感谢任何评论。
btw,hlapi.so是使用GCC选项" -g -fpic"构建的。
我一段时间调查了问题,我认为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和Core文件的输出后,我们知道一旦将共享库加载到该过程中,将重新分配全局变量的地址,并且全局变量的地址清晰。因此,一旦拥有共享库的符号信息,GDB可以映射变量。