Mach-O 文件的组成

9 阅读2分钟

概述

Mach-O(Mach Object)是 macOS、iOS 等 Apple 系统使用的可执行文件格式。一个标准的 Mach-O 文件由 三大部分 组成:

┌─────────────────────────────────────┐
│  1. Header(文件头)                  │
│  2. Load Commands(加载命令)         │
│  3. Data(数据段)                    │
└─────────────────────────────────────┘

1. Header(文件头)

位于文件偏移 0 处,是文件的"身份证"。

核心内容:

字段说明
Magic0xFEEDFACE (32位) / 0xFEEDFACF (64位)
cputypeCPU 架构(X86_64、ARM64 等)
filetype文件类型(可执行文件、动态库、目标文件等)
ncmdsLoad Commands 的数量
sizeofcmdsLoad Commands 的总大小
flags文件特性标志(PIE、ASLR 等)

作用:告诉系统"这是什么文件、给什么 CPU 用、后面有多少内容"。


2. Load Commands(加载命令)

紧跟在 Header 之后,是"加载说明书"。

常见命令类型:

命令作用
LC_SEGMENT / LC_SEGMENT_64描述段(Segment)如何映射到内存
LC_LOAD_DYLIB依赖的动态库列表
LC_SYMTAB符号表位置
LC_DYSYMTAB动态符号表位置
LC_CODE_SIGNATURE代码签名信息位置
LC_MAIN程序入口点(替代旧的 LC_UNIXTHREAD
LC_BUILD_VERSION构建版本信息

作用:指导 dyld(动态链接器)如何将文件加载到内存、解析依赖、准备执行。


3. Data(数据)

文件的实际内容,按段(Segment)组织。

主要段(Segments)

段名权限内容
__TEXT只读、可执行代码(__text)、常量字符串(__cstring)、Objective-C 元数据等
__DATA可读、可写全局变量(__data)、未初始化数据(__bss)、线程本地存储等
__LINKEDIT只读链接和加载所需的元数据

__LINKEDIT 段详解

包含大量支持动态链接和数据结构:

数据类型说明
符号表函数/变量名与地址的映射关系
字符串表符号名称的原始字符串存储
重定位表需要运行时修正的地址列表
代码签名CMS 签名、CDHash、权限声明(Entitlements)
导出表本文件对外暴露的符号
绑定信息延迟绑定的符号信息

总结

组成部分核心职责类比
Header身份识别和基本信息身份证
Load Commands告诉系统如何加载说明书
Data实际可执行代码和数据货物本身

一句话理解:Header 说"我是谁",Load Commands 说"怎么加载我",Data 说"我的内容是什么"。


查看工具

# 查看 Header
otool -h /bin/ls

# 查看 Load Commands
otool -l /bin/ls

# 查看所有符号
nm /bin/ls

# GUI 工具:MachOView、Hopper、IDA Pro