分析iOS APP可执行文件(Link Map)

iOS 编译后,引入的一些第3方库都会被编译到可执行文件内,可执行文件相当于windows电脑下载 exe文件。

下面将介绍这个可执行文件的构成,分析一下那些库占用空间大,方法如下:

1、开启Write Link Map File

XCode -> Project -> Build Settings -> 搜索map关键词 -> 把Write Link Map File选项设为Yes,并指定好linkMap的存储位置(默认有路径,txt文件)




2、编译之后,找到对应的txt文件

上述的Path to Link Map File位于:(以arm64命令集为例)

~/Library/Developer/Xcode/DerivedData/项目名称-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/ArchiveIntermediates/项目名/IntermediateBuildFilesPath/项目名称.build/Debug-iphoneos/项目名称.build/项目名称-LinkMap-normal-arm64.txt

这个LinkMap里展示了全部可执行文件的全貌,列出了编译后的每个.o文件的信息(包括静态链接库.a里的),以及每一个目标文件的代码段,数据段存储详情。

以TestApp项目为例,在LinkMap里首先列出来的是目标文件列表:

# Path: /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Products/Debug-iphoneos/TestApp.app/TestApp
# Arch: arm64
# Object files:
[  0] linker synthesized
[  1] dtrace
[  2] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/AppDelegate+NIM.o
[  3] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/AppDelegate+XCLConstantsConfig.o
[  4] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/AppDelegate.o
[  5] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/XCLLaunchScreenViewController.o
[  6] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/AppDelegate+Share.o
[  7] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/AppDelegate+XCLRouter.o
[  8] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/AppDelegate+EaseMob.o
[  9] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/AppDelegate+SensorsAnalytics.o
[ 10] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/AppDelegate+XCLRootViewController.o
[ 11] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/main.o
[ 12] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/AppDelegate+PadConfig.o
[ 13] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Intermediates.noindex/TestApp.build/Debug-iphoneos/TestApp.build/Objects-normal/arm64/AppDelegate+XCLDataBase.o
[ 14] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Products/Debug-iphoneos/AFNetworking/libAFNetworking.a(AFAutoPurgingImageCache.o)
[ 15] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Products/Debug-iphoneos/AFNetworking/libAFNetworking.a(AFHTTPSessionManager.o)
[ 16] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Products/Debug-iphoneos/AFNetworking/libAFNetworking.a(AFImageDownloader.o)
[ 17] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Products/Debug-iphoneos/AFNetworking/libAFNetworking.a(AFNetworkActivityIndicatorManager.o)
[ 18] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Products/Debug-iphoneos/AFNetworking/libAFNetworking.a(AFNetworking-dummy.o)
[ 19] /Users/lmy/Library/Developer/Xcode/DerivedData/TestApp-aodmtzoayqjaqicjfnybtopdiamz/Build/Products/Debug-iphoneos/AFNetworking/libAFNetworking.a(AFNetworkReachabilityManager.o)
...

中括号里的是这个文件的编号,后面会用到,像项目里引用到静态链接库libAFNetworking.a里的目标文件都会在这里列出来。

接着是一个段表,描述各个段在最后编译成的可执行文件中的偏移位置及大小,包括了代码段(__TEXT,保存程序代码段编译后的机器码)和数据段(__DATA,保存变量值)

# Sections:
# Address   Size        Segment Section
0x100004800 0x01FD335C  __TEXT  __text
0x101FD7B5C 0x00004404  __TEXT  __stubs
0x101FDBF60 0x00003A74  __TEXT  __stub_helper
0x101FDF9D4 0x000B8150  __TEXT  __gcc_except_tab
0x102097B30 0x00138DF9  __TEXT  __cstring
0x1021D0929 0x000B096C  __TEXT  __objc_methname
0x102281296 0x0000DED0  __TEXT  __ustring
0x10228F166 0x00011591  __TEXT  __objc_classname
0x1022A06F7 0x000185FF  __TEXT  __objc_methtype
0x1022B8D00 0x000A3618  __TEXT  __const
0x10235C318 0x0000037B  __TEXT  __dof_RACSignal
0x10235C693 0x000002E8  __TEXT  __dof_RACCompou
0x10235C97C 0x00036F78  __TEXT  __unwind_info
0x1023938F8 0x000006E4  __TEXT  __eh_frame
0x102394000 0x00001688  __DATA  __got
0x102395688 0x00002D58  __DATA  __la_symbol_ptr
0x1023983E0 0x000004B8  __DATA  __mod_init_func
0x1023988A0 0x000CC8A8  __DATA  __const
0x102465148 0x000674E0  __DATA  __cfstring
0x1024CC628 0x00004D98  __DATA  __objc_classlist
0x1024D13C0 0x000000A8  __DATA  __objc_nlclslist
0x1024D1468 0x00000850  __DATA  __objc_catlist
0x1024D1CB8 0x00000030  __DATA  __objc_nlcatlist
0x1024D1CE8 0x000008D8  __DATA  __objc_protolist
0x1024D25C0 0x00000008  __DATA  __objc_imageinfo
0x1024D25C8 0x00244FD0  __DATA  __objc_const
0x102717598 0x00027030  __DATA  __objc_selrefs
0x10273E5C8 0x00000120  __DATA  __objc_protorefs
0x10273E6E8 0x00004A10  __DATA  __objc_classrefs
0x1027430F8 0x000030F0  __DATA  __objc_superrefs
0x1027461E8 0x0000DD10  __DATA  __objc_ivar
0x102753EF8 0x00030840  __DATA  __objc_data
0x102784740 0x000CD4A0  __DATA  __data
0x102851BE0 0x00114168  __DATA  __bss
0x102966000 0x000DC020  __DATA  __common

