Использование GCC для создания читаемой сборки?

Мне было интересно, как использовать GCC в моем исходном файле C, чтобы сбросить мнемоническую версию машинного кода, чтобы я мог видеть, в что мой код компилируется. Вы можете сделать это с Java, но я не смог найти способ с GCC.

Я пытаюсь переписать метод C в сборке и посмотреть, как GCC делает это, было бы большой помощью.

9 ответов


если вы компилируете с символами отладки, вы можете использовать objdump произвести более читаемую разборку.

>objdump --help
[...]
-S, --source             Intermix source code with disassembly
-l, --line-numbers       Include line numbers and filenames in output

objdump -drwC -Mintel хорошо:

  • -r показывает имена символов при перемещениях (так что вы увидите puts на call инструкцию ниже)
  • -R показывает динамическое связывание перемещений / имен символов (полезно в общих библиотеках)
  • -C имена символов demangles C++
  • -w" широкий " режим: это не линия-обернуть машина-кода байт
  • -Mintel: используйте газ / binutils MASM-like .intel_syntax noprefix синтаксис вместо AT & T
  • -S: чередование исходных линий с разборкой.

вы могли бы поставить что-то вроде alias disas="objdump -drwCS -Mintel" в своем ~/.bashrc


пример:

> gcc -g -c test.c
> objdump -d -M intel -S test.o

test.o:     file format elf32-i386


Disassembly of section .text:

00000000 <main>:
#include <stdio.h>

int main(void)
{
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
   3:   83 e4 f0                and    esp,0xfffffff0
   6:   83 ec 10                sub    esp,0x10
    puts("test");
   9:   c7 04 24 00 00 00 00    mov    DWORD PTR [esp],0x0
  10:   e8 fc ff ff ff          call   11 <main+0x11>

    return 0;
  15:   b8 00 00 00 00          mov    eax,0x0
}
  1a:   c9                      leave  
  1b:   c3                      ret

Я хотел бы добавить к этим ответам, что если вы дадите gcc флаг -fverbose-asm, ассемблер, который он испускает, будет намного яснее читать.


используйте переключатель-S (Примечание: capital S) в GCC, и он выдаст код сборки в файл с a .расширение С. Например, следующая команда:

gcc -O2 -S foo.c

оставит сгенерированный код сборки в файле foo.s.

вырвано прямо из http://www.delorie.com/djgpp/v2faq/faq8_20.html (но удаление ошибочных -c)


С помощью -S переключение на GCC в системах на базе x86 создает дамп синтаксиса AT&T по умолчанию, который может быть указан с помощью -masm=att переключатель, вот так:

gcc -S -masm=att code.c

тогда как если вы хотите создать дамп в синтаксисе Intel, вы можете использовать -masm=intel переключатель, вот так:

gcc -S -masm=intel code.c

(оба производят свалки code.c в их различный синтаксис, в файл code.s соответственно)

для того чтобы произвести подобные влияния с objdump, вы хотите использовать --disassembler-options= intel/att switch, пример (с дампами кода для иллюстрации различий в синтаксисе):

 $ objdump -d --disassembler-options=att code.c
 080483c4 <main>:
 80483c4:   8d 4c 24 04             lea    0x4(%esp),%ecx
 80483c8:   83 e4 f0                and    xfffffff0,%esp
 80483cb:   ff 71 fc                pushl  -0x4(%ecx)
 80483ce:   55                      push   %ebp
 80483cf:   89 e5                   mov    %esp,%ebp
 80483d1:   51                      push   %ecx
 80483d2:   83 ec 04                sub    x4,%esp
 80483d5:   c7 04 24 b0 84 04 08    movl   x80484b0,(%esp)
 80483dc:   e8 13 ff ff ff          call   80482f4 <puts@plt>
 80483e1:   b8 00 00 00 00          mov    x0,%eax
 80483e6:   83 c4 04                add    x4,%esp 
 80483e9:   59                      pop    %ecx
 80483ea:   5d                      pop    %ebp
 80483eb:   8d 61 fc                lea    -0x4(%ecx),%esp
 80483ee:   c3                      ret
 80483ef:   90                      nop

