开发者

Is there a way to get gcc to output raw binary?

开发者 https://www.devze.com 2022-12-10 07:19 出处:网络
Is there a set of command-line options that will convince gcc to produce a flat binary file from a self-contained source file?For example, suppose the con开发者_Python百科tents of foo.c are

Is there a set of command-line options that will convince gcc to produce a flat binary file from a self-contained source file? For example, suppose the con开发者_Python百科tents of foo.c are

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

No external references, nothing to export to the linker. I'd like to get a small file with just the machine instructions for this function, without any other decoration. Sort of like a (DOS) .COM file except 32-bit protected mode.


Try this out:

$ gcc -c test.c     
$ objcopy -O binary -j .text test.o binfile

You can make sure it's correct with 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  

And compare it with the binary file:

$ 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


You can pass options to the linker directly with -Wl,<linker option>

The relevant documentation is copied below from the man gcc

-Wl,option
Pass option as an option to the linker. If option contains commas, it is split into multiple options at the commas. You can use this syntax to pass an argument to the option. For example, -Wl,-Map,output.map passes -Map output.map to the linker. When using the GNU linker, you can also get the same effect with -Wl,-Map=output.map.

So when compiling with gcc if you pass -Wl,--oformat=binary you will generate a binary file instead of the elf format. Where --oformat=binary tells ld to generate a binary file.

This removes the need to objcopy separately.

Note that --oformat=binary can be expressed as OUTPUT_FORMAT("binary") from within a linker script. If you want to deal with flat binaries, there's a big chance that you would benefit from high level of control that linker scripts provide.


You can use objcopy to pull the text segment out of the .o file or the a.out file.

$ 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    


The other answers are definitely the way to go. However, I had to specify additional command line arguments to objcopy in order for my output to be as expected. Note that I am developing 32-bit code on a 64-bit machine, hence the -m32 argument. Also, I like intel assembly syntax better, so you'll see that in the arguments as well.

$ 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    

Ok, here's where I had to specify that I specifically only wanted the .text section:

$ 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

It took me about 2 hours of reading and trying different options before I figured this out. Hopefully this saves someone else that time.

0

精彩评论

暂无评论...
验证码 换一张
取 消