Есть ли способ получить gcc для вывода необработанных двоичных файлов?
Есть ли набор параметров командной строки, которые убедят gcc в создании плоского двоичного файла из автономного исходного файла? Например, предположим, что содержимое foo.c
static int f(int x)
{
int y = x*x;
return y+2;
}
Нет внешних ссылок, ничего не экспортируется в компоновщик. Я бы хотел получить небольшой файл с инструкциями машины для этой функции без каких-либо других украшений. Похоже на файл (DOS).COM, за исключением 32-разрядного защищенного режима.
Ответы
Ответ 1
Попробуйте следующее:
$ 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
Ответ 2
Вы можете использовать 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
Ответ 3
Другие ответы - это, безусловно, путь. Однако мне нужно было указать дополнительные аргументы командной строки для 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 часов чтения и попробовать разные варианты, прежде чем я понял это. Надеюсь, это спасет кого-то еще в это время.
Ответ 4
Вы можете передать параметры компоновщику непосредственно с -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")
из компоновщика script. Если вы хотите иметь дело с плоскими двоичными файлами, существует большая вероятность того, что вы получите высокий уровень контроля, который предоставляют сценарии компоновщика.