1

我试图使用 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)

现在据我所知,这些文件之间只有一个真正的区别——DW_AT_location变量 j 的属性上的字节块大小不同(这就是为什么DW_AT_sibling函数 f 的标签中的属性不同,所以我不算)。我认为这在某种程度上意味着静态,但我不知道如何。

4

2 回答 2

2

DWARF 不会尝试描述变量的链接,只描述它的类型、作用域以及如何定位它。“范围”是指当代码可以看到/访问仅在 的主体内的值时f(),即使它是静态的。

fbreg是作为堆栈帧基础的寄存器——最常见于 x86_64, rbp. 局部变量包含在函数堆栈框架内的堆栈中(同样在 x86_64 上,通常在rbp和之间rsp)。堆栈向下增长,因此rbp具有比 更高的值rsp

至于DW_AT_location您的静态显示值为 20,我猜您在链接到可执行文件之前转储了 .o 文件的 DWARF。当它链接到最终的可执行文件时,我希望链接器用DW_AT_location静态的实际地址更新它 - 现在我打赌它只是一个重定位占位符。

通常调试器使用可执行文件本身中的符号名称来扩充其全局/静态变量列表,因为即使超出范围,用户也可能想要检查f's变量。静态名称会以某种方式被破坏(不一定是 C++ 意义上的重整)(否则另一个函数也会发生冲突),因此调试器需要知道如何处理它。jf()g()static j

于 2013-06-29T08:30:10.530 回答
0

I'm no expert on "DWARF", but I see a very distinct difference between these lines:

<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)

One of the is fbreg: -20 - so "frame buffer regeister, offset -20".

The other, I presume referring to an absolute address (32 bytes into the DATA segment, perhaps?)

于 2013-06-28T23:42:13.303 回答