dsym
當(dāng)APP發(fā)生crash的時(shí)候,??會(huì)生成一個(gè)crash report文件保存在設(shè)備上,我們可以通過Xcode導(dǎo)出,但是這個(gè)文件是unsymbolicated,需要解析之后才能進(jìn)行分析,這里就需要用到dsym文件。
dsym符號(hào)集
當(dāng)編譯器把目標(biāo)代碼編譯成機(jī)器碼的時(shí)候,它還生成調(diào)試符號(hào),將編譯二進(jìn)制中的每個(gè)機(jī)器指令映射回源代碼的對(duì)應(yīng)的位置。在Xcode中設(shè)置DEBUG_INFORMATION_FORMAT屬性可以調(diào)試符號(hào)是在二進(jìn)制文件中還是單獨(dú)的dsym文件,建議在debug模式選擇DWARF,因?yàn)樯?code>dsym文件對(duì)編譯時(shí)間會(huì)有一定的影響。
atos命令解析crash文件
atos是mac自帶的命令,關(guān)于命令的相關(guān)使用,在term輸入man atos即可。解析使用如下命令:
atos -arch arm64 -o TheElements.app.dSYM/Contents/Resources/DWARF/TheElements -l 0x1000e4000 0x00000001000effdc
-[AtomicElementViewController myTransitionDidStop:finished:context:]
- -arch:指令集,現(xiàn)在release的都包含arm64指令集架構(gòu)??梢酝ㄟ^
atool -hv appname查看相關(guān)的指令集; - -o :目標(biāo)文件:可執(zhí)行文件。
- -l :
load address,及發(fā)生crash對(duì)應(yīng)的鏡像起始地址;后面一個(gè)地址是symblicate address,及符號(hào)地址。
通過symbolicatecrash分析crash文件
Xcode有自帶的symbolicatecrash工具,可以通過dSYM文件將crash文件中的16進(jìn)制地址轉(zhuǎn)換成可讀的函數(shù)地址.
該文件是隱藏文件,可以通過如下命令查找并拷貝到系統(tǒng)目錄下,并建立快捷方式。
- 查找
symbolicatecrash目錄
$ find /Applications/Xcode.app -name symbolicatecrash -type f
-> $symbolicatecrashpath = /Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash
- 拷貝
symbolicatecrash到/usr/bin目錄下(不行的話可以手動(dòng)拷貝一下)
sudo cp $symbolicatecrashpath /usr/bin/symbolicatecrash
- 設(shè)置
DEVELOPER_DIR系統(tǒng)變量
vi ~/.bash_profile
## 輸入下面內(nèi)容
export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
## 保存后執(zhí)行
source .bash_profile
- 重啟終端,確認(rèn)設(shè)置
DEVELOPER_DIR系統(tǒng)變量
echo $DEVELOPER_DIR
-> /Applications/Xcode.app/Contents/Developer
- 使用如下命令,即可正確解析crash文件
symbolicatecrash appname.crash appname.app.dSYM > crash.txt
關(guān)于具體如何解析crash文件,下篇文章會(huì)有詳細(xì)介紹。
link map文件
link map文件是Xcode生成的鏈接映射文件,我們可以通過分析link map文件窺探二進(jìn)制文件中布局及所有文件信息,符號(hào)表等信息。例如我們可以知道每個(gè)文件運(yùn)行時(shí)所占用的空間,每個(gè)文件的方法等等。
XCode開啟編譯選項(xiàng)Write Link Map File
XCode -> Project -> Build Settings -> link map -> 把Write Link Map File選項(xiàng)設(shè)為yes, 如下圖所示。

