是否有一组命令行选项会说服gcc从自包含的源文件生成平面二进制文件?例如,假设foo.c的内容是
static int f(int x)
{
int y = x*x;
return y+2;
}
无外部引用,无需导出到链接器。我想获得一个只包含此功能的机器说明的小文件,没有任何其他装饰。类似于(DOS).COM文件,除了32位保护模式。
答案 0 :(得分:34)
试试这个:
$ 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 :(得分: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
答案 2 :(得分:10)
其他答案肯定是要走的路。但是,我必须为objcopy指定其他命令行参数,以使我的输出符合预期。请注意,我正在64位计算机上开发32位代码,因此-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个小时阅读并尝试了不同的选择。希望这能节省别人的时间。
答案 3 :(得分:10)
您可以使用-Wl,<linker option>
以下从man gcc
-Wl,选项
传递选项作为链接器的选项。如果选项包含逗号,则会在逗号中将其拆分为多个选项。您可以使用 此语法将参数传递给选项。例如, -Wl,-Map,output.map将-Map output.map传递给链接器。使用GNU链接器时,您也可以获得相同的效果 -Wl,-Map = output.map。
因此,如果通过-Wl,--oformat=binary
进行gcc编译,则会生成二进制文件而不是elf格式。 --oformat=binary
告诉ld
生成二进制文件的位置。
这样就无需单独objcopy
。
请注意,--oformat=binary
可以在linker script内表示为OUTPUT_FORMAT("binary")
。如果您想处理扁平二进制文件,那么您很有可能从链接器脚本提供的高级控制中受益。