淺談 LinkMap 檢查每個類佔用大小
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
檔案中包含了一下幾個部分:
App的編譯路徑(#Path)
# Path: /Users/XXXX/Library/Developer/Xcode/DerivedData/XXXX-boyphtjpmytnckgosnyjctscvngm/Build/Products/Debug-iphoneos/XXXXapp/XXXX
App對應的架構(#Arch)
# Arch: arm64
Object files:
# 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:
# Sections: # AddressSizeSegment 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:
# Symbols: # AddressSizeFileName 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
。