Reputation: 2119
How can you generate a flat binary that will run directly on the CPU?
That is, without an Operating System; also called free standing environment code (see What is the name for a program running directly without an OS?).
I've noticed that the assembler I'm using, as
from the OS-X developer tools bundle, keeps generating Mach-O files, and not flat binaries.
Upvotes: 5
Views: 4215
Reputation: 1
There is no easy way I know of.
Once I needed to create plain binary file which will be loaded and executed by another program. However, as
didn't allow me to do that. I tried to use gobjcopy
to convert object file to raw binary, but it was not able to properly convert code such as this:
.quad LinkName2 - LinkName1
In binary file produced by gobjcopy
it looked like
.quad 0
I've ended up writing special dumping program, which is executable that will save part of the memory on disk:
.set SYS_EXIT, 0x2000001 .set SYS_READ, 0x2000003 .set SYS_WRITE, 0x2000004 .set SYS_OPEN, 0x2000005 .set SYS_CLOSE, 0x2000006The code that have to be saved as raw binary file is included in.data dumpfile: .ascii "./dump" .byte 0 OutputFileDescriptor: .quad 0
.section __TEXT,__text,regular .globl _main
_main:
movl $0644, %edx # file mode movl $0x601, %esi # O_CREAT | O_TRUNC | O_WRONLY leaq dumpfile(%rip), %rdi movl $SYS_OPEN, %eax syscall movq %rax, OutputFileDescriptor(%rip) movq $EndDump - BeginDump, %rdx leaq BeginDump(%rip), %rsi movq OutputFileDescriptor(%rip), %rdi movl $SYS_WRITE, %eax syscall movq OutputFileDescriptor(%rip), %rdi movl $SYS_CLOSE, %eax syscall
Done: movq %rax, %rdi movl $SYS_EXIT, %eax syscall
.align 3
BeginDump: .include "dump.s" EndDump: .quad 0
dump.s
Upvotes: 0
Reputation: 1382
This is the way I've done it. Using the linker that comes with the XCode Command Line Tools, you can combine object files using:
ld code1.o code2.o -o code.bin -r -U start
The -r
asks ld
to just combine object files together without making a library, -U
tells ld
to ignore the missing definition of _start
(which would normally be provided by the C stdlib).
This creates a binary which still has some header bytes, but this is easily identified with
otool -l code.bin
Look for the __text
section in the output:
Section
sectname __text
segname __TEXT
addr 0x00000000
size 0x0000003b
offset 240
align 2^4 (16)
reloff 300
nreloc 1
flags 0x80000400
reserved1 0
reserved2 0
Note the offset (which you can confirm by comparing the output of otool -l
and hexdump
). We don't want the headers so just use dd
to copy out the bytes you need:
dd if=code.bin of=code_stripped.bin ibs=240 skip=1
where I've set the block size to the offset and skipping one block.
Upvotes: 4
Reputation:
You may want to try using the nasm
assembler -- it has an option to control the output binary format, including -f bin
for flat binaries.
Note that you can't easily compile C code to flat binaries, since almost any C code will require binary features (like external symbols and relocations) which can't be represented in a flat binary.
Upvotes: 0
Reputation:
I don't think you necessarily need to do this. Some bootloaders can load more complex executable formats. For example, GRUB can load ELF right off the bat. I'm sure you can somehow get it or some other bootloader to load Mach-O files.
Upvotes: 1
Reputation: 490583
You don't. You get the linker to produce a flat (pure) binary. To do that, you have to write a linker script file with OUTPUT_FORMAT(binary)
. If memory serves, you also need to specify something about how the sections are merged, but I don't remember any of the details.
Upvotes: 3