DWARF - Как найти адреса конца пролога/начального эпилога функций в заданном двоичном файле?

У меня есть двоичный файл ARM, для которого мне нужно точно определить, по каким адресам заканчиваются прологи его функций и начинаются эпилоги. Другими словами, мне нужны границы тел функций. Например, если у меня есть функция, сборка которой выглядит примерно так:

0x00000320 <+0>:    push    {r7, lr}
0x00000322 <+2>:    sub sp, #16
0x00000324 <+4>:    add r7, sp, #0
0x00000326 <+6>:    str r0, [r7, #4]
0x00000328 <+8>: (Function body starts here)
...
0x0000034c <+44>:   (Function body ends here)
0x0000034e <+46>:   mov sp, r7
0x00000350 <+48>:   pop {r7, pc}

Мне нужен способ быстро найти 0x00000326 и 0x0000034e (конец пролога/начало эпилога) или 0x00000328 и 0x0000034c (начало/конец тела функции), используя что-то вроде readelf или objdump. Просто разобрать его и проверить код не получится (в идеале я бы использовал скрипт для анализа вывода readelf или любой другой программы, которую я использую для получения информации о DWARF).

Согласно стандарту DWARF 4, раздел .debug_line предположительно содержит информацию о номере строки, которая включает «prologue_end» и «epilogue_begin», что мне и нужно. Однако вывод arm-linux-readelf --debug-dump=rawline,decodedline не дает мне этой информации.

Я компилирую, используя gcc 4.8.2 с флагом -ggdb3.

РЕДАКТИРОВАТЬ: Еще немного информации: и objdump, и readelf показывают мне что-то вроде этого:

Line Number Statements:
[0x00000074]  Extended opcode 2: set Address to 0x100
[0x0000007b]  Advance Line by 302 to 303
[0x0000007e]  Copy
[0x0000007f]  Special opcode 34: advance Address by 4 to 0x104 and Line by 1 to 304
[0x00000080]  Special opcode 34: advance Address by 4 to 0x108 and Line by 1 to 305
[0x00000081]  Special opcode 37: advance Address by 4 to 0x10c and Line by 4 to 309
[0x00000082]  Special opcode 34: advance Address by 4 to 0x110 and Line by 1 to 310
[0x00000083]  Special opcode 20: advance Address by 2 to 0x112 and Line by 1 to 311
[0x00000084]  Special opcode 37: advance Address by 4 to 0x116 and Line by 4 to 315
[0x00000085]  Special opcode 34: advance Address by 4 to 0x11a and Line by 1 to 316
[0x00000086]  Advance Line by -13 to 303
[0x00000088]  Special opcode 19: advance Address by 2 to 0x11c and Line by 0 to 303
[0x00000089]  Special opcode 34: advance Address by 4 to 0x120 and Line by 1 to 304
[0x0000008a]  Advance PC by 4 to 0x124
[0x0000008c]  Extended opcode 1: End of Sequence

Глядя на источник binutils dwarf.c, кажется, что он должен печатать что-то вроде «Set prologue_end to true» и «Set epilogue_begin to true» в дампе информации о строке. Однако все коды операций кажутся специальными, а не стандартными.


person Martin    schedule 18.09.2014    source источник
comment
Для чего стоит скомпилировать с clang-3.6 -gdwarf-4 -g3, я получаю Set prologue_end to true DWARF info: GCC, кажется, не может сгенерировать это (пока?).   -  person ysdx    schedule 08.12.2014


Ответы (2)


Это очень запоздалый ответ, но: если вы используете LLVM, вы можете получить эту информацию из конечного автомата линейной программы DWARF: LLVM выдает DW_LNS_set_prologue_end и DW_LNS_set_epilogue_begin в качестве флагов для каждой записи линейной программы.

GCC, по-видимому, (пока) не поддерживает эти атрибуты, поэтому вполне вероятно, что окружающие его инструменты (например, readelf и gdb) тоже не поддерживают. Но вы должны иметь возможность анализировать прологи и эпилоги с помощью pyelftools.

person yossarian    schedule 28.04.2021

Пытаться

readelf -wi

И найдите DW_AT_low_pc и DW_AT_high_pc для подпрограммы, которую вы ищете.

Спецификация DWARF говорит:

Запись подпрограммы может иметь либо пару атрибутов DW_AT_low_pc и DW_AT_high_pc, либо атрибут DW_AT_ranges, значения которого кодируют непрерывные или несмежные диапазоны адресов, соответственно, машинных инструкций, сгенерированных для подпрограммы (см. Раздел 2.17).

Если я правильно помню, DW_AT_low_pc — это адрес сразу после пролога, а DW_AT_high_pc — последний адрес перед эпилогом.

Не беспокойтесь о том, что коды операций являются «особыми», это просто означает, что они не принимают аргументы для экономии места в программе кодирования номеров строк.

person Torleif    schedule 28.09.2014
comment
К сожалению, DW_AT_low_pc, по-видимому, соответствует адресу первой инструкции подпрограммы (то есть первой инструкции пролога), а DW_AT_high_pc, по-видимому, является смещением инструкции, следующей за последней инструкцией эпилога. - person Martin; 29.09.2014