如何使用dwarf确定非成员函数中的局部静态变量

时间:2013-06-28 23:29:47

标签: c++ static local-variables dwarf non-member-functions

我试图用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的标签是不同的,所以我不算那个)。我认为这意味着静态,但我不知道如何。

2 个答案:

答案 0 :(得分:2)

DWARF不会尝试描述变量的链接,只是它的类型,它的范围以及如何定位它。通过“范围”,我的意思是代码可以查看/访问仅在f()的正文中的值,即使它是静态的。

fbreg是作为堆栈框架基础的寄存器 - 最常用于x86_64,rbp。局部变量包含在函数堆栈帧内的堆栈中(同样在x86_64上,通常在rbprsp之间)。堆栈向下增长,因此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个字节?)