2013-04-30 2 views
6

Я изучаю, как файл C скомпилирован в машинный код. Я знаю, что могу сгенерировать сборку с gcc с флагом -S, однако он также дает много кода, чтобы сделать с main() и printf(), что меня сейчас не интересует.Есть ли способ вывести сборку одной функции в отдельности?

Есть ли способ, чтобы получить gcc или clang к «компилировать» функцию в изоляции и вывода сборки?

I.e. получить сборку для следующего с в изоляции:

int add(int a, int b) { 
    return a + b; 
} 
+0

Некоторые IDE позволят вам установить точку останова и просмотреть код сборки, сгенерированный этой функцией. Это называется * разборным окном *. Это должно делать то, что вы ищете - вы используете IDE? – Aaron

+0

Я предпочитаю компилировать (с оптимизацией), а затем разбирать, вы должны понимать, что компилятор оставит несколько инструкций неполными для внешних адресов и т. Д., Но читать IMO легче, чем использовать -S. gcc -O2 -c hello.c -o hello.o, objdump -D hello.o –

+3

Перейдите сюда: http://gcc.godbolt.org/ вставьте функцию, выберите компилятор, очень полезно. – harold

ответ

7

Есть два способа сделать это для конкретного объектного файла:

  1. -ffunction-sections варианта gcc инструктирует его, чтобы создать раздел в отдельного ELF для каждой функции в Исходный_файле компилируется.
  2. Таблица символов содержит название раздела, начальный адрес и размер заданной функции; который может быть подан в objdump через аргументы --start-address/--stop-address.

Первый пример:

$ readelf -S t.o | grep ' .text.' 
    [ 1] .text    PROGBITS   0000000000000000 00000040 
    [ 4] .text.foo   PROGBITS   0000000000000000 00000040 
    [ 6] .text.bar   PROGBITS   0000000000000000 00000060 
    [ 9] .text.foo2  PROGBITS   0000000000000000 000000c0 
    [11] .text.munch  PROGBITS   0000000000000000 00000110 
    [14] .text.startup.mai PROGBITS   0000000000000000 00000180

Это было составлено с -ffunction-sections и есть четыре функции, foo(), bar(), foo2() и munch() в моем файле объекта. Я могу разобрать их по отдельности, так как:

$ objdump -w -d --section=.text.foo t.o 

t.o:  file format elf64-x86-64 

Disassembly of section .text.foo: 

0000000000000000 <foo>: 
    0: 48 83 ec 08    sub $0x8,%rsp 
    4: 8b 3d 00 00 00 00  mov 0(%rip),%edi  # a <foo+0xa> 
    a: 31 f6     xor %esi,%esi 
    c: 31 c0     xor %eax,%eax 
    e: e8 00 00 00 00   callq 13 <foo+0x13> 
    13: 85 c0     test %eax,%eax 
    15: 75 01     jne 18 <foo+0x18> 
    17: 90      nop 
    18: 48 83 c4 08    add $0x8,%rsp 
    1c: c3      retq

Другой вариант может быть использован, как это (nm отвалов записей таблицы символов):

$ nm -f sysv t.o | grep bar 
bar  |0000000000000020| T | FUNC|0000000000000026|  |.text 
$ objdump -w -d --start-address=0x20 --stop-address=0x46 t.o --section=.text 

t.o:  file format elf64-x86-64 

Disassembly of section .text: 

0000000000000020 <bar>: 
    20: 48 83 ec 08    sub $0x8,%rsp 
    24: 8b 3d 00 00 00 00  mov 0(%rip),%edi  # 2a <bar+0xa> 
    2a: 31 f6     xor %esi,%esi 
    2c: 31 c0     xor %eax,%eax 
    2e: e8 00 00 00 00   callq 33 <bar+0x13> 
    33: 85 c0     test %eax,%eax 
    35: 75 01     jne 38 <bar+0x18> 
    37: 90      nop 
    38: bf 3f 00 00 00   mov $0x3f,%edi 
    3d: 48 83 c4 08    add $0x8,%rsp 
    41: e9 00 00 00 00   jmpq 46 <bar+0x26>

В этом случае -ffunction-sections вариант не имеет поэтому начальное смещение функции не равно нулю, и оно не находится в отдельном разделе (но в .text).

Остерегайтесь, хотя при разборке объектных файлов ...

Это не точно то, что вы хотите, потому что, для объектных файлов, то call целей (а также адрес глобальных переменных) не разрешены - вы не видите здесь, что foo звонит printf, потому что разрешение этого на двоичном уровне происходит только во время соединения. Однако источник сборки имел бы call printf.Информация о том, что это callq на самом деле равна printf, находится в объектном файле, но отдельно от кода (находится в так называемом разделе relocation, в котором перечислены местоположения в объектном файле, «пропатченные» компоновщиком); дизассемблер не может это решить.

+0

Я вижу, просто fyi для кого-либо еще, вы можете использовать «gcc -ffunction-sections -c test.c» для компиляции исходного файла в файл объекта. Благодаря ~ – ashleysmithgpu

0

Лучший способ пойти бы скопировать вашу функцию в одном temp.c C файл и скомпилировать его с -c флагом, как это: gcc -c -S temp.c -o temp.s

Он должен производить более сжатый код сборки без какого-либо другого отвлечения (кроме верхнего и нижнего колонтитула).

Смежные вопросы