然后找到上面默認(rèn)的文件位置(或者自定義位置),我們通過AFN的demo來查看下大致的結(jié)構(gòu):
# Path: /Users/jamy/Library/Developer/Xcode/DerivedData/AFNetworking-cmhenvqhrddnjtcnbkcxlqypctnc/Build/Products/Debug-iphonesimulator/AFNetworking.framework/AFNetworking
# Arch: x86_64
# Object files:
[ 0] linker synthesized
[ 1] /Users/jamy/Library/Developer/Xcode/DerivedData/AFNetworking-cmhenvqhrddnjtcnbkcxlqypctnc/Build/Intermediates.noindex/AFNetworking.build/Debug-iphonesimulator/AFNetworking iOS.build/Objects-normal/x86_64/UIProgressView+AFNetworking.o
[ 2] /Users/jamy/Library/Developer/Xcode/DerivedData/AFNetworking-cmhenvqhrddnjtcnbkcxlqypctnc/Build/Intermediates.noindex/AFNetworking.build/Debug-iphonesimulator/AFNetworking iOS.build/Objects-normal/x86_64/AFNetworkReachabilityManager.o
[ 3] /Users/jamy/Library/Developer/Xcode/DerivedData/AFNetworking-cmhenvqhrddnjtcnbkcxlqypctnc/Build/Intermediates.noindex/AFNetworking.build/Debug-iphonesimulator/AFNetworking iOS.build/Objects-normal/x86_64/UIRefreshControl+AFNetworking.o
.......
# Sections:
# Address Size Segment Section
0x000012C0 0x0003ABEC __TEXT __text
0x0003BEAC 0x0000033C __TEXT __stubs
0x0003C1E8 0x00000574 __TEXT __stub_helper
0x0003C75C 0x00000F1C __TEXT __gcc_except_tab
0x0003D680 0x000000B8 __TEXT __const
0x0003D738 0x000052A6 __TEXT __objc_methname
0x000429DE 0x00002DEA __TEXT __cstring
0x000457C8 0x00000475 __TEXT __objc_classname
0x00045C3D 0x0000106C __TEXT __objc_methtype
0x00046CAC 0x00000348 __TEXT __unwind_info
0x00047000 0x00000010 __DATA __nl_symbol_ptr
0x00047010 0x00000150 __DATA __got
0x00047160 0x00000450 __DATA __la_symbol_ptr
0x000475B0 0x00001180 __DATA __const
0x00048730 0x00001260 __DATA __cfstring
0x00049990 0x000000E0 __DATA __objc_classlist
0x00049A70 0x00000010 __DATA __objc_nlclslist
0x00049A80 0x00000050 __DATA __objc_catlist
0x00049AD0 0x00000078 __DATA __objc_protolist
0x00049B48 0x00000008 __DATA __objc_imageinfo
0x00049B50 0x000078E8 __DATA __objc_const
0x00051438 0x000014B0 __DATA __objc_selrefs
0x000528E8 0x00000018 __DATA __objc_protorefs
0x00052900 0x00000210 __DATA __objc_classrefs
0x00052B10 0x000000C8 __DATA __objc_superrefs
0x00052BD8 0x00000450 __DATA __objc_ivar
0x00053028 0x00000910 __DATA __objc_data
0x00053938 0x000005F8 __DATA __data
0x00053F30 0x00000240 __DATA __bss
.......
# Symbols:
# Address Size File Name
0x000012C0 0x00000070 [ 1] -[UIProgressView(AFNetworking) af_uploadProgressAnimated]
0x00001330 0x00000090 [ 1] -[UIProgressView(AFNetworking) af_setUploadProgressAnimated:]
....
0x00002040 0x00000290 [ 2] _AFStringFromNetworkReachabilityStatus
0x000022D0 0x000000B0 [ 2] +[AFNetworkReachabilityManager sharedManager]
0x00002380 0x00000050 [ 2] ___45+[AFNetworkReachabilityManager sharedManager]_block_invoke
.....
0x00003560 0x000000D0 [ 3] -[UIRefreshControl(AFNetworking) af_notificationObserver]
0x00003630 0x00000080 [ 3] -[UIRefreshControl(AFNetworking) setRefreshingWithStateOfTask:]
......
- Object files: 編譯后的目標(biāo)文件.o
- Sections:machO對(duì)應(yīng)的各個(gè)段,如__TEXT,__DATA,__LINK_EDITD等等。
- Symbols:符號(hào)相關(guān)信息,第一列是在文件中的偏移位置,第二列是大小,第三列是對(duì)應(yīng)的文件名[1.2.3]代表上面
Object files對(duì)應(yīng)的編號(hào)。如[1]代表[ 1] /Users/jamy/Library/Developer/Xcode/DerivedData/AFNetworking-cmhenvqhrddnjtcnbkcxlqypctnc/Build/Intermediates.noindex/AFNetworking.build/Debug-iphonesimulator/AFNetworking iOS.build/Objects-normal/x86_64/UIProgressView+AFNetworking.o文件。
每一行的數(shù)據(jù)都緊跟在上一行后面,如_AFStringFromNetworkReachabilityStatus的文件偏移位置是0x00002040,大小是0x00000290,相加就是下一列0x000022D0。
我們可以通過統(tǒng)計(jì)對(duì)應(yīng)的大小進(jìn)而知道使用的靜態(tài)庫之類的運(yùn)行時(shí)大小,從而做一些優(yōu)化。
reference
Understanding and Analyzing Application Crash Reports
iOS APP可執(zhí)行文件的組成