2009-10-30 2 views
28

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

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

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

+1

Два прекрасных ответа, представленных в то же время. Я не знаю, какой из них должен поставить галочку. –

+0

Вы можете принять [более свежий ответ] (http://stackoverflow.com/a/23502466/1483676), который напрямую отвечает на ваш вопрос (чистый ответ компилятора/компоновщика). – cubuspl42

ответ

30

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

$ 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 
+1

Я должен был включить '-j .text' в качестве параметра' objcopy', чтобы получить правильный результат. – SpellingD

+0

Почему? Что случилось, когда вы этого не сделали? –

+0

Он скопировал неправильный раздел (.text) из файла .o. Версия: 'GNU objcopy version 2.22.52.0.1-10.fc17 20120131' – SpellingD

15

Вы можете использовать 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  
+1

Вы, кажется, потеряли ссылку. – 2009-10-30 00:34:33

+0

Исправлено, спасибо .... – DigitalRoss

11

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

$ 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 часов чтения и пробовать разные варианты, прежде чем я понял это. Надеюсь, это спасет кого-то еще в то время.

9

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

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

-Wl, вариант
вариант Pass в качестве опции линкера. Если опция содержит запятые, она разделяется на несколько опций в запятых. Вы можете использовать этот синтаксис , чтобы передать аргумент опции. Например, -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") с точностью до linker script.Если вы хотите иметь дело с плоскими двоичными файлами, есть большая вероятность, что вы получите высокий уровень контроля, который предоставляют скрипты компоновщика.

+0

Фактически этот ответ является единственным реальным действительным ответом здесь ... Я бы сказал, что другие приемлемые обходные пути. – cubuspl42

+0

В будущем: решение '--oformat = binary', кажется, испускает неправильный машинный код в некоторых случаях * или * Я ничего не знаю о чем-то, но если вы случайно столкнетесь с каким-то странным поведением внешних символов, попробуйте 'objcopy'. – cubuspl42

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