GDB为什么需要可执行文件以及核心转储?


11

我正在使用核心转储进行调试,请注意,gdb需要您提供可执行文件以及核心转储。为什么是这样?如果核心转储包含该进程使用的所有内存,那么核心转储中是否包含可执行文件?也许不能保证整个exe文件都已加载到内存中(尽管单个可执行文件通常不会那么大),或者核心转储毕竟不包含所有相关内存?是否用于符号(也许它们没有正常加载到内存中)?


1
可执行文件包含符号信息,如gdb文档中所述...
Thomas Dickey

1
令人惊讶的是,没有答案(除了我刚刚添加的答案)提到了DWARF格式
Basile Starynkevitch

Answers:


15

核心转储只是程序内存占用的转储,如果您知道所有内容都在哪里,则可以使用它。

您使用可执行文件是因为它解释了事物(在逻辑地址方面)在内存中的位置,即核心文件。

如果使用命令objdump,它将转储有关正在调查的可执行对象的元数据。以名为a.out的可执行对象为例。

objdump -h a.out仅转储标题信息,您将看到名为eg的部分。.data.bss.text(还有更多)。这些通知内核加载程序在对象中的哪个地方可以找到各个节,应该在进程地址空间中的哪个地方加载该节,以及对于某些节(例如.data .text)应该加载什么。(.bss节在文件中不包含任何数据,但它指的是在进程中为未初始化的数据保留的内存量,它用零填充)。

可执行目标文件的布局符合标准ELF。

objdump -x a.out -倾倒一切

如果可执行对象仍然包含其符号表(尚未剥离,man strip并且您曾经-g生成调试生成以gcc 假定使用ac源编译),则可以按符号名称检查核心内容,例如,是否有变量/缓冲区在源代码中名为inputLine的情况下,您可以使用该名称gdb查看其内容。即gdb会知道从程序初始化的数据段(其中inputLine开始)的起点的偏移量以及该变量的长度。

进一步阅读第1 第2条,以及更具体的可执行和链接格式(ELF)规范


在@mirabilos评论后更新。

但是如果像这样使用符号表

$ gdb --batch -s a.out -c core -q -ex "x buf1"

产生

 0x601060 <buf1>:    0x72617453

然后不使用符号表并直接检查地址,

$ gdb --batch -c core -q -ex "x 0x601060"

产生

0x601060:   0x72617453

我直接检查了内存,没有使用第二个命令中的符号表。


我也看到,@ user580082的答案进一步说明了这一点,并将投票赞成。


6
从未听说过“基本堆栈部分”。.bss(历史上)是“以符号开头的块”,实际上是“统一数据”,而.data是“初始化数据”,文本(不是.code)用于存储机器代码。二进制文件中没有堆栈部分,因为堆栈是在运行时创建的。
jlliagre

“如果您知道所有内容都在哪里,那么您就可以使用它”也不是正确的,因为程序中的所有内容都不一定包含在内。
mirabilos

1
@jlliagre,您是正确的,我错误地称为.text .code(因为在撰写答案时我一直在想一个解释)-已更新。我错误地按名称误认为了bss,并更新了答案,但避免了*以符号开头的块,因为我认为它并未真正添加到等式中,并已将其解释为未初始化的数据,这就是我们达成共识。谢谢-感谢您发表评论以更正此帖子。
X田

4

核心文件是进程终止时堆栈映像,内存映射和寄存器的快照。其内容可以按照核心手册页中的说明进行操作。默认情况下,私有映射,共享映射和ELF标头信息被转储到核心文件中。

谈到您的问题,gdb需要可执行文件的原因是因为它不像valgrind那样通过读取和解释二进制指令来模拟执行,相反它成为了进程的父级,从而在运行期间控制了进程的行为时间。它使用核心文件来确定崩溃期间的内存映射和进程的处理器状态。

在Linux中,父进程可以获得有关其子进程的其他信息,特别是ptrace的能力,这使调试器可以访问进程的底层信息,例如读/写其内存,寄存器,更改信号映射,停止其执行等。

阅读任何调试器的工作原理后,尽管拥有更多核心文件,您将了解可执行文件的要求。


1

(除了其他好的答案)

在现代Linux(以及许多类似Unix的系统)上,调试信息(包括有关符号类型,源代码位置,变量类型等的元数据)是DWARF格式,位于ELF可执行文件(或ELF共享库)时使用某些-g选项进行编译。我建议编译要调试的程序,如果使用最新的GCC-g3 -O0也可能要调试;但是,使用GCC,您甚至可以同时编译优化和调试信息,例如使用,尽管在这种情况下调试信息可能有点“模糊”(这可能会有助于捕获一些顽皮的Heisenbugs)。-fno-inline-O2 -g1

避免将这些信息放在核心文件中是非常明智的,因为core对于同一个可执行文件,您可能会有许多不同的核心文件(想象一个使用广泛的软件,有许多用户在进行错误报告,其中大多数用户使用转储)。此外核心(5)文件由内核,这不应该关心矮部分存在倾销精灵(5)可执行文件(因为这些部分不映射到虚拟地址空间的断层的过程,其倾倒在一些核心信号( 7))。甚至有可能将调试信息放在单独的文件中(在可执行文件之外)。

顺便说一句,GDB可以很痛苦地用于调试没有任何调试信息的可执行文件的核心转储。但是实际上您是在机器代码级别(而不是编程语言及其编译器提供的符号级别)进行调试的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.