I was lazy to handle args properly, so it has to be recompiled each time.
It creates executable mach-o file a.out
which bundles code from file __TEXT.__text
.
Likely files larger than one page size are broken.
Supported options:
- Arch: MAKE_ARM64, MAKE_X86_32, MAKE_X86_64
- Entry point specifier: ENTRYP_CMD for LC_MAIN or THREAD_CMD for LC_UNIXTHREAD
- PAGEZERO -- to include a null mapping, needed everywhere except x86_32.
- LINKEDIT -- to include a
__LINKEDIT
segment - FAKELINKEDIT -- same, but make it with vmsize=0 and filesize=0. Useful to get dyld working.
- DYLD -- include LC_LOAD_DYLINKER
- DYLDINO -- include LC_DYLD_INFO_ONLY
- SYMTAB -- include emtpy SYMTAB
- DYSYMTAB -- include empty DYSYMTAB
- DYLIB -- link to
/usr/lib/system/libdyld.dylib
, needed fordyld
to get working. - TEXT_SECT -- make a
__TEXT.__text
section. - NOPAD -- don't add padding to make file at least of
PAGE_SIZE
. Useful for testing. - NO_CMDSIZE_ROUND -- don't make cmdsize's divisible by 8 (for DYLD/DYLIB, where lc_str's are used).
- TEXT_ALIGN_END -- align code to the end -- useful for codesigning.
- FUNCTION_STARTS -- haven't really tested since it turened out to be useless
- VERSION -- macos version, not really tested
LC_MAIN is handled by dyld.
Therefore, DYLD
is needed to make it work.
LC_UNIXTHREAD is handled by kernel itself, and can be used to set registers loaded when thread is started.
dyld
would refuse to work if DYLDINO/SYMTAB/DYSYMTAB are missing, or if there's no (fake) LINKEDIT segment.
And even with those dyld
would fail with error libdyld.dylib support not present for LC_MAIN
, because libdyld.dylib
is simply not loaded.
So that's why it needs DYLIB
.
dyld
doesn't like if symtab.symoff
collides with mach-o header/commands, or if it's "under" LINKEDIT.
All binaries are required to have __PAGEZERO
(any mapping with VM_PROT_NONE protection covering page at 0x0).
IIRC they (Apple) didn’t make it required on x86_32 mode only because some legacy softwaredidn’t have it and they’re afraid to break it.
LINKEDIT creates another segment with size 0x80.
FAKELINKEDIT creates another segment which is much like __PAGEZERO
-- with 0 size. That's enough to get dyld happy.
File size has to be at least of page size, or kernel would say it's "Bad Mach-O". Because of that, padding might be necessary. This option disables it.
Place actual code in the end of page instead of placing it right after the load commands. Needed for CodeSigning.
I've made a couple of files printing "Hi Frand" and exiting with exit status 42 for different archs. There's also a main.c for the reference.
See post
MIT