Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

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.

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.

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, 0x2000006

.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

The code that have to be saved as raw binary file is included in dump.s

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top