Как разобрать DW_OP_call_frame_cfa? - PullRequest
0 голосов
/ 19 мая 2019

Я пытаюсь получить местоположение переменных из кода C (x86_64) с помощью libdwarf, но GCC даже с отключенной оптимизацией (-O0) генерирует базу кадров относительно DW_OP_call_frame_cfa.В свою очередь, clang использует DW_OP_reg6, что указывает на rbp в x86_64 ABI.

Я прочитал стандарт DWARF-4, но не могу понять, как получить фактический адрес относительно стека или базыуказатель.Я также сталкивался с подобным вопросом Что мне делать здесь с 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 и использовать простой регистр, или мне действительно нужно интерпретировать информацию кадра?и если да, то как?

1 Ответ

1 голос
/ 21 мая 2019

Я не очень знаком с DWARF или форматами отладочной информации в целом, но чтобы ответить только на

Есть ли способ заставить GCC не использовать DW_OP_call_frame_cfa

часть, я обнаружил из опроса DW_OP_call_frame_cfa в источниках GCC, что переключатель -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

Не уверен, подходит ли переключение на версию 2 DWARFВы, хотя.

...