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

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

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

Ответ 1

Если вы компилируете символы отладки, вы можете использовать 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 отображает имена символов C++
  • -w является "широким" режимом: он не строит -w рэп -C ode bytes
  • -Mintel: используйте GAS/binutils MASM-like .intel_syntax noprefix синтаксис .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

Ответ 2

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

Ответ 3

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

gcc -O2 -S foo.c

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

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

Ответ 4

Использование переключателя -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, пример (с --disassembler-options= кода для иллюстрации различий в синтаксисе):

 $ objdump -d --disassembler-options=att code.c
 080483c4 <main>:
 80483c4:   8d 4c 24 04             lea    0x4(%esp),%ecx
 80483c8:   83 e4 f0                and    $0xfffffff0,%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    $0x4,%esp
 80483d5:   c7 04 24 b0 84 04 08    movl   $0x80484b0,(%esp)
 80483dc:   e8 13 ff ff ff          call   80482f4 <[email protected]>
 80483e1:   b8 00 00 00 00          mov    $0x0,%eax
 80483e6:   83 c4 04                add    $0x4,%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 <[email protected]>
 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

Ответ 5

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

#include <stdio.h>

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

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

-x c -std=c99 -O3

и Colourise генерируют следующее:

enter image description here

Ответ 6

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

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

Если вы хотите понять, что делает gcc, попробуйте передать -fdump-tree-all но будьте осторожны: вы получите сотни файлов дампа.

Кстати, GCC можно расширять с помощью плагинов или с помощью MELT (высокоуровневый домен-специфический язык для расширения GCC; от которого я отказался в 2017 году)

Ответ 7

Вы можете использовать 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    $0x8,%esp
0x08048336 :    and    $0xfffffff0,%esp
0x08048339 :    sub    $0x10,%esp

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

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

End of assembler dump.

Ответ 8

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

gcc -O2 -S -c foo.c

Ответ 9

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

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