LinkMap解析
导读
IOS在做包大小优化的时候,需要分析包大小组成,然后通过包大小组成来有针对的做优化。其中最主要的工具就是linkmap文件的解析,下面文章讲简单说明如何解析linkmap文件。
如何生成linkMap文件
Xcode开启编译选项Write Link Map File
XCode -> Project -> Build Settings -> 搜map -> 把Write Link Map File选项设为yes,并指定好linkMap的存储位置
编译后,到编译目录里找到该txt文件,文件路径就是上面设定的路径,我的位于:
~/Library/Developer/Xcode/DerivedData/FFProject-gdxobffdqcwvyleustpwgfdxslqp/Build/Intermediates/FFProject.build/Debug-iphonesimulator/FFProject.build
linkMap文件结构解析
1. 基础信息
|
|
2.类表
|
|
这里保存了所有用到的类生成的.o文件,也包括用到的dylib
库。前面[num]是序号,类是按照顺序保存的,后续可以通过序号查到具体对应的哪个类。
3.段表
|
|
接下来是段表,描述了不同功能的数据保存的地址,通过这个地址就可以查到对应内存里存储的是什么数据。
其中第一列是起始地址,第二列是段占用的大小,第三个是段类型,第四列是段名称,每一行初始地址 = 上一行的初始地址+占用大小
其中:
__TEXT 表示代码段,用于执行,可读不可以写,可以被执行
__DATA 表示数据段,用于存储数据,可以读写,不可以执行
其中:
第一个段是__PAGEZERO 地址从0到0x100000000,程序保留字段。
3.1 段表内容含义
__TEXT段节名含义
|
|
__DATA段节名含义
|
|
3.2 后续符号表内容
3.2.1 代码节
|
|
这里面保存里类里面的方法内存情况。其中
- 第一列是起始地址位置,通过这个地址我们可以查上面的段表,可以知道,对应的节为
__text
。 - 第二列是大小,通过这个可以算出方法占用的大小。
- 第三列是归属的类(.o文件),这里序号是2,通过查类表可以知道对应的类是PAFFConfig。
通过这部分我们可以分析出来每个类对应的方法的大小是多少。
3.2.3 方法名节(__objc_methname
)
|
|
这部分保存了类里方法的字符串信息(所以原则上方法名起短一些,是可以减少占用的 - -!)
分析步骤:
- 查看第一列起始地址,然后在上面的段表中查看这个地址在那个节里,可以看到在
__objc_methname
中。 - 通过第二列对比大小
- 通过第三列解析对应的类和对应方法名称
类列表节(__objc_classlist
)
|
|
__objc_classlist
存储了所有类的虚拟地址。即__objc_data
地址。这里都是二进制数据,具体保存了什么,看下对应的数据结构
__objc_data
的数据结构为:
|
|
其中最主要的是data
字段,保存了_objc_const
节对应的数据地址。数据结构为:
|
|
这里面保存了类名,方法名,协议名,ivar指针和属性对应的地址。最后对应到相应的TEXT段里就能找到。比如类名在__objc_classname
可以找到,方法名可以在__objc_methname
。应用程序就是通过这个结构来寻找哪个类对应的那个方法,从而执行相关逻辑
如何找到没有用到的类和方法?
通过__objc_classrefs
和_objc_classname
对比就可以知道哪些类没用。其中__objc_classrefs
的解析需要通过otool命令才能解析
同理:
通过__objc_selrefs
和_objc_methname
对比可以知道哪些方法没有使用到。其中__objc_selrefs
需要用otool命令才能解析。
otool -v -s __DATA __objc_selrefs <path>
otool使用
这个用来做反汇编的,比如分析哪些类被使用了,需要用这个工具。
比如获取使用到的方法可以用这个命令:
otool -V -s __DATA __objc_selrefs <path> -arch arm64 | open -f
其中path是你的应用编译后生成的可执行文件。通常在项目的DerivedData目录下的Build/Products//.app文件,然后显示包内容,有个和工程同名的可执行文件。比如我的目录:
/Users/bolei/Library/Developer/Xcode/DerivedData/FFProject-gqpkbetfhlofkxcmyfwpmkfqubun/Build/Products/Release-iphoneos/FFProject.app/FFProject
打印使用到的类: _objc_classrefs
otool -V -o FFProject -arch arm64 | open -f
可以打印出来objc Section中的所有数据
代码参考
相关代码欢迎fork:https://github.com/dishibolei/iSee.git
主要功能包含了
- 代码占用分析
- 未使用类分析
- 未使用方法分析