目录
什么是MachO文件
一、Mach-O
Mach-O其实是Mach Object文件格式的缩写,是macOS、iOS、iPadOS存储程序(可执行文件)和库的文件格式,对应系统通过应用二进制接口(application binary interface,缩写为 ABI)来运行该格式的文件。
ABI稳定指的是Mach-O文件的内部结构稳定了下来,相应的系统在调用解析Mach-O文件时的流程也就稳定了下来.
类似于windows上的PE格式(Portable Executable),Linux上的elf格式(Executable and Linking Format)。
Mach-O为Mach Object文件格式的缩写,它是一种用于可执行文件、目标代码、动态库的文件格式。作为a.out格式的替代,Mach-O提供了更强的扩展性。
Mach-O格式用来替代BSD系统的a.out格式。Mach-O文件格式保存了在编译过程和链接过程中产生的机器代码和数据,从而为静态链接和动态链接的代码提供了单一文件格式。
可以理解为 Mach-O = 文件配置 + 二进制代码
objdump –macho –private-headers 文件
二、属于MachO格式的常见文件
目标文件: .o
库文件: .a
.dylib
.Framework
可执行文件
dyld
.dsym
三、查看文件格式
可通过file
指令查看文件类型
1、查看.o文件的类型
$ vi test.c
$ clang -c test.c
$ file test.o
test.o: Mach-O 64-bit object x86_64
test.c文件内容
#include <stdio.h>
int main(){
printf("helloWorld!\n");
return 0;
}
2、查看.dylib文件的类型
$ find / -name "*.dylib"
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/libssl.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/plugin/libcrypto.1.0.0.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/plugin/libssl.1.0.0.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/plugin/debug/libcrypto.1.0.0.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/plugin/debug/libssl.1.0.0.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/libmysqlclient.21.dylib
...
file /usr/local/mysql-8.0.12-macos10.13-x86_64/lib/libssl.dylib
/usr/local/mysql-8.0.12-macos10.13-x86_64/lib/libssl.dylib: Mach-O 64-bit dynamically linked shared library x86_64
3、查看可执行文件的类型
$ clang test.o
$ ls
a.out test.c test.o
$ ./a.out
helloWorld!
$ file a.out
a.out: Mach-O 64-bit executable x86_64
我们改造下test.c文件
#include <stdio.h>
void test1();
int main(){
printf("helloWorld!\n");
test1();
return 0;
}
在创建一个test1.c文件
void test1(){
printf("test1\n");
}
查看文件类型
$ clang -c test.c test1.c //编译
clang -o demo test.o test1.o //连接
./demo //执行
helloWorld!
test1
$ file demo
demo: Mach-O 64-bit executable x86_64
在看下我们iOS工程的可执行文件的类型
$ file XXXClient
XXXClient: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O executable arm_v7] [arm64]
XXXClient (for architecture armv7): Mach-O executable arm_v7
XXXClient (for architecture arm64): Mach-O 64-bit executable arm64
4、查看dyld文件的类型
$ cd /usr/lib
$ ls dyld
dyld
$ file dyld
dyld: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit dynamic linker x86_64] [i386:Mach-O dynamic linker i386]
dyld (for architecture x86_64): Mach-O 64-bit dynamic linker x86_64
dyld (for architecture i386): Mach-O dynamic linker i386
5、查看.dsym文件类型
$ ls -l
total 48
-rwxr-xr-x 1 LKLC staff 8432 4 24 16:50 a.out
-rw-r--r-- 1 LKLC staff 72 4 24 16:50 test.c
-rw-r--r-- 1 LKLC staff 776 4 24 16:50 test.o
-rw-r--r-- 1 LKLC staff 38 4 24 16:12 test1.c
drwxr-xr-x 3 LKLC staff 96 4 23 11:03 xxx.app.dSYM
$ file ./xxx.app.dSYM/Contents/Resources/DWARF/xxx
./xxx.app.dSYM/Contents/Resources/DWARF/xxx: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O dSYM companion file arm_v7] [arm64]
./xxx.app.dSYM/Contents/Resources/DWARF/xxx (for architecture armv7): Mach-O dSYM companion file arm_v7
./xxx.app.dSYM/Contents/Resources/DWARF/xxx (for architecture arm64): Mach-O 64-bit dSYM companion file arm64
universal binary
一、介绍
苹果公司提出的一种程序代码。能同时适用多种架构的二进制文件。
同一程序包中同时为多种架构提供最理想的性能。
因为需要存储多种代码,通用二进制应用程序通常比单一平台二进制的程序要大。
但是由于两种架构有共通的非执行资源,所以并不会达到单一版本的两倍之多。
而且由于执行中只调用一部分代码,运行起来也不需要额外的内存。
另外从iOS11的系统开始,只支持arm64架构
看下在xcode中如何配置
二、拆分与合并(lipo命令)
1、使用 lipo -info MachO文件 查看MachO文件包含的架构
$ lipo -info xxxmacho
Architectures in the fat file: macho are: armv7 arm64
2、使用 lipo MachO文件 -thin 架构 -output 输出文件路径 拆分某种架构
$ lipo xxxmacho -thin arm64 -output macho_arm64
$ lipo -info macho_arm64
Non-fat file: macho_arm64 is architecture: arm64
$ lipo xxxmacho -thin armv7 -o macho_armv7
$ lipo -info macho_armv7
Non-fat file: macho_armv7 is architecture: armv7
3、使用 lipo -create macho文件1 macho文件2 -output 输入文件路径 合并多种架构
$ lipo -create macho_armv7 macho_arm64 -output macho_lc
$ lipo -info macho_lc
Architectures in the fat file: macho_lc are: armv7 arm64
localhost:test LKLC$ md5 xxxmacho
MD5 (xxxmacho) = 882235a199c6cfb1bcf3f437527f7961
localhost:test LKLC$ md5 macho_lc
MD5 (macho_lc) = 882235a199c6cfb1bcf3f437527f7961
MachO文件结构
MachO文件本身是一种文件格式,所以我们一定需要了解其文件内部结构。
MachO的组成结构如图所示包括了
一、Header包含该二进制文件的一般信息
字节顺序(大小端)、架构类型、加载指令的数量等。
使得可以快速确认一些信息,比如当前文件用于32位还是64位,对应的处理器是什么、文件类型是什么
程序加载的时候会首先解析头部信息,在xcode内command+shift+o 搜索loader.h可以看到头部的一些数据结构
通过MachOView工具看下头部信息
二、Load commands 一张包含很多内容的表
内容包括区域的位置、符号表、动态符号表等。
三、Data 通常是对象文件中最大的部分
包含 segement的具体数据
MachO可以简单类比成一本书,其中header为序,Load Commands为目录,Data为具体的内容。
行者常至,为者常成!