原文:How to point GDB to your sources
翻译:雁惊寒
如果你手头上有一个你自己或者别人开发的程序,但它有一些bug。或者你只是想知道这个程序是如何工作的。怎么办呢?你需要一个调试工具。
现在很少有人会直接对着汇编指令进行调试,通常情况下,大家都希望能对照着源代码进行调试。但是,你调试使用的主机,一般来说并不是构建程序的那台,因此你会看到如下这个令人沮丧的消息:
$ gdb -q python3.7
Reading symbols from python3.7...done.
(gdb) l
6 ./Programs/python.c: No such file or directory.
我经常会看到这些报错信息,并且对于调试程序来说,这也非常重要。所以,我认为我们需要详细了解一下GDB是如何在调试会话中显示源代码的。
调试信息
首先,我们从调试信息开始。调试信息是由编译器生成的存在于二进制文件中的特殊段,供调试器和其他相关的工具使用。
在GCC中,有一个著名的-g
标志用于生成调试信息。大多数使用某种构建系统的项目都会在构建时默认包含或者通过一些标志来添加调试信息。
例如,在CPython中,你需要执行以下命令:
$ ./configure --with-pydebug
$ make -j
-with-pydebug
会在调用GCC时添加-g
选项。
这个-g
选项会生成二进制的调试段,并插入到程序的二进制文件中。调试段通常采用DWARF格式。对于ELF二进制文件来说,调试段的名称一般都是像.debug_ *
这样的,例如 .debug_info
或者.debug_loc
。这些调试段使得调试程序成为可能,可以这么说,它是汇编级别的指令与源代码之间的映射。
要查看程序是否包含调试符号,你可以使用objdump
命令列出二进制文件的所有段:
$ objdump -h ./python
python: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 0000001c 0000000000400238 0000000000400238 00000238 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 0000000000400254 0000000000400254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
...
25 .bss 00031f70 00000000008d9e00 00000000008d9e00 002d9dfe 2**5
ALLOC
26 .comment 00000058 0000000000000000 0000000000000000 002d9dfe 2**0
CONTENTS, READONLY
27 .debug_aranges 000017f0 0000000000000000 0000000000000000 002d9e56 2**0