и

$ objdump -d --disassembler-options=intel code.c
 080483c4 <main>:
 80483c4:   8d 4c 24 04             lea    ecx,[esp+0x4]
 80483c8:   83 e4 f0                and    esp,0xfffffff0
 80483cb:   ff 71 fc                push   DWORD PTR [ecx-0x4]
 80483ce:   55                      push   ebp
 80483cf:   89 e5                   mov    ebp,esp
 80483d1:   51                      push   ecx
 80483d2:   83 ec 04                sub    esp,0x4
 80483d5:   c7 04 24 b0 84 04 08    mov    DWORD PTR [esp],0x80484b0
 80483dc:   e8 13 ff ff ff          call   80482f4 <puts@plt>
 80483e1:   b8 00 00 00 00          mov    eax,0x0
 80483e6:   83 c4 04                add    esp,0x4
 80483e9:   59                      pop    ecx
 80483ea:   5d                      pop    ebp
 80483eb:   8d 61 fc                lea    esp,[ecx-0x4]
 80483ee:   c3                      ret    
 80483ef:   90                      nop

godbolt - очень полезный инструмент, в их списке есть только компиляторы C++, но вы можете использовать -x c флаг, чтобы получить его рассматривать код как C. Затем он будет генерировать список сборок для вашего кода бок о бок, и вы можете использовать Colourise возможность генерировать цветные полосы, чтобы визуально указать, какой исходный код сопоставляется с сгенерированной сборкой. Например, следующий код:

#include <stdio.h>

void func()
{
  printf( "hello world\n" ) ;
}

используя следующую командную строку:

-x c -std=c99 -O3

и Colourise будет генерировать следующее:

enter image description here


ты gcc -S -fverbose-asm -O source.c затем посмотрите в сгенерированный source.s файл ассемблер ?

сгенерированный код ассемблера переходит в source.s (вы можете переопределить это с помощью -o ассемблер-имя файла ); the -fverbose-asm опция просит компилятор выдать некоторые комментарии ассемблера, "объясняющие" сгенерированный код ассемблера. The -O опция просит компилятор немного оптимизировать (он может оптимизировать больше с помощью -O2 или -O3).

если вы хотите понять что?!--8--> делает попытку передает -fdump-tree-all но будьте осторожны: вы получите сотни файлов дампа.

кстати, GCC является расширяемым через плагины или с расплавить (язык домена высокого уровня для расширения GCC).


вы можете использовать gdb для этого, как objdump.

этот отрывок взят из http://sources.redhat.com/gdb/current/onlinedocs/gdb_9.html#SEC64


вот пример, показывающий смешанный источник + сборка для Intel x86:

  (gdb) disas /m main
Dump of assembler code for function main:
5       {
0x08048330 :    push   %ebp
0x08048331 :    mov    %esp,%ebp
0x08048333 :    sub    x8,%esp
0x08048336 :    and    xfffffff0,%esp
0x08048339 :    sub    x10,%esp

6         printf ("Hello.\n");
0x0804833c :   movl   x8048440,(%esp)
0x08048343 :   call   0x8048284 

7         return 0;
8       }
0x08048348 :   mov    x0,%eax
0x0804834d :   leave
0x0804834e :   ret

End of assembler dump.

используйте переключатель-S (Примечание: capital S) в GCC, и он выдаст код сборки в файл с a .расширение С. Например, следующая команда:

ССЗ -О2 -с -с ФОО.c


Я не дал выстрел в gcc, но в случае g++. Команда ниже работает для меня. - g для сборки отладки и-Wa, - adhln передается ассемблеру для листинга с исходным кодом

g++ - g-Wa, - adhln src.cpp