DW_AT_location DW_OP_fbreg DW_OP_addr

时间:2017-07-25 06:10:52

标签: dwarf

如何计算DW_AT_location的值可以有人帮忙吗? 我还想知道何时使用此属性的DW_OP_addrDW_OP_fbreg

    .uleb128 0x2    # (DIE (0x75) DW_TAG_variable)
    .ascii "c\0"    # DW_AT_name
    .byte   0x1     # DW_AT_decl_file (DW_TAG_const_type_1.c)
    .byte   0x5     # DW_AT_decl_line
    .long   0x88    # DW_AT_type
                    # DW_AT_external
    .uleb128 0x9    # DW_AT_location
    .byte   0x3     # DW_OP_addr

.quad c

    .uleb128 0x6    # (DIE (0x6d) DW_TAG_variable)
    .ascii "obj\0"  # DW_AT_name
    .byte   0x1     # DW_AT_decl_file (DW_TAG_base_type_1.c)
    .byte   0x5     # DW_AT_decl_line
    .long   0x84    # DW_AT_type
    .uleb128 0x3    # DW_AT_location
    .byte   0x91    # DW_OP_fbreg
    .sleb128 -96

1 个答案:

答案 0 :(得分:1)

您的问题中没有足够的信息来提供完整的答案。

在每种情况下,看起来好像DW_AT_location已经用DW_FORM_exprloc形式表达,这是一个ULEB128编码的长度,后跟相应的字节数,在这种情况下构成一个用作位置描述的DWARF表达式。

在第一种情况下,长度为9,但只显示了第一个字节,即DW_OP_addrDWARF 4标准包含以下有用的解释:

  

2.5.1一般操作

     

每个常规操作代表简单堆栈计算机上的后缀操作。堆栈的每个元素都是目标计算机上的地址大小。 “执行”DWARF表达式后堆栈顶部的值被视为结果(对象的地址,数组绑定的值,动态字符串的长度,所需的值本身等等) )。

     

2.5.1.1文字编码

     

以下操作都将值推送到DWARF堆栈。如果其中一个操作中的常量值大于可以存储在单个堆栈元素中的值,则该值将被截断为元素大小,并且低位将被压入堆栈。

     
      
  1. DW_OP_addr
  2.         

    DW_OP_addr操作有一个操作数,用于编码机器地址,其大小是目标机器上地址的大小。

因此,在应用任何重定位之前,第一个示例结束后的八个字节将是变量c的地址。

第二个例子也不完整。在SLEB128中对十进制-96进行编码会消耗两个字节0xa0 0x7f,因此您拥有整个位置描述,即DW_OP_fbreg(-96)。但是,正如标准所解释的那样:

  

2.5.1.2基于寄存器的寻址

     

以下操作将值压入堆栈,这是将寄存器内容添加到给定带符号偏移量的结果。

     
      
  1. DW_OP_fbreg
  2.         

    DW_OP_fbreg操作提供与当前函数的DW_AT_frame_base属性中的位置描述指定的地址的签名LEB128偏移量。 (这通常是一个“堆栈指针”寄存器加上或减去一些偏移。在更复杂的系统上,它可能是一个位置列表,根据PC更改时堆栈指针的变化调整偏移量。)

因此,您需要为拥有obj的函数找到DIE并评估其DW_AT_frame_baseobj存储在该地址下方的九十六个字节。

相关问题