如何计算DW_AT_location的值可以有人帮忙吗?
我还想知道何时使用此属性的DW_OP_addr
和DW_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
.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
答案 0 :(得分:1)
您的问题中没有足够的信息来提供完整的答案。
在每种情况下,看起来好像DW_AT_location
已经用DW_FORM_exprloc
形式表达,这是一个ULEB128编码的长度,后跟相应的字节数,在这种情况下构成一个用作位置描述的DWARF表达式。
在第一种情况下,长度为9,但只显示了第一个字节,即DW_OP_addr
。 DWARF 4标准包含以下有用的解释:
2.5.1一般操作
每个常规操作代表简单堆栈计算机上的后缀操作。堆栈的每个元素都是目标计算机上的地址大小。 “执行”DWARF表达式后堆栈顶部的值被视为结果(对象的地址,数组绑定的值,动态字符串的长度,所需的值本身等等) )。
2.5.1.1文字编码
以下操作都将值推送到DWARF堆栈。如果其中一个操作中的常量值大于可以存储在单个堆栈元素中的值,则该值将被截断为元素大小,并且低位将被压入堆栈。
- DW_OP_addr
醇>DW_OP_addr操作有一个操作数,用于编码机器地址,其大小是目标机器上地址的大小。
因此,在应用任何重定位之前,第一个示例结束后的八个字节将是变量c
的地址。
第二个例子也不完整。在SLEB128中对十进制-96进行编码会消耗两个字节0xa0
0x7f
,因此您拥有整个位置描述,即DW_OP_fbreg(-96)
。但是,正如标准所解释的那样:
2.5.1.2基于寄存器的寻址
以下操作将值压入堆栈,这是将寄存器内容添加到给定带符号偏移量的结果。
- DW_OP_fbreg
醇>DW_OP_fbreg操作提供与当前函数的DW_AT_frame_base属性中的位置描述指定的地址的签名LEB128偏移量。 (这通常是一个“堆栈指针”寄存器加上或减去一些偏移。在更复杂的系统上,它可能是一个位置列表,根据PC更改时堆栈指针的变化调整偏移量。)
因此,您需要为拥有obj
的函数找到DIE并评估其DW_AT_frame_base
。 obj
存储在该地址下方的九十六个字节。