内容简介:它是一种用于可执行文件、目标代码、动态库的文件格式,作为.out格式的替代,MachO提供了更强的扩展性
作者: 我是好宝宝
链接:https://juejin.im/post/5df47aebe51d4558483d9717
一、MachO初探
1.定义
MachO
其实是 Mach Object
文件格式的缩写,是mac以及iOS上可执行文件的格式,类似于Windows上的PE格式(Portable Executable)、 Linux 上的elf格式(Executable and Linking Format)
它是一种用于可执行文件、目标代码、动态库的文件格式,作为.out格式的替代,MachO提供了更强的扩展性
2.常见的MachO文件
-
目标文件.o
-
库文件
-
.a
-
.dylib
-
.Framework
-
可执行文件
-
dyld(动态链接器)
-
.dsym(符号表:Relese环境运行生成
3.查看文件类型
$ file xxx.xx
二、关于架构
1.架构表
其实iPhone不同的型号对应的架构是不一样的
2.生成多种架构
新建一个工程,真机运行,查看可执行文件仅仅是一个arm64架构的
将项目最低适配系统调为iOS9.0,真机运行
Relese环境
为什么要改为iOS9.0呢 ?是因为iPhone5c等armv7、armv7s架构不支持iOS11.0
为什么要Relese环境运行呢 ?因为Xcode默认Debug只生成单一架构
怎么生成所有架构
?Xcode10中只包含了v7和64,需要在 Architectures
中添加
三、通用二进制文件
1.定义
通用二进制文件(Universal binary)也被叫做 胖二进制(Fat binary)
-
苹果公司提出的一种程序代码,能同时适用多种架构的二进制文件
-
同一个程序包中同时为多种架构提供最理想的性能
-
因为需要储存多种代码,通用二进制应用程序通常比单一平台二进制的程序要大
-
但是由于两种架构有共通的非执行资源,所以并不会达到单一版本的两倍之多
-
而且由于执行中只调用一部分代码,运行起来也不需要额外的内存
2.拆分/合并架构
架构拆分
合并架构
通用二进制
大小为342kb,四个架构大小为80+80+80+81=321kb
What!为什么不是单纯的1+1=2?
因为不同架构之间代码部分是不共用的 (因为代码的二进制文件不同的组合在不同的 cpu 上可能会是不同的意义),而公共资源文件是公用的
利用上述方法可以给我们的app瘦身
结论:
① 胖二进制
拆分后再重组会得到原始 胖二进制
② 通用二进制
的大小可能大于子架构大小之和,也可能小于,也可能等于,取决于 公共资源文件
的多少
3.终端命令行
// 查看二进制文件
$ lipo -info xx
// 通用二进制文件
// 拆分二进制文件
lipo xxx -thin armv7 -output xxx
// 组合二进制文件
lipo -create x1 x2 x3 x4 -output xxx
四、MachO文件
1.整体结构
用 MachOView
打开会看到 通用二进制文件
由 Fat Header
和 四个可执行文件
组成
可执行文件
是由
Header
、
Load commands
和
Data
组成
我们可以这么理解,把
通用二进制文件
看作四本翻译语言不同的书,每本书有
标题(header)
、
目录(load commands)
、
内容(data)
-
header:
-
load commands:
-
data:
另外我们也可以通过 otool
命令行查看MachO文件结构
$ otool -f universe
2.header
header
包含了该二进制文件的字节顺序、架构类型、加载指令的数量等,使得可以快速确认一些信息,比如当前文件用于 32 位
还是 64 位
,对应的处理器是什么、文件类型是什么
Xcode中 shift+command+O
-> load.h
->如下信息
struct mach_header_64 {
uint32_t magic; /* 魔数,快速定位64位/32位 */
cpu_type_t cputype; /* cpu 类型 比如 ARM */
cpu_subtype_t cpusubtype; /* cpu 具体类型 比如arm64 , armv7 */
uint32_t filetype; /* 文件类型 例如可执行文件 .. */
uint32_t ncmds; /* load commands 加载命令条数 */
uint32_t sizeofcmds; /* load commands 加载命令大小*/
uint32_t flags; /* 标志位标识二进制文件支持的功能 , 主要是和系统加载、链接有关*/
uint32_t reserved; /* reserved , 保留字段 */
};
mach_header_64(64位)对比mach_header(32位)只多了一个保留字段
3.load commands
load commands
是一张包括区域的位置、符号表、动态符号表等内容的表。它详细保存着加载指令的内容,告诉链接器如何去加载这个 Mach-O 文件。通过查看内存地址我们发现,在内存中 load commands
是紧跟在 header
之后的
4.data
data
是MachO文件中最大的部分,其中 _TEXT段
、 _DATA段
能给到很多信息
load commands
和 data
之间还留有不少空间,给我们留下了注入代码的冲破口
_TEXT段
_DATA段
五、dyld
dyld(the dynamic link editor)是苹果的动态链接器,是苹果操作系统的一个重要组成部分,在系统内容做好程序准备工作之后,交由dyld负责余下的工作
系统库的方法由于是公用的,存放在共享缓存中,那么我们的MachO在调用系统方法时,dyld会将MachO里调用存放在共享缓存中的方法进行符号绑定。这个符号在 release环境
是会被自动去掉的,这也是我们经常使用收集 bug 工具时需要恢复符号表的原因
如果感觉这篇文章不错可以点击在看:point_down:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Scala在资源文件夹中获取文件的文件路径
- Go语言的文件操作:文件的读写,文件的新建打开和删除
- 安卓文件存储/文件读写操作
- 文件上传之秒传文件
- Eclipse中写jsp文件时,发现里面加载不了js文件和css文件(解决css文件在eclipse中显示不了)
- Linux 下按照文件大小查找文件
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Essential C++中文版
[美] Stanley B. Lippman / 侯捷 / 华中科技大学出版社 / 2001-8 / 39.80元
书中以4个面向来表现C++的本质:procedural(程序性的)、generic(泛型的)、object-based(个别对象的)、object-oriented(面向对象的),全书围绕着一系列逐渐繁复的程序问题,以及用以解决这些问题的语言特性。循此方式,读者不只学到C++的函数和结构,也会学习到它们的设计目的和基本原理。一起来看看 《Essential C++中文版》 这本书的介绍吧!