GDB可以解析xx.so中没有可执行文件的全局数据吗?

时间:2017-11-25 12:43:48

标签: debugging gcc memory-management gdb core

我在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"。

1 个答案:

答案 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就可以映射变量。