详细版本 https://www.yuque.com/docs/share/077aaf76-0fe6-47da-a7c9-d2af0c4b4e3a?# 《初识Mach-O 文件》
何为Mach-O文件?
Mach-O为Mach Object文件格式的缩写,它是一种用于可执行文件,目标代码,动态库,内核转储的档案格式,mac和iOS的可执行文件都是这种格式
当然了,他也有很多种存在的格式
- 目标文件.o
- 库文件:.a静态库文件;.dylib动态库文件;.framework系统级为动态库文件,自己创建的为静态库文件
- 可执行文件及MDW.app内部的MDW文件(通用二进制文件)
- .dyld动态链接器将依赖的动态库加载到内存
- .dsym符号表
发展历史
macOS系统一路走来,支持的CPU及硬件平台都有了很大的变化,从早期的PowerPC平台,到后来的x86,再到现在主流的arm、x86-64平台。软件开发人员为了做到不同硬件平台的兼容性,如果需要为每一个平台编译一个可执行文件,这将是非常繁琐的。为了解决软件在多个硬件平台上的兼容性问题,苹果开发了一个通用的二进制文件格式(Universal Binary)。
Mach-O文件的内部结构
官方图片
image.png文件分为三个部分:
1、Header:包含Mach-O文件的基本信息,字节顺序、架构类型、加载指令的数量等
2、Load commands:包含区域位置、符号表、动态符号表,加载Mach-O文件时使用这里的数据确定内存分布
3、Data:数据段segement,包含具体代码、常量、类、方法等,有多个segment,每个segment有0到多个section,每个段有一个虚拟地址映射到进程的地址空间
通过Mach-O文件 可以查看到里面的内容
image.png
Header
image.png- magic:魔数,确定是64位还是32位
- cputype:cpu类型
- cpusubtype:cpu子类型(arm64 armv7)
- filetype:Mach-O支持多种文件类型,使用filetype来标注具体文件类型,比如可执行文件、目标文件等等
- ncmds:加载命令(load commands)的数量
- sizeofcmds:命令区域(load commands)总的字节大小
- flags:标识二进制文件所支持的功能,主要与系统的加载、链接有关
Load commands
image.png- LC_SEGMENT_64:将文件中的段映射到进程地址空间中
- LC_DYLD_INFO_ONLY:动态链接相关信息
- LC_SYMTAB:符号表信息,位置、偏移、数据个数,供dyld使用
- LC_DYSYMTAB:动态符号表信息,供dyld使用
- LC_LOAD_DYLINKER:链接器信息,记录使用那些链接器完成内核后序的加载工作
- LC_UUID:Mach-O文件的唯一标识
- LC_VERSION_MIN_MACOSX:支持最低操作系统版本
- LC_SOURCE_VERSION:源代码的版本号
- LC_MAIN:设置主线程的入口即栈大小
- LC_LOAD_DYLIB:依赖库信息,dyld通过该命令去加载依赖库
- LC_FUNCTION_STARTS:函数的起始地址表
- LC_CODE_SIGNATURE:代码签名
- sectname:是__text ,就是主程序代码
- segname:该section所属的segment名,第一个是__TEXT
- addr:当前section在内存中的起始位置
- size:当前section所占内存大小
- offset:当前section的文件偏移
- align:字节大小对齐
- reloff:重定位入口的文件偏移,0
- nreloc:需要重定位的入口数量,0
- flags:包含section的type和attributes
- reserved1、reserved2预留字段
Data
Data区域由Segment段和Section节组成
Segment
segment主要有__TEXT和__DATA组成
__text:是主程序代码
__stubs、__stub_helper:是动态链接的桩
__cstring:程序中c语言字符串
__const:常量
image.png
image.png
Section
在 Segment 里面会包含不同的 section ,其结构如下
struct section_64 { /* for 64-bit architectures */
char sectname[16]; /* name of this section */
char segname[16]; /* segment this section goes in */
uint64_t addr; /* memory address of this section */
uint64_t size; /* size in bytes of this section */
uint32_t offset; /* file offset of this section */
uint32_t align; /* section alignment (power of 2) */
uint32_t reloff; /* file offset of relocation entries */
uint32_t nreloc; /* number of relocation entries */
uint32_t flags; /* flags (section type and attributes)*/
uint32_t reserved1; /* reserved (for offset or index) */
uint32_t reserved2; /* reserved (for count or sizeof) */
uint32_t reserved3; /* reserved */
};
sectname: section 的名字
segname: segment 的名字
addr: 映射到虚拟地址的偏移
size: section 的大小
offset: section 在当前架构中的偏移
align: section的字节对齐大小 n
reloff: 重定位入口的文件偏移
nreloc: 重定位入口的个数
flags: section的类型与属性:
reserved: 保留位
网友评论