Fundamentals 10 min read

Understanding Mach-O: Structure, Definitions, and Practical Applications

Mach‑O is the macOS and iOS binary format whose header, load commands, and __TEXT/__DATA sections define executable, library, and symbol information, enabling developers to understand loading, linking, and startup performance, and to implement custom initialization hooks or modular launch tasks via custom data sections.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Understanding Mach-O: Structure, Definitions, and Practical Applications

Mach-O (Mach Object) is the standard file format for executables, static libraries (.a), dynamic libraries, and other binary objects on macOS and iOS. Knowing its structure helps developers understand how the system loads binaries, performs static and dynamic linking, and measures startup performance.

Definition and File Types

.o – object file (MH_OBJECT)

.a – static library (MH_OBJECT)

Executable – MH_EXECUTE

Dynamic library – MH_DYLIB

Dyld (dynamic linker) – MH_DYLINKER

Symbol information – MH_DSYM

All of these are variations of the Mach-O format and can be inspected via the source of loader.h .

Mach-O Header

The header contains crucial metadata such as the magic number (identifies 32‑ or 64‑bit), CPU type (e.g., x86, arm64), file type (e.g., MH_EXECUTE), number of load commands, and the total size of load commands.

Load Commands

Load commands describe how the file’s segments are mapped into the process address space and provide information for the dynamic linker. Common commands include:

LC_SEGMENT_64 – maps a 64‑bit segment

LC_DYLD_INFO_ONLY – dyld‑related info

LC_SYMTAB – global symbol table

LC_DYSYMTAB – dynamic symbol table

LC_LOAD_DYLINKER – loads the dyld

LC_UUID – app UUID

LC_VERSION_MIN_IPHONEOS – minimum OS version

LC_MAIN – entry point for the main thread

LC_LOAD_DYLIB – loads a dependent dynamic library

LC_FUNCTION_STARTS – function start address table

LC_CODE_SIGNATURE – code signature

Data Sections

Mach‑O files are divided into three major parts: the header, load commands, and data. The data part consists of several segments, the most important being __TEXT (read‑only code) and __DATA (read‑write data).

Key __TEXT subsections:

TEXT.text – executable machine code

TEXT.cstring – deduplicated C strings

TEXT.const – initialized constants

TEXT.stubs / TEXT.stub_helper – lazy‑binding stubs

TEXT.unwind_info – unwind information for exception handling

TEXT.eh_frame – debugging info

Key __DATA subsections:

DATA.data – initialized mutable data

DATA.nl_symbol_ptr – non‑lazy binding pointers

DATA.la_symbol_ptr – lazy‑binding pointers (initially point to stub_helper)

DATA.const – uninitialized constants

DATA.mod_init_func – functions executed before main

DATA.mod_term_func – functions executed after main returns

DATA.bss – zero‑initialized static variables

DATA.common – uninitialized symbol declarations

Practical Use Cases

Understanding Mach‑O enables developers to:

Measure the time spent in C++ static initializers by hooking the mod_init_func section in __DATA .

Register custom startup tasks without cluttering AppDelegate , by placing function pointers into a custom __DATA section using the section("__DATA, \"#period\"") attribute.

Example macro for registering a launch task:

static void Launch_Func_(void);
__attribute__((used, section("__DATA, \"#period\""))) static const void * __Func__ = Launch_Func_;
static void Launch_Func_(void)

#define RegisterLaunchTaskOnWillFinishLaunchPeriod   RegisterLaunchTask(willFinishLaunch)
#define RegisterLaunchTaskOnDidFinishLaunchPeriod    RegisterLaunchTask(didFinishLaunch)
#define RegisterLaunchTaskOnDidFinishADPeriod        RegisterLaunchTask(didFinishAD)
#define RegisterLaunchTaskOnDidFinishHomepagePeriod RegisterLaunchTask(didFinishHome)

Business code can then register a task simply:

RegisterLaunchTaskOnDidFinishHomepagePeriod{
    /* do something */
}

By iterating over the custom __DATA section at runtime (using getsectbynamefromheader_64 ), the app can execute all registered functions in order, allowing modular startup logic and precise timing analysis.

References:

https://everttjf.github.io/2017/02/06/a-method-of-hook-static-2.initializers/

https://github.com/fangshufeng/MachOView

iOSMach-OmacOSclangStartup PerformanceBinary Formatload commandsstatic initializer
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.