LinkMap
文件是 Xcode
产生可执行文件的同时生成的链接信息,用来描述可执行文件的构造成分,包括代码段 __TEXT
和数据段 __DATA
的分布情况。只要设置 Project->Build Settings->Write Link Map File
为 YES
,并设置 Path to Link Map File
,build
完后就可以在设置的路径看到 LinkMap
文件了:
image.png
LinkMap
的路径:
/Users/XXXX/Library/Developer/Xcode/DerivedData/XXXX-boyphtjpmytnckgosnyjctscvngm/Build/Intermediates.noindex/XXXX.build/Debug-iphoneos/XXXX.build/XXXX-LinkMap-normal-arm64.txt
一份完整的 LinkMap
文件中包含了一下几个部分:
# Path: /Users/XXXX/Library/Developer/Xcode/DerivedData/XXXX-boyphtjpmytnckgosnyjctscvngm/Build/Products/Debug-iphoneos/XXXXapp/XXXX
# Arch: arm64
# Object files:
[ 0] linker synthesized
[ 1] /Users/XXXX/Library/Developer/Xcode/DerivedData/XXXX-boyphtjpmytnckgosnyjctscvngm/Build/Intermediates.noindex/XXXX.build/Debug-iphoneos/XXXX.build/Objects-normal/arm64/QMGameReport.o
[ 2] /Users/XXXX/Library/Developer/Xcode/DerivedData/XXXX-boyphtjpmytnckgosnyjctscvngm/Build/Intermediates.noindex/XXXX.build/Debug-iphoneos/XXXX.build/Objects-normal/arm64/QMNewAnimationManager.o
[ 3] /Users/XXXX/Library/Developer/Xcode/DerivedData/XXXX-boyphtjpmytnckgosnyjctscvngm/Build/Intermediates.noindex/XXXX.build/Debug-iphoneos/XXXX.build/Objects-normal/arm64/QMCocosAnimationView.o
...
第一部分列举可执行文件里所有链接的 .o
文件,以及每个文件的编号。
# Sections:
# Address Size Segment Section
0x100004180 0x027ECF28 __TEXT __text
0x1027F10A8 0x00005130 __TEXT __stubs
0x1027F61D8 0x000048B4 __TEXT __stub_helper
0x1027FAAA0 0x00131318 __TEXT __const
0x10292BDC0 0x0018FFDF __TEXT __cstring
0x102ABBDA0 0x0001839E __TEXT __ustring
0x102AD413E 0x000EC936 __TEXT __objc_methname
0x102BC0A74 0x00013E5F __TEXT __objc_classname
0x102BD48D3 0x00023F8A __TEXT __objc_methtype
0x102BF8860 0x00106C50 __TEXT __gcc_except_tab
0x102CFF4B0 0x0004FF6C __TEXT __unwind_info
0x102D4F420 0x00000BBC __TEXT __eh_frame
0x102D50000 0x00001A30 __DATA __got
0x102D51A30 0x00003620 __DATA __la_symbol_ptr
0x102D55050 0x000003D8 __DATA __mod_init_func
0x102D55428 0x00000008 __DATA __mod_term_func
0x102D55430 0x000DFAC0 __DATA __const
0x102E34EF0 0x00097920 __DATA __cfstring
0x102ECC810 0x00006430 __DATA __objc_classlist
0x102ED2C40 0x000000C0 __DATA __objc_nlclslist
0x102ED2D00 0x00000958 __DATA __objc_catlist
0x102ED3658 0x00000108 __DATA __objc_nlcatlist
0x102ED3760 0x000012B8 __DATA __objc_protolist
0x102ED4A18 0x00000008 __DATA __objc_imageinfo
0x102ED4A20 0x0033CE60 __DATA __objc_const
0x103211880 0x0003B238 __DATA __objc_selrefs
0x10324CAB8 0x000000A0 __DATA __objc_protorefs
0x10324CB58 0x00005F78 __DATA __objc_classrefs
0x103252AD0 0x00004400 __DATA __objc_superrefs
0x103256ED0 0x000126B0 __DATA __objc_ivar
0x103269580 0x0003EA30 __DATA __objc_data
0x1032A7FC0 0x000C89E0 __DATA __data
0x1033709A0 0x00310E68 __DATA __bss
0x103682000 0x00104C40 __DATA __common
第二部分是可执行文件的段表,描述各个段在可执行文件中的地址和大小,段类型以及段名称。第一列是段的地址,第二列是段占用大小;第三列是段类型,代码段和数据段,数据类型分为两种不同类型,一种是 __TEXT
,用于保存程序代码段经过编译后的机器码,另外一种是 __DATA
用于保存诸如全局变量或者局部变量;第四列是段名称,如 __text
段是可执行机器码,__cstring
段是字符串常量, __bss
表示未初始化的全局变量及局部静态变量,__const
表示的是对应的不可变的变量。当然这一切的数据都是文件占用空间,并不是运行时的占用空间。
# Symbols:
# Address Size File Name
0x100004180 0x000002A4 [ 1] -[QMGameReport initWithFrame:isNightMode:]
0x100004424 0x00000264 [ 1] -[QMGameReport setConnerRadiusForBackgroundView]
0x100004688 0x00000034 [ 1] _CGSizeMake
0x1000046BC 0x00000120 [ 1] -[QMGameReport showInView:]
0x1000047DC 0x00000040 [ 1] ___27-[QMGameReport showInView:]_block_invoke
0x10000481C 0x0000004C [ 1] ___copy_helper_block_
0x100004868 0x00000030 [ 1] ___destroy_helper_block_
0x100004898 0x00000064 [ 1] -[QMGameReport tapClick:]
0x1000048FC 0x000001F0 [ 1] -[QMGameReport dismiss]
0x100004AEC 0x00000040 [ 1] ___23-[QMGameReport dismiss]_block_invoke
0x100004B2C 0x0000004C [ 1] ___copy_helper_block_.276
0x100004B78 0x00000030 [ 1] ___destroy_helper_block_.277
0x100004BA8 0x00000040 [ 1] ___23-[QMGameReport dismiss]_block_invoke.279
0x100004BE8 0x0000004C [ 1] ___copy_helper_block_.282
0x100004C34 0x00000030 [ 1] ___destroy_helper_block_.283
0x100004C64 0x00000AFC [ 1] -[QMGameReport setUpconfigItem]
0x100005760 0x0000005C [ 1] _CGRectMake
0x1000057BC 0x0000039C [ 1] -[QMGameReport reportAction:]
...
第三部分详细描述每个 .o
文件在每个段的分布情况,按第二部分 Sections
顺序展示。例如序号 1
的 QMGameReport.o
文件,-[QMGameReport initWithFrame:isNightMode:]
方法在 __TEXT
的 Segment
里面 .__text
的 Section
段地址是 0x100004180
,占用大小是116字节。根据序号累加每个 .o
文件在每个段的占用大小,从而计算出每个 .o
文件在可执行文件的占用大小,进而算出每个静态库、每个功能模块代码占用大小。
这里要注意的地方是,由于 __DATA
的 Segment
里面 .__bbs
的 Section
是代表未初始化的静态变量,Size
表示应用运行时占用的堆大小,并不占用可执行文件,所以计算 .o
占用大小时,要排除这个段的 Size
。