如何解析DW_OP_call_frame_cfa?
How to parse DW_OP_call_frame_cfa?
我正在尝试使用 libdwarf 从 C (x86_64) 代码中获取变量位置,但即使关闭了优化 (-O0),GCC 也会生成相对于 DW_OP_call_frame_cfa
的框架基址。反过来,clang 使用 DW_OP_reg6
,它指向 x86_64 ABI 中的 rbp。
我已经阅读了 DWARF-4 标准,但我不知道如何从堆栈或基指针获取实际地址。我在这里也遇到了类似的问题What do I do with DW_OP_call_frame_cfa,但是没有成功。
像这样的简单代码:
int main()
{
int va = 1;
int vb = 2;
va = va + vb;
return (va);
}
将在 dwarfdump 中产生以下输出:
< 1><0x0000002d> DW_TAG_subprogram
DW_AT_external yes(1)
DW_AT_name main
DW_AT_decl_file 0x00000001 file.c
DW_AT_decl_line 0x00000001
DW_AT_type <0x00000069>
DW_AT_low_pc 0x00400620
DW_AT_high_pc <offset-from-lowpc>29
DW_AT_frame_base len 0x0001: 9c: DW_OP_call_frame_cfa
DW_AT_GNU_all_call_sites yes(1)
DW_AT_sibling <0x00000069>
< 2><0x0000004e> DW_TAG_variable
DW_AT_name va
DW_AT_decl_file 0x00000001 file.c
DW_AT_decl_line 0x00000003
DW_AT_type <0x00000069>
DW_AT_location len 0x0002: 916c: DW_OP_fbreg -20
< 2><0x0000005b> DW_TAG_variable
DW_AT_name vb
DW_AT_decl_file 0x00000001 file.c
DW_AT_decl_line 0x00000004
DW_AT_type <0x00000069>
DW_AT_location len 0x0002: 9168: DW_OP_fbreg -24
以及readelf -wf file
中的以下信息
00000070 000000000000001c 00000044 FDE cie=00000030 pc=0000000000400620..000000000040063d
DW_CFA_advance_loc: 1 to 0000000000400621
DW_CFA_def_cfa_offset: 16
DW_CFA_offset: r6 (rbp) at cfa-16
DW_CFA_advance_loc: 3 to 0000000000400624
DW_CFA_def_cfa_register: r6 (rbp)
DW_CFA_advance_loc: 24 to 000000000040063c
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
根据我的阅读,我必须实现一个最小堆栈机器,但我什至不知道如何手动解析它。
有没有办法强制 GCC 不使用 DW_OP_call_frame_cfa 而使用简单的寄存器,或者我真的需要解释框架信息吗?如果是,怎么做?
我不太熟悉 DWARF 或一般的调试信息格式,但只是回答
Is there a way to force GCC to not use the DW_OP_call_frame_cfa
部分,我从 GCC 源中的 DW_OP_call_frame_cfa
grepping 中发现 -gdwarf-2
gcc 开关使它产生这个:
DW_AT_frame_base <loclist at offset 0x00000000 with 4 entries follows>
[ 0]< offset pair low-off : 0x00000000 addr 0x00001119 high-off 0x00000001 addr 0x0000111a>DW_OP_breg7+8
[ 1]< offset pair low-off : 0x00000001 addr 0x0000111a high-off 0x00000004 addr 0x0000111d>DW_OP_breg7+16
[ 2]< offset pair low-off : 0x00000004 addr 0x0000111d high-off 0x0000001c addr 0x00001135>DW_OP_breg6+16
[ 3]< offset pair low-off : 0x0000001c addr 0x00001135 high-off 0x0000001d addr 0x00001136>DW_OP_breg7+8
不确定切换到 DWARF 版本 2 是否适合您。
我正在尝试使用 libdwarf 从 C (x86_64) 代码中获取变量位置,但即使关闭了优化 (-O0),GCC 也会生成相对于 DW_OP_call_frame_cfa
的框架基址。反过来,clang 使用 DW_OP_reg6
,它指向 x86_64 ABI 中的 rbp。
我已经阅读了 DWARF-4 标准,但我不知道如何从堆栈或基指针获取实际地址。我在这里也遇到了类似的问题What do I do with DW_OP_call_frame_cfa,但是没有成功。
像这样的简单代码:
int main()
{
int va = 1;
int vb = 2;
va = va + vb;
return (va);
}
将在 dwarfdump 中产生以下输出:
< 1><0x0000002d> DW_TAG_subprogram
DW_AT_external yes(1)
DW_AT_name main
DW_AT_decl_file 0x00000001 file.c
DW_AT_decl_line 0x00000001
DW_AT_type <0x00000069>
DW_AT_low_pc 0x00400620
DW_AT_high_pc <offset-from-lowpc>29
DW_AT_frame_base len 0x0001: 9c: DW_OP_call_frame_cfa
DW_AT_GNU_all_call_sites yes(1)
DW_AT_sibling <0x00000069>
< 2><0x0000004e> DW_TAG_variable
DW_AT_name va
DW_AT_decl_file 0x00000001 file.c
DW_AT_decl_line 0x00000003
DW_AT_type <0x00000069>
DW_AT_location len 0x0002: 916c: DW_OP_fbreg -20
< 2><0x0000005b> DW_TAG_variable
DW_AT_name vb
DW_AT_decl_file 0x00000001 file.c
DW_AT_decl_line 0x00000004
DW_AT_type <0x00000069>
DW_AT_location len 0x0002: 9168: DW_OP_fbreg -24
以及readelf -wf file
00000070 000000000000001c 00000044 FDE cie=00000030 pc=0000000000400620..000000000040063d
DW_CFA_advance_loc: 1 to 0000000000400621
DW_CFA_def_cfa_offset: 16
DW_CFA_offset: r6 (rbp) at cfa-16
DW_CFA_advance_loc: 3 to 0000000000400624
DW_CFA_def_cfa_register: r6 (rbp)
DW_CFA_advance_loc: 24 to 000000000040063c
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
根据我的阅读,我必须实现一个最小堆栈机器,但我什至不知道如何手动解析它。
有没有办法强制 GCC 不使用 DW_OP_call_frame_cfa 而使用简单的寄存器,或者我真的需要解释框架信息吗?如果是,怎么做?
我不太熟悉 DWARF 或一般的调试信息格式,但只是回答
Is there a way to force GCC to not use the DW_OP_call_frame_cfa
部分,我从 GCC 源中的 DW_OP_call_frame_cfa
grepping 中发现 -gdwarf-2
gcc 开关使它产生这个:
DW_AT_frame_base <loclist at offset 0x00000000 with 4 entries follows>
[ 0]< offset pair low-off : 0x00000000 addr 0x00001119 high-off 0x00000001 addr 0x0000111a>DW_OP_breg7+8
[ 1]< offset pair low-off : 0x00000001 addr 0x0000111a high-off 0x00000004 addr 0x0000111d>DW_OP_breg7+16
[ 2]< offset pair low-off : 0x00000004 addr 0x0000111d high-off 0x0000001c addr 0x00001135>DW_OP_breg6+16
[ 3]< offset pair low-off : 0x0000001c addr 0x00001135 high-off 0x0000001d addr 0x00001136>DW_OP_breg7+8
不确定切换到 DWARF 版本 2 是否适合您。