首列是数据在文件的偏移位置,
第二列是这一段占用大小,
第三列是段类型,代码段和数据段,
第四列是段名称。

每一行的数据都紧跟在上一行后面,如第二行__symbol_stub的地址0x00275FD0就是第一行__text的地址0x00002740加上大小0x00273890,整个可执行文件大致数据分布就是这样。

这里可以清楚看到各种类型的数据在最终可执行文件里占的比例,例如__text表示编译后的程序执行语句,__data表示已初始化的全局变量和局部静态变量,__bss表示未初始化的全局变量和局部静态变量,__cstring表示代码里的字符串常量,等等。

接着就是按上表顺序,列出具体的按每个文件列出每个对应字段的位置和占用空间

# Sections:
# Address   Size        Segment Section
0x100004800 0x01FD335C  __TEXT  __text
0x101FD7B5C 0x00004404  __TEXT  __stubs
0x101FDBF60 0x00003A74  __TEXT  __stub_helper
0x101FDF9D4 0x000B8150  __TEXT  __gcc_except_tab
0x102097B30 0x00138DF9  __TEXT  __cstring
0x1021D0929 0x000B096C  __TEXT  __objc_methname
0x102281296 0x0000DED0  __TEXT  __ustring
0x10228F166 0x00011591  __TEXT  __objc_classname
0x1022A06F7 0x000185FF  __TEXT  __objc_methtype
0x1022B8D00 0x000A3618  __TEXT  __const
0x10235C318 0x0000037B  __TEXT  __dof_RACSignal
0x10235C693 0x000002E8  __TEXT  __dof_RACCompou
0x10235C97C 0x00036F78  __TEXT  __unwind_info
0x1023938F8 0x000006E4  __TEXT  __eh_frame
0x102394000 0x00001688  __DATA  __got
0x102395688 0x00002D58  __DATA  __la_symbol_ptr
0x1023983E0 0x000004B8  __DATA  __mod_init_func
0x1023988A0 0x000CC8A8  __DATA  __const
0x102465148 0x000674E0  __DATA  __cfstring
0x1024CC628 0x00004D98  __DATA  __objc_classlist
0x1024D13C0 0x000000A8  __DATA  __objc_nlclslist
0x1024D1468 0x00000850  __DATA  __objc_catlist
0x1024D1CB8 0x00000030  __DATA  __objc_nlcatlist
0x1024D1CE8 0x000008D8  __DATA  __objc_protolist
0x1024D25C0 0x00000008  __DATA  __objc_imageinfo
0x1024D25C8 0x00244FD0  __DATA  __objc_const
0x102717598 0x00027030  __DATA  __objc_selrefs
0x10273E5C8 0x00000120  __DATA  __objc_protorefs
0x10273E6E8 0x00004A10  __DATA  __objc_classrefs
0x1027430F8 0x000030F0  __DATA  __objc_superrefs
0x1027461E8 0x0000DD10  __DATA  __objc_ivar
0x102753EF8 0x00030840  __DATA  __objc_data
0x102784740 0x000CD4A0  __DATA  __data
0x102851BE0 0x00114168  __DATA  __bss
0x102966000 0x000DC020  __DATA  __common

同样首列是数据在文件的偏移地址,第二列是占用大小,第三列是所属文件序号,对应上述Object files列表,最后是名字。
例如第二行代表了文件序号为2(反查上面就是TKPFileInfo.o)的parseWithDictionary方法占用了1000byte大小。

这个文件可以让你了解整个APP编译后的情况,也许从中可以发现一些异常,还可以用这个文件计算静态链接库在项目里占的大小,有时候我们在项目里链了很多第三方库,导致APP体积变大很多,我们想确切知道每个库占用了多大空间,可以给我们优化提供方向。LinkMap里有了每个目标文件每个方法每个数据的占用大小数据,所以只要写个脚本,就可以统计出每个.o最后的大小,属于一个.a静态链接库的.o加起来,就是这个库在APP里占用的空间大小。

文件分析工具:# LinkMap

https://github.com/jayden320/LinkMap


LinkMap解析工具:检查每个类占用大小

一个大型的项目,只是代码段就有可能超过100M,算上armv7和arm64架构,就会超过200M。 这时候检查到底是哪个类、哪个第三方库占用了太多空间,就显得尤为重要。

这个工具是专为用来分析项目的LinkMap文件,得出每个类或者库所占用的空间大小(代码段+数据段),方便开发者快速定位需要优化的类或静态库。

使用说明

1、打开LinkMap.xcodeproj,并运行,就可以看到工具界面




2、点击“选择文件”按钮,选择LinkMap文件(如何生成LinkMap详见下方的:如何获得LinkMap文件)

3、点击“开始”按钮,就可以看到每个类/静态库所占用的空间大小



4、点击“输出文件”,可以将结果输出到文本文档中

展开阅读全文

页面更新:2024-04-30

标签:静态   大小   名称   位置   目标   代码   文件   项目   数据   空间

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top