我试图用dwarf来比较两个c ++文件,但是当我在非成员函数中找到局部变量时,我遇到了问题。请考虑以下代码 -
int f(){
[static] int j=0;
return j;
}
如果我在没有 static
修饰符的情况下编译,我会收到以下矮人信息 -
<1><eb>: Abbrev Number: 13 (DW_TAG_subprogram)
<ec> DW_AT_external : 1
<ed> DW_AT_name : f
<ef> DW_AT_decl_file : 1
<f0> DW_AT_decl_line : 15
<f1> DW_AT_MIPS_linkage_name: (indirect string, offset: 0x22): _Z1fv
<f5> DW_AT_type : <0xa8>
<f9> DW_AT_low_pc : 0x0
<101> DW_AT_high_pc : 0x10
<109> DW_AT_frame_base : 0x0 (location list)
<10d> DW_AT_sibling : <0x130>
<2><111>: Abbrev Number: 14 (DW_TAG_lexical_block)
<112> DW_AT_low_pc : 0x4
<11a> DW_AT_high_pc : 0xe
<3><122>: Abbrev Number: 15 (DW_TAG_variable)
<123> DW_AT_name : j
<125> DW_AT_decl_file : 1
<126> DW_AT_decl_line : 16
<127> DW_AT_type : <0xa8>
<12b> DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20)
但是如果我使用编译我得到的static
修饰符 -
<1><eb>: Abbrev Number: 13 (DW_TAG_subprogram)
<ec> DW_AT_external : 1
<ed> DW_AT_name : f
<ef> DW_AT_decl_file : 1
<f0> DW_AT_decl_line : 22
<f1> DW_AT_MIPS_linkage_name: (indirect string, offset: 0x24): _Z1fv
<f5> DW_AT_type : <0xa8>
<f9> DW_AT_low_pc : 0x0
<101> DW_AT_high_pc : 0xc
<109> DW_AT_frame_base : 0x0 (location list)
<10d> DW_AT_sibling : <0x137>
<2><111>: Abbrev Number: 14 (DW_TAG_lexical_block)
<112> DW_AT_low_pc : 0x4
<11a> DW_AT_high_pc : 0xa
<3><122>: Abbrev Number: 15 (DW_TAG_variable)
<123> DW_AT_name : j
<125> DW_AT_decl_file : 1
<126> DW_AT_decl_line : 23
<127> DW_AT_type : <0xa8>
<12b> DW_AT_location : 9 byte block: 3 20 0 0 0 0 0 0 0 (DW_OP_addr: 20)
据我所知,这些文件之间只有一个真正的区别 - 变量j的DW_AT_location
属性上的字节块大小不同(这就是DW_AT_sibling
属性的原因函数f的标签是不同的,所以我不算那个)。我认为这意味着静态,但我不知道如何。
答案 0 :(得分:2)
DWARF不会尝试描述变量的链接,只是它的类型,它的范围以及如何定位它。通过“范围”,我的意思是代码可以查看/访问仅在f()
的正文中的值,即使它是静态的。
fbreg
是作为堆栈框架基础的寄存器 - 最常用于x86_64,rbp
。局部变量包含在函数堆栈帧内的堆栈中(同样在x86_64上,通常在rbp
和rsp
之间)。堆栈向下增长,因此rbp
的值高于rsp
。
对于静态显示值为20的DW_AT_location
,我猜你在链接到可执行文件之前就抛弃了.o文件的DWARF。当这个链接到最终的可执行文件时,我希望链接器用静态的实际地址更新DW_AT_location
- 现在我认为它只是一个重定位占位符。
通常调试器使用可执行文件本身中的符号名称来扩充其全局/静态变量列表,因为用户可能希望检查f
的{{1}}变量,即使j
不在范围。静态的名称将以某种方式被破坏(不一定在C ++的修改意义上)(否则另一个函数f()
也会有g()
会发生冲突)所以调试器需要知道如何处理。
答案 1 :(得分:0)
我不是“DWARF”的专家,但我看到这些界限之间存在非常明显的差异:
<12b> DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20)
<12b> DW_AT_location : 9 byte block: 3 20 0 0 0 0 0 0 0 (DW_OP_addr: 20)
其中一个是fbreg: -20
- 所以“帧缓冲区重新表示,偏移-20”。
另一方面,我认为是指绝对地址(也许是数据段的32个字节?)