Dwarf调试信息Consumer——gdb
1 引言
前面介绍过dwarf调试信息格式,内容包括有哪些类型的调试信息,调试信息的存放格式、某些调试信息的编码方法等。本文的内容主要调试信息是怎样被解析使用的调试信息作为编译器为了实现源码级别调试生成的内容,其主要的consumer自然是gdb。下面介绍gdb中如何使用dwarf调试信息。
本文是一个基于源码debug过程的分析文档,内容比较细,偏笔记性质的。总结抽象工作做得不多。所以其中的内容以及一些流程图都会比较细节。下面提供一个总结概括性的ppt文档点击打开链接。
2 调试信息回顾
在介绍gdb如何读取dwarf调试信息之前,我们先回顾一下有哪些调试信息,调试信息在elf文件中的位置。
在使用gcc编译程序的时候,加上-g参数,那么最后生成的目标文件中会有调试信息,调试信息格式使用dwarf2格式。使用readelf工具加上-S参数,可以查看目标文件中有哪些调试信息section,示例如图2-1所示。
图 2‑1 调试信息类别
可以看到.debug_*都是调试信息的section,每个section代表不同类型的调试信息,表2-1介绍不同类型调试信息。
表格2‑1调试信息类型说明
Section |
说明 |
.debug_info |
调试信息主要内容,各个DIE |
.debug_abbrev |
调试信息缩写表,每个编译单元对应一个缩写表,每个缩写表包含一系列的缩写声明,每个缩写对应一个DIE |
.debug_line |
行号信息 |
.debug_macinfo |
宏信息,编译器-g3参数才会产生宏信息 |
.debug_aranges |
范围表,每个编译单元对应一个范围范围表,记录了该编译单元的某些ENTRY的text或者data的起始地址和长度,用于跨编译单元的快速查询 |
.debug_pubnames |
全局符号查询表,以编译单元为单位,记录了每个编译单元的全局符号的名称 |
.debug_frame |
函数的堆栈信息 |
.debug_str |
.debug_info中使用到的字符串表 |
.debug_loc |
Location list |
3 Gdb使用调试信息
Gdb中实现源码级别调试,主要实现名称、位置的映射。而这些信息在gdb内部通过symbol来记录的。Symbols按照一定的关系组合在一起,形成symbol table。在gdb中有三类符号表。
表格3‑1 gdb中的符号表
说明 |
|
Minimal_symbol table |
该符号表通过分析elf文件中的.symtab section得来,该section中记录的是在elf文件的链接过程中所必须的一些全局的符号。该符号表在没有-g参数的时候也会有。 |
Partial symboltable |
顾名思义,部分符号表,里面记录的是部分的符号的部分的信息,在gdb读入symbol file的时候会初步分析调试信息,建立这么一张partial symbol table,它有两个作用:1,满足一部分的调试需求;2,gdb可以根据partial symtab读入full symtab。 |
Full symbol table |
完整符号表,里面记录的是完整的符号信息,源码级别调试实现的基础。由于其信息很多,占的内存空间很大,所以gdb在一开始读入symbol file的时候并不会产生这么一个full symtab,而是在后续的调试过程中,如果有需要完整符号表的地方,才会把该cu的full symtab读入,这样效率较高。 |
Gdb调试主要依靠这三个符号表实现,minimal symtab比较简单,也不属于调试信息分析的范畴,本文不会对minimal symtab多加叙述。Partial symtab和full symtab的建立是根据调试信息完成的。下面gdb对调试信息的使用过程也是这么两张符号表的建立的过程。
3.1 Debug_info——PartialSymtab
3.1.1 Partial symtab简介
在展开partial symbol相关的讨论之前,我们先看看partialsymbol是什么。
在gdb中使用structpartial_symbol,来描述一个partial symbol,其中包含的信息如下表所示。
表格3‑2 struct partial_symbol
数据项 |
说明 |
Domain |
该symbol的类型:变量、函数、type、label等。 |
Address_class |
说明该符号的地址类型,即在什么地方可以找到该符号:寄存器、arglist、local变量、typedef类型等。 |
Struct general_symbol_info |
所有类型符号的基础信息:name、value(是个union,取决于符号的类型)、在哪个section等。 |
Partial symbol以一定的规则组合在一起,形成partial symtab,gdb中以source file为单位,每个source file对应一个struct partial_symtab,一个objfile中的所有的partial_symtab组成一个链表。Partial symtab中只记录该file中static类型的和global类型的一些符号。Struct partial_symtab的包含的信息如下表所示。
表格3‑3 struct partial_symtab
数据项 |
说明 |
Struct partial_symtab *next |
Objfile的所有partial_symtab形成一个链表 |
Filename、fullname、dirname |
文件名、路径等信息 |
Struct objfile *objfile |
对应是哪个objfile |
Struct section_offsets |
Objfile的各个section的offset |
Textlow、 texthigh |
该file的地址范围 |
Struct partial_symtab **dependencies |
该file依赖的文件。依赖的意思是在读入本file的symbol之前,要先将dependency的symbol先读入。比如hello.c中include hello.h&#x |