I am working making an assembler that compiles bf code into an executable that can be run on macOS. Essentially, I run the compiler, which outputs a raw arm64 binary to output.bin (i.e., a binary that contains the arm64 machine code without any formatting). I figured out that the output.bin cannot be run directly, rather it needs to be first linked into a Mach-O binary in order for it to be executable. From what I've researched, the linking phase seems like it could be accomplished with the following steps:
- Compile an empty C file to create a stub Mach-O object
touch stub.c
cc -c stub.c -o stub.o
- Link the
output.bininto the stub Mach-O object, creating a_startsymbol
ld -r -o output.o stub.o -sectcreate __TEXT _start output.bin
- Link the newly-created
output.oagainst the system libraries and designate_startas the executable entry point
ld -o output output.o -lSystem -syslibroot `xcrun -sdk macosx --show-sdk-path` -e _start -arch arm64
Where I get stuck is when I try to link the output.o to make the final executable, I get the following error:
Undefined symbols for architecture arm64:
"_start", referenced from:
ld: symbol(s) not found for architecture arm64
make: *** [output] Error 1
When I run the nm output.o command, it doesn't show the _start symbol in the symbol table, rather I only see the following:
0000000000000000 t ltmp0
However, when I hex dump the output.o, there is a cluster of bytes that comes up with this:
000000b0: 0000 0000 0000 0000 5f73 7461 7274 0000 ........_start..
000000c0: 0000 0000 0000 0000 5f5f 5445 5854 0000 ........__TEXT..
Furthermore, the program code starts at offset 0x00000170 in the output.o. What step am I missing here?