您已经几乎回答了所有的问题,只有两个问题还没有解决。
首先,文件名/行号和程序计数器之间的关系编码在 .debug_line
中,而不是 .debug_info
。
其次,变量不是 foo()
的子级:每个变量都是词法块的子级。程序结构中相关部分应该如下:
DW_TAG_compile_unit
DW_TAG_subprogram
DW_TAG_lexical_block
DW_TAG_variable
DW_TAG_lexical_block
DW_TAG_variable
词法块应该与地址范围相关联,但这可能使用DW_AT_ranges
来编码,而不是DW_AT_low_pc
/DW_AT_high_pc
; 如果是这种情况,则需要解释.debug_ranges
。
为了说明这个问题,我使用cc -g
(Oracle Linux上的gcc 4.8.5)编译了以下内容...
1 #include <stdlib.h>
2
3 struct A { int a; };
4 struct B { int b; };
5
6 void foo()
7 {
8 {
9 struct A *b;
10 }
11
12 {
13 struct B *b;
14 b = malloc(sizeof (struct B));
15 }
16 }
...并使用'readelf -w'解码DWARF。第14行出现在行号表中:
[0x00000032] Special opcode 124: advance Address by 8 to 0x8 and Line by 7 to 14
意思是我们对地址0x8很感兴趣。DIE层次结构包括:
<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
<1><96>: Abbrev Number: 6 (DW_TAG_subprogram)
<9d> DW_AT_low_pc : 0x0
<a5> DW_AT_high_pc : 0x18
<2><b3>: Abbrev Number: 7 (DW_TAG_lexical_block)
<b4> DW_AT_low_pc : 0x8
<bc> DW_AT_high_pc : 0xe
<3><c4>: Abbrev Number: 8 (DW_TAG_variable)
<c5> DW_AT_name : b
<c7> DW_AT_decl_file : 1
<c8> DW_AT_decl_line : 13
<c9> DW_AT_type : <0xd2>
地址为0xb3的DIE不包含任何进一步的词法块,因此它表示地址0x8处最紧密的作用域。因此,在这一点上,“b”这个名称必须引用DIE在0xc4处的子级。该变量的类型由其给出。
<1><d2>: Abbrev Number: 9 (DW_TAG_pointer_type)
<d3> DW_AT_byte_size : 8
<d4> DW_AT_type : <0x81>
<1><81>: Abbrev Number: 4 (DW_TAG_structure_type)
<82> DW_AT_name : B
<84> DW_AT_byte_size : 4
<2><8b>: Abbrev Number: 5 (DW_TAG_member)
<8c> DW_AT_name : b
<90> DW_AT_type : <0x34>
<94> DW_AT_data_member_location: 0
<1><34>: Abbrev Number: 3 (DW_TAG_base_type)
<35> DW_AT_byte_size : 4
<36> DW_AT_encoding : 5 (signed)
<37> DW_AT_name : int
编辑:
在你自己的回答中,你提供了一个反例,其中存在没有对应地址范围的词法块。这种DWARF不符合标准:DWARF 2的§3.4规定词法块条目具有DW_AT_low_pc和DW_AT_high_pc属性,并未暗示这些属性是可选的。如果你使用的是gcc,可能是"内联词法块缺少范围的DWARF调试信息"引起了这个问题。默认的mplayer配置包括-O2优化,它会打开内联;你将在父级DW_TAG_subprogram
中看到这一点,该代码段是从中获取的draw_vertices()
。解决此问题的方法是将-fno-inline
添加到编译器选项中;这似乎并不能完全抑制所有内联,因此您可能希望完全禁用优化。
.debug_aranges
无法帮助你:你需要解析每个 CU 的头部,找到一个匹配的名称。一旦你找到了正确的 CU,你必须自己检查它的后代,将找到的地址范围与所关心的 PC 进行比较。我的观点是,可以将词法块的地址范围编码为DW_AT_ranges
,它引用.debug_ranges
中的一个条目(而不是.debug_aranges
)。 - undefined