如何利用libdwarf信息获取局部变量的内存位置
问题解答
核心错误原因
你错误地将整个函数FDE中的CFI指令按顺序全部执行,包括函数末尾epilogue阶段的规则,但my_local的生命周期仅对应函数prologue完成后的主体代码段,此时的CFA状态和你计算的完全不同。
正确计算流程
1. 定位变量对应的CFI生效区间
do_stuff的FDE覆盖pc范围0x1135~0x1178,其中:
- 前两条CFI指令(
DW_CFA_advance_loc:1+DW_CFA_def_cfa_offset:16+DW_CFA_offset: r6 (rbp) at cfa-16)对应函数入口push rbp执行后的状态。 - 第三条
DW_CFA_advance_loc:3+DW_CFA_def_cfa_register: r6 (rbp)对应mov rbp, rsp执行后的状态,这之后直到0x1177的代码段就是my_local存在的区间,此时CFI规则固定为:CFA = rbp + 16(DW_CFA_def_cfa_register仅修改CFA的基寄存器为rbp,之前设置的offset=16保持不变)。
2. 计算变量地址
my_local的DW_AT_location是DW_OP_fbreg: -24(十进制,即-0x18),变量地址计算公式为:
&my_local = CFA + 偏移量
代入CFA规则:
&my_local = (rbp + 0x10) + (-0x18) = rbp - 0x8
(注:如果实际汇编中my_local是-0x14(%rbp),说明你获取的DWARF偏移值可能有误,比如应为-0x24(十进制-36),此时计算结果会完全匹配:(rbp+0x10)-0x24=rbp-0x14)
避免手动计算的正确姿势
手动解析CFI极易出错,推荐直接使用libdwarf的API完成计算:
- 调用
dwarf_get_fde_list获取目标程序的FDE列表。 - 用
dwarf_find_fde定位到my_local所在代码段对应的FDE。 - 调用
dwarf_cfa计算该pc地址对应的实时CFA值。 - 解析变量的
DW_AT_location表达式(此处为DW_OP_fbreg加偏移),将CFA与偏移相加得到变量的内存地址。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

