有没有办法让gcc输出原始二进制文件?

I. *_*edy 29 linux x86 linker command-line gcc

是否有一组命令行选项可以说服gcc从自包含的源文件生成平面二进制文件?例如,假设foo.c的内容是

static int f(int x)
{
  int y = x*x;
  return y+2;
}
Run Code Online (Sandbox Code Playgroud)

没有外部引用,没有什么可以导出到链接器.我想获得一个只包含此功能的机器说明的小文件,没有任何其他装饰.类似于(DOS).COM文件,除了32位保护模式.

Car*_*rum 34

试试这个:

$ cc -c test.c
$ objcopy -O binary test.o binfile
Run Code Online (Sandbox Code Playgroud)

你可以确保它是正确的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  
Run Code Online (Sandbox Code Playgroud)

并与二进制文件进行比较:

$ 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
Run Code Online (Sandbox Code Playgroud)

  • 我必须将`-j .text`作为参数包含在`objcopy`中以获得正确的结果. (2认同)

Dig*_*oss 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    
Run Code Online (Sandbox Code Playgroud)

  • 你似乎已经失去了链接. (2认同)

FDi*_*off 11

您可以直接将选项传递给链接器 -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")链接描述文件中表示.如果您想处理扁平二进制文件,那么您很有可能从链接器脚本提供的高级控制中受益.

  • 实际上,这个答案是这里唯一真正有效的答案......我想说其他都是可以接受的解决方法。 (5认同)

Chr*_*ome 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    
Run Code Online (Sandbox Code Playgroud)

好的,这里我必须指定我特别只想要.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
Run Code Online (Sandbox Code Playgroud)

在我弄清楚之前,我花了大约2个小时阅读并尝试了不同的选择.希望这能节省别人的时间.