How to inspect Mach-O files
clang main.c produces an
which on macOS is a binary in the Mach-O (“Mach object”) format:
$ clang main.c $ file a.out a.out: Mach-O 64-bit executable x86_64
clang produces Mach-O files when run on macOS
because the executable format in macOS is Mach-O.
By contrast, on Linux,
clang produces ELF files (“Executable and Linkable Format”),
because Linux’s executable format is ELF.
This is documented in man pages.
On macOS, the page for the
execve system call says:
execve()transforms the calling process into a new process. The new process is constructed from an ordinary file ... This file is either an executable object file, or a file of data for an interpreter. An executable object file consists of ... see a.out(5).
The page for
The object files produced by the assembler and link editor are in Mach-O (Mach object) file format.
Since Mach-O files are just ordinary files, we can dig into the bits-and-bytes.
But we can also inspect Mach-O files with a tool called
otool (“object tool”).
For example, we can see what dynamic libraries our
$ otool -L a.out a.out: /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.60.2)
.dylib is a Mach-O dynamic module/library.
clang decided that our program should depend on a dynamic library at
This provides the implementations of many things used by C programs, such as stdio functions.
Dynamic libraries can themselves require dynamic libraries.
The big dylib at
/usr/lib/libSystem.B.dylib requires a bunch more dylibs:
$ otool -L /usr/lib/libSystem.B.dylib /usr/lib/libSystem.B.dylib: ... /usr/lib/system/libsystem_asl.dylib (compatibility version 1.0.0, current version 349.50.5) /usr/lib/system/libsystem_blocks.dylib (compatibility version 1.0.0, current version 67.0.0) /usr/lib/system/libsystem_c.dylib (compatibility version 1.0.0, current version 1158.50.2) /usr/lib/system/libsystem_configuration.dylib (compatibility version 1.0.0, current version 888.60.2) /usr/lib/system/libsystem_coreservices.dylib (compatibility version 1.0.0, current version 41.4.0) ...
An important dylib in here is
It defines a bunch of functions used by C programs.
For example, this dylib defines the function
We can see this using a tool
nm (“name”), which shows the name/symbol table of a Mach-O file.
$ nm -g /usr/lib/system/libsystem_c.dylib | grep fprintf 000000000003ed45 T _fprintf 000000000003ee18 T _fprintf_l 0000000000046355 T _vfprintf 0000000000046308 T _vfprintf_l
Notice that the symbol is not
_fprintf. This is because “The name of a symbol representing a function that conforms to standard C calling conventions is the name of the function with an underscore prefix”, according to Apple.
More by Jim
- Your syntax highlighter is wrong
- Granddad died today
- The Three Ts of Time, Thought and Typing: measuring cost on the web
- I hate telephones
- The sorry state of OpenSSL usability
- The dots do matter: how to scam a Gmail user
- My parents are Flat-Earthers
- How Hacker News stays interesting
- Project C-43: the lost origins of asymmetric crypto
- The hacker hype cycle
- The inception bar: a new phishing method
- Time is running out to catch COVID-19
- A probabilistic pub quiz for nerds
- Smear phishing: a new Android vulnerability
Tagged . All content copyright James Fisher 2017. This post is not associated with my employer. Found an error? Edit this page.