開發(fā)中經(jīng)常遇到蘋果反饋的崩潰報(bào)告,絕大部分都是沒有經(jīng)過符號(hào)化的報(bào)告行瑞,看起來一頭霧水排查問題也不知道如何下手嘹朗,經(jīng)過詳細(xì)翻閱蘋果官方文檔以及經(jīng)過親身實(shí)踐后,整理出來分析未經(jīng)符號(hào)化報(bào)告的幾種方法诲侮,記錄下來镀虐,方便自己方便他人~
重要提醒:如果項(xiàng)目中開啟了bitcode模式,那么在分析線上崩潰的時(shí)候一定要去更新下自己的dSYM文件沟绪,因?yàn)殚_啟bitcode發(fā)布的包刮便,在你本機(jī)上編譯之后的版本并不是最終發(fā)布給用戶的版本,從你本機(jī)上傳至APPStore之后绽慈,APPStore會(huì)再次編譯該應(yīng)用包恨旱,然后分發(fā)給用戶,所以用戶拿到的包跟你編譯提交至APPStore的包并不一致久信,你也無法使用你編譯產(chǎn)生的dSYM文件來符號(hào)化線上蘋果返回給你的崩潰報(bào)告窖杀。
我將創(chuàng)建一個(gè)測試的APP,用來模擬程序的崩潰裙士,然后從手機(jī)端獲取到未符號(hào)化的崩潰報(bào)告入客,然后我們將使用三種方法將未符號(hào)化的報(bào)告符號(hào)化來分析問題所在。
先看簡單的引起崩潰的代碼:
很簡單的一個(gè)數(shù)組越界腿椎,在手機(jī)端運(yùn)行之后導(dǎo)出未符號(hào)化的崩潰報(bào)告保存在電腦上桌硫,這個(gè)過程模擬我們從APPStore獲取到崩潰報(bào)告之后保存下來的行為,切記保存的格式為xxx.crash 文件啃炸。
先看一下完全沒有符號(hào)化的崩潰報(bào)告:
沒有任何參考意義铆隘,只是一堆十六進(jìn)制的地址名,所以我們需要使用和這個(gè)編譯包對應(yīng)的符號(hào)表來符號(hào)化出來一個(gè)有參考意義的崩潰報(bào)告南用。一共有三種方法膀钠,逐個(gè)嘗試。
一裹虫、使用Xcode來符號(hào)化崩潰報(bào)告
使用Xcode自帶的符號(hào)化功能進(jìn)行符號(hào)化也是官方比較推薦的一種做法肿嘲,會(huì)檢索你本機(jī)上的所有可用的符號(hào)化表進(jìn)行符號(hào)化,具體步驟如下:
復(fù)制蘋果給的報(bào)錯(cuò)報(bào)告筑公,可以直接在網(wǎng)頁右鍵雳窟,保存為.carsh格式,然后直接拖動(dòng)到手機(jī)端端deviceLog列表匣屡,進(jìn)行符號(hào)化的操作封救,就可以看到部分內(nèi)容被符號(hào)化拇涤,然后搜尋關(guān)鍵的信息排查問題。
手機(jī)連接Xcode, 打開手機(jī)端的報(bào)告列表
拖動(dòng)我們創(chuàng)建好的crash文件進(jìn)入列表
如果沒有符號(hào)化的話直接右鍵重新符號(hào)化一下誉结,然后查看就可以鹅士。
可以看到報(bào)錯(cuò)的方法名及崩潰原因:
二 使用命令行符號(hào)化崩潰報(bào)告
使用命令行和使用Xcode自帶的符號(hào)化工具類似,我們演示一下如果操作搓彻。
使用命令行進(jìn)行崩潰報(bào)告符號(hào)化需要以下四個(gè)文件:
- crash文件
- symbolicatecrash工具
- dSYM包
- APP安裝包文件
我們一個(gè)一個(gè)來找如绸,其實(shí)很簡單。
首先建立一個(gè)空的文件夾旭贬,把我們導(dǎo)出來的未符號(hào)化的崩潰報(bào)告放進(jìn)去,命名為TestCrash.crash搪泳。
1.crash文件
這個(gè)文件就是我們導(dǎo)出來的未符號(hào)化的崩潰報(bào)告TestCrash.crash稀轨,已經(jīng)有了。
2.symbolicatecrash工具
這個(gè)工具的目錄地址為:
/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash
使用命令行直接open /Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/
然后把symbolicatecrash這個(gè)文件拷貝至我們準(zhǔn)備的文件夾里就可以岸军。
3.dSYM包和APP安裝包文件
dSYM包和APP安裝包文件在一個(gè)地方奋刽,我們看下如何查找。
首先我們使用命令行cd到我們建立的文件夾下艰赞,此時(shí)里面有兩個(gè)文件
- 獲取匹配使用的UUID
使用命令行
grep --after-context=1000 "Binary Images:" <Path to Crash Report> | grep <Binary Name>
來獲取到我們需要的跟dSYM匹配的UDID佣谐,我的APP命名為TestCrash,使用示例如下:
grep --after-context=1000 "Binary Images:" TestCrash.crash | grep TestCrash
可以看到輸出為:
其中的c9c5a77b053f35a7b136d0036ca74da3就是APP對應(yīng)的UDID方妖,接下來將這個(gè)小心的UDID格式化為全部大小的各位為8—4-4-4-12位的編碼狭魂,如下:
C9C5A77B-053F-35A7-B136-D0036CA74DA3
- 查找對應(yīng)dSYM文件的位置
然后我們使用命令mdfind來查找對應(yīng)dSYM文件的位置:
mdfind "com_apple_xcode_dsym_uuids == <UUID>"
使用示例如下:
mdfind "com_apple_xcode_dsym_uuids == C9C5A77B-053F-35A7-B136-D0036CA74DA3"
可以看到輸出了dSYM文件的地址,然后我們open到這個(gè)地址,可以看到:
我們需要的dSYM包和APP安裝包文件就是這兩個(gè)了
(這種方式找到的dSYM包精準(zhǔn)度比較高党觅,還有比較簡單的方式在文末會(huì)介紹雌澄,這種使用簡單的方式介紹找到的包也一定要記得驗(yàn)證UUID)
把他們也全部拷貝到我們建立的文件夾里。
此時(shí)我們需要的四個(gè)文件全部都有了杯瞻,我們建立的文件夾里的文件如下:
在進(jìn)行最后一步前镐牺,我們先驗(yàn)證一下這幾個(gè)文件的UUID是否匹配,如果不匹配的話我們符號(hào)化出來的報(bào)告是沒有意義的魁莉。
重新cd到我們建立的文件夾里:
- 獲取dSYM的UDID:
執(zhí)行命令格式如下:
dwarfdump --uuid <PathToDSYMFile>/Contents/Resources/DWARF/<BinaryName>
使用示例如下:
dwarfdump --uuid TestCrash.app.dSYM/Contents/Resources/DWARF/TestCrash
結(jié)果如下:
可以看到睬涧,dSYM的UUID為:C9C5A77B-053F-35A7-B136-D0036CA74DA3
- 獲取APP文件的UDID:
執(zhí)行命令格式如下:
dwarfdump --uuid <PathToBinary>
使用示例如下:
dwarfdump --uuid TestCrash.app/TestCrash
結(jié)果如下:
可以看到,APP文件的UDID為:C9C5A77B-053F-35A7-B136-D0036CA74DA3
所以:
我們最開始從crash文件里獲取到的UDID為:C9C5A77B-053F-35A7-B136-D0036CA74DA3
dSYM文件里的UDID為:C9C5A77B-053F-35A7-B136-D0036CA74DA3
APP文件里的UDID為:C9C5A77B-053F-35A7-B136-D0036CA74DA3
這一套文件是匹配的旗唁,我們就可以進(jìn)行最終的符號(hào)化操作了畦浓。
使用如下命令進(jìn)行符號(hào)化:
symbolicatecrash TestCrash.crash TestCrash.app.dSYM > log.crash
執(zhí)行的過程中如果提示報(bào)錯(cuò):
則執(zhí)行:
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
然后重新執(zhí)行
symbolicatecrash TestCrash.crash TestCrash.app.dSYM > log.crash
幾秒鐘之后在查看我們的文件夾里會(huì)發(fā)現(xiàn)多了一個(gè)log.crash文件
這個(gè)就是我們符號(hào)化好的崩潰報(bào)告,打開如下:
OK,可以愉快的分析問題所在了~
三 終極操作-針對某一行地址使用命令行符號(hào)化
崩潰報(bào)告會(huì)反饋給我們當(dāng)程序崩潰的時(shí)候操作系統(tǒng)正在執(zhí)行的所有操作逆皮,如果針對某個(gè)線程的某個(gè)操作比較感興趣宅粥,但是符號(hào)化列表又沒有進(jìn)行符號(hào)化,此時(shí)我們可以通過命令行針對性的去符號(hào)化某一行十六進(jìn)制地址电谣,看看他代表的是什么類型的什么任務(wù)秽梅。
使用命令行符號(hào)化某一行代碼使用的文件比較少抹蚀,僅僅需要dSYM文件就可以了。(如何獲取dSYM文件請參照第二種方法的部分內(nèi)容)
假如我們想看看崩潰報(bào)告里的這一行地址代表的信息:
需要使用如下命令:
atos -arch <BinaryArchitecture> -o <PathToDSYMFile>/Contents/Resources/DWARF/<BinaryName> -l <LoadAddress> <AddressesToSymbolicate>
幾個(gè)參數(shù)取值如下:
BinaryArchitecture
查看最后一列標(biāo)記的TestCrash的Architecture
就是它
PathToDSYMFile
dSYM文件地址
BinaryName
APP文件名
LoadAddress和AddressesToSymbolicate
所以使用示例如下:
cd到dSYM文件所在的文件夾企垦,執(zhí)行
atos -arch arm64 -o TestCrash.app.dSYM/Contents/Resources/DWARF/TestCrash -l 0x1044c4000 0x00000001044ca2c4
結(jié)果如下:
此時(shí)這一行十六進(jìn)制編碼對應(yīng)的信息就符號(hào)化出來了环壤。
補(bǔ)充:另一種獲取dSYM文件的方法:
dSYM文件:
APP文件:
用這種方法找到的dSYM文件和APP文件一定要記得根據(jù)第二種方法里的操作驗(yàn)證一下UUID,否則符號(hào)化出來的報(bào)告是沒有意義的钞诡。