Skip to content

stek29/minmacho

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 

make.c usage

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 for dyld 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

ENTRYP_CMD & THREAD_CMD

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

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.

SYMTAB

dyld doesn't like if symtab.symoff collides with mach-o header/commands, or if it's "under" LINKEDIT.

PAGEZERO

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 & FAKELINKEDIT

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.

NOPAD

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.

TEXT_ALIGN_END

Place actual code in the end of page instead of placing it right after the load commands. Needed for CodeSigning.

main.c/main.s

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.

Smallest runnable Mach-O

See post

License

MIT

About

A tool to craft mach-o files

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published