本文介紹瞭如何解析 iOS 的 crash 堆棧,分別使用了 symbolicatecrash
來自動解析整個堆棧,以及使用 atos
來解析單個地址的符號。在
iOS 開發中,解決 crash 問題是比較常見的工作。其中能夠解析出符號當然是定位問題的開始。實際工作中,也有看到很多人其實會卡在解析符號這裏,遇到這種情況,可以按照本文中的做法解決。
使用 symbolicatecrash 解析堆棧
symbolicatecrash
是
Xcode 自帶的 crash 符號解析工具,可以自動搜索本地符號表,解析整個 crash 堆棧。
確認 Xcode 環境
首先,需要確認 Xcode 的環境,執行以下代碼,獲取當前 Xcode 的目錄。
1
|
/usr/bin/xcode-select -print-path |
結果應該是:
1
|
/Applications/Xcode.app/Contents/Developer/ |
如果結果不是上述的路徑,則指定一下路徑:
1
|
sudo /usr/bin/xcode-select - switch /Applications/Xcode.app/Contents/Developer/ |
準備好解析堆棧符號的工具:symbolicatecrash
需要先找到 symbolicatecrash 所在的路徑,以 Xcode
7.3
版本爲例,執行:
1
|
find /Applications/Xcode.app -name symbolicatecrash -type f |
將會返回:
1
|
/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash |
可以做一個快捷方式:
1
|
alias symbolicatecrash= '/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash' |
需要先配置好 DEVELOPER_DIR
,否則會報錯。如下:
1
|
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer/ |
開始解析
準備好 dSYM 文件和 app 文件,可以存放在任何位置,只要 mac 系統的 spotlight 能夠找到就行。
接着執行
1
|
symbolicatecrash xxx.crash |
就可以解析符號了。
找不到符號的解決方法
首先,需要確認一下符號表是不是正確的。可以通過以下方式看看符號文件和堆棧是否是對應的 (判斷 uuid 是否相同):
1
2
3
|
dwarfdump --uuid MyApp.app/MyApp dwarfdump --uuid xxx.app.dSYM/Contents/Resources/DWARF/Resources/MyApp grep "0x.*com.wison.xxx .*<" NoSymbolsTestxxx.crash |
如果不一樣,那麼說明崩潰堆棧和符號文件對應不上,很可能是搞錯版本,或者打包的時候有問題導致符號文件生成不正確。
如果輸出一樣的 uuid,那麼就是對應的,此時 symbolicatecrash
應該可以正常解析符號。
如果還是不能正確解析,那麼很可能是 mdfind 自動查找的問題。
Xcode 找符號文件的時候,是通過 mdfind 來找的,比如:
1
|
mdfind 'com_apple_xcode_dsym_uuids = *' |
該命令會把當前環境下的所有符號文件找出來。
如果你的符號文件不在此列表中,說明 mdfind 找不到我們的符號,
那麼就在執行 symbolicatecrash
的時候顯式指定dSYM文件的路徑:
1
|
symbolicatecrash xxx.crash xxx.dSYM/Contents/Resources/DWARF/MyApp |
如果還是不能解析,試一試把 App 文件也指定:
1
|
symbolicatecrash xxx.crash xxx.dSYM/Contents/Resources/DWARF/MyApp MyApp.app/MyApp |
使用 atos 解析單個符號
有時候我們需要解析單個地址的符號,比如 lr
寄存器的地址對應的符號,就需要用到 atos
用法如下:
1
|
atos -arch [armv7 or arm64] -o [BinaryFile or dSYMFile] -l loadAddress address |
其中-arch
指定二進制的架構,比如
armv7,armv7s,arm64 等等。-o
指定符號文件,可以是
dSYM 文件,也可以是包含了符號表的可執行文件。-l
是加載地址,由於
Xcode 默認打開 PIE 選項,所以加載地址每次都不一樣,所以需要指定,可以在 crash 堆棧的 Binary Image 那段看到應用的加載地址。
最後一個參數是需要解析符號的地址。