Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

3.6 调试信息

目标文件里面还有可能保存的是调试信息。几乎所有现代的编译器都支持源代码级别的调试,比如我们可以在函数里面设置断点,可以监视变量变化,可以单步行进等,前提是编译器必须提前将源代码与目标代码之间的关系等,比如目标代码中的地址对应源代码中的哪一行、函数和变量的类型、结构体的定义、字符串保存到目标文件里面。甚至有些高级的编译器和调试器支持查看STL容器的内容,即程序员在调试过程中可以直接观察STL容器中的成员的值。

如果我们在GCC编译时加上"-g"参数,编译器就会在产生的目标文件里面加上调试信息,我们通过readelf等工具可以看到,目标文件里多了很多"debug"相关的段:

[Nr] Name     Type    Addr    Off Size  ES  Flg Lk  Inf Al
...
  [ 4] .debug_abbrev  PROGBITS  00000000 000040 000034 00 0   0  1
  [ 5] .debug_info      PROGBITS  00000000 000074 0000af 00 0   0  1
  [ 6] .rel.debug_info  REL 00000000 000738 000038 08 9   5  4
  [ 7] .debug_line      PROGBITS  00000000 000123 000037 00 0   0  1
  [ 8] .rel.debug_line  REL 00000000 000770 000008 08 19  7  4
  [ 9] .debug_frame   PROGBITS  00000000 00015c 000034 00 0   0  4
  [10] .rel.debug_frame REL 00000000 000778 000010 08 19  9  4
  [11] .debug_loc     PROGBITS  00000000 000190 00002c 00 0   0  1
  [12] .debug_pubnames  PROGBITS  00000000 0001bc 00001a 00 0   0  1
  [13] .rel.debug_pubnam  REL 00000000 000788 000008 08 19  12 4
  [14] .debug_aranges   PROGBITS  00000000 0001d6 000020 00 0   0  1
  [15] .rel.debug_arange  REL 00000000 000790 000010 08 19  14 4
...

这些段中保存的就是调试信息。现在的ELF文件采用一个叫DWARF(Debug With Arbitrary Record Format)的标准的调试信息格式,现在该标准已经发展到了第三个版本,即DWARF 3,由DWARF标准委员会由2006年颁布。Microsoft也有自己相应的调试信息格式标准,叫CodeView。关于调试信息的具体内容我们在这里不再详细展开了,它将是另外一个独立的并且很大的话题,对我们理解整个系统软件的意义不大,有兴趣的读者可以参照相应的格式标准。但是值得一提的是,调试信息在目标文件和可执行文件中占用很大的空间,往往比程序的代码和数据本身大好几倍,所以当我们开发完程序并要将它发布的时候,须要把这些对于用户没有用的调试信息去掉,以节省大量的空间。在Linux下,我们可以使用"strip"命令来去掉ELF文件中的调试信息:

$strip foo