【问题标题】:How to parse DW_OP_call_frame_cfa?如何解析 DW_OP_call_frame_cfa?
【发布时间】:2019-05-19 02:06:45
【问题描述】:

我正在尝试使用 libdwarf 从 C (x86_64) 代码中获取变量位置,但 GCC 即使关闭优化 (-O0) 也会从 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 并使用简单的寄存器,还是我真的需要解释帧信息?如果有,怎么做?

【问题讨论】:

    标签: c gcc clang dwarf


    【解决方案1】:

    我对 DWARF 或一般调试信息格式并不十分熟悉,但我只想回答

    有没有办法强制 GCC 不使用 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 是否适合您。

    【讨论】:

    • 很高兴看到使用 DWARF-2 GCC 使用位置列表,这将比尝试处理 DW_OP_call_frame_cfa 容易得多,对于我的需要,版本 2 似乎很适合我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 2013-01-31
    • 2012-09-29
    • 2016-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多