Есть ли способ получить GCC для вывода сырых двоичных файлов? - PullRequest
29 голосов
/ 30 октября 2009

Существует ли набор параметров командной строки, которые убедят gcc создать плоский двоичный файл из автономного исходного файла? Например, предположим, что содержимое файла foo.c равно

static int f(int x)
{
  int y = x*x;
  return y+2;
}

Нет внешних ссылок, ничего для экспорта в компоновщик. Я хотел бы получить небольшой файл, содержащий только машинные инструкции для этой функции, без какого-либо другого оформления. Вроде как (DOS) .COM файл, кроме 32-битного защищенного режима.

Ответы [ 4 ]

34 голосов
/ 30 октября 2009

Попробуйте это:

$ cc -c test.c
$ objcopy -O binary test.o binfile

Вы можете убедиться, что это правильно, набрав objdump:

$ objdump -d test.o 
test.o:     file format pe-i386


Disassembly of section .text:

00000000 <_f>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 04                sub    $0x4,%esp
   6:   8b 45 08                mov    0x8(%ebp),%eax
   9:   0f af 45 08             imul   0x8(%ebp),%eax
   d:   89 45 fc                mov    %eax,-0x4(%ebp)
  10:   8b 45 fc                mov    -0x4(%ebp),%eax
  13:   83 c0 02                add    $0x2,%eax
  16:   c9                      leave  
  17:   c3                      ret  

И сравните с двоичным файлом:

$ hexdump -C binfile 
00000000  55 89 e5 83 ec 04 8b 45  08 0f af 45 08 89 45 fc  |U......E...E..E.|
00000010  8b 45 fc 83 c0 02 c9 c3                           |.E......|
00000018
15 голосов
/ 30 октября 2009

Вы можете использовать objcopy, чтобы извлечь текстовый сегмент из файла .o или файла a.out.

$ cat q.c
f() {}
$ cc -S -O q.c
$ cat q.s
        .file   "q.c"
        .text
.globl f
        .type   f, @function
f:
        pushl   %ebp
        movl    %esp, %ebp
        popl    %ebp
        ret
        .size   f, .-f
        .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
        .section        .note.GNU-stack,"",@progbits
$ cc -c -O q.c
$ objcopy -O binary q.o q.bin
$ od -X q.bin
0000000 5de58955 000000c3
0000005
$ objdump -d q.o
q.o:     file format elf32-i386
Disassembly of section .text:
00000000 <f>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   5d                      pop    %ebp
   4:   c3                      ret    
10 голосов
/ 06 мая 2014

Вы можете передать параметры компоновщику напрямую с помощью -Wl,<linker option>

Соответствующая документация скопирована ниже из man gcc

-Wl, опция
Опция передачи в качестве опции для компоновщика. Если опция содержит запятые, она разделяется на несколько опций через запятую. Ты можешь использовать этот синтаксис для передачи аргумента в опцию. Например, -Wl, -Map, output.map передает -Map output.map компоновщику. При использовании компоновщика GNU, вы также можете получить тот же эффект с -Wl, -Map = output.map.

Таким образом, при компиляции с помощью gcc, если вы передадите -Wl,--oformat=binary, вы создадите двоичный файл вместо формата elf. Где --oformat=binary указывает ld создать двоичный файл.

Это устраняет необходимость objcopy отдельно.

Обратите внимание, что --oformat=binary можно выразить как OUTPUT_FORMAT("binary") из сценария компоновщика . Если вы хотите работать с плоскими двоичными файлами, есть большая вероятность, что вы выиграете от высокого уровня контроля, который обеспечивают сценарии компоновщика.

10 голосов
/ 21 ноября 2011

Другие ответы, безусловно, путь. Однако я должен был указать дополнительные аргументы командной строки для objcopy, чтобы мой вывод был таким, как ожидалось. Обратите внимание, что я разрабатываю 32-битный код на 64-битной машине, отсюда и аргумент -m32. Кроме того, мне больше нравится синтаксис сборки Intel, так что вы увидите это и в аргументах.

$ cat test.c
int main() { return 0; }
$ gcc -nostdinc -m32 -masm=intel -Wall -c test.c -o test.o
$ objdump --disassemble --disassembler-options intel test.o

test.o:     file format elf32-i386


Disassembly of section .text:

00000000 <main>:
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
   3:   b8 00 00 00 00          mov    eax,0x0
   8:   5d                      pop    ebp
   9:   c3                      ret    

Хорошо, вот где я должен был указать, что мне нужен только раздел .text:

$ objcopy --only-section=.text --output-target binary test.o test.bin
$ hexdump -C test.bin
00000000  55 89 e5 b8 00 00 00 00  5d c3   |U.......].|
0000000a

Мне потребовалось около 2 часов, чтобы прочитать и попробовать разные варианты, прежде чем я понял это. Надеюсь, это спасет кого-то еще в этот раз.

...