最近看到一篇關于符號化iOS崩潰報告的文章挺好,決定翻一下,下方鏈接是原文地址:
https://possiblemobile.com/2015/03/symbolicating-your-ios-crash-reports/
開始
你已經(jīng)遞交你的應用程序的崩潰報告,但是棧回溯包含了難懂的內(nèi)存地址。開發(fā)者該怎么辦?簡而言之,你需要調(diào)試符號來應用于堆棧追蹤,從而使它人類可讀,這個過程我們稱作符號化。
在開始之前,我們依照使用Crasher,它提供了一個簡單崩潰報告,讓你破譯。
你應該有.crash文件。如果沒有,你可以從iTunes Connect中攫取,或者直接通過Xcode從連接的設備中攫取(Windows > Devices),或在一個連接的設備(Settings > Privacy > Diagnostics & Usage),或使用 PLCrashReporter 框架。你可能已經(jīng)使用了第三方的崩潰報告服務,在你配置正確后,它將符號化你的崩潰。
根據(jù)你的應用創(chuàng)建是如何配置的,你需要一個或者全部下面的東西:
0.導致崩潰的應用程序構建的.app文件。這個包包含了應用二進制文件,以及可能包含測試符號。(如果你有一個.ipa文件,你可以把它當做一個.zip文件,通過解壓這個文件把它提取出來)
1.導致崩潰的應用程序構建的.dSYM文件。這是你的應用程序的副產(chǎn)品,包含調(diào)試符號化。
你需要哪一個? 在 Xcode中,查找Build Setting里的 "Strip Debug Symbols During Copy"(COPY_PHASE_STRIP)。當允許時,調(diào)試符號將會從你的.app省去,把它放到了.dSYM文件。否則你的.app包含這些符號。(默認情況下, 由于某些不清楚的原因,調(diào)試符號從釋放的創(chuàng)建中剝離,你可能不應該改變這個發(fā)布配置)
但是等等,什么是調(diào)試符號?
為了讓調(diào)試符號變成人類可讀的即程序員給方法命名的名稱,編譯器通過使用它自己的符號來減少這些命名的調(diào)試符號,從而使代碼模糊。即使兩次相同代碼創(chuàng)建,你也不能依賴這些符號。
檢查崩潰
如果通過Xcode的Organizer從設備中提交崩潰報告,你的崩潰報告可能將會對UIKit和其他iOS框架自動符號化。如果Xcode知道你的創(chuàng)建,他將自動符號化你的崩潰。
如果不是這種情況,你需要自己符號化。
使用"Symbolicatecrash"工具來符號化
幸運的是,蘋果提供給了我們腳本來檢索調(diào)試符號化,將他們應用于崩潰報告。
對 Xcode 6,你可以在下面目錄里找到這個工具:
/Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/Current/Resources/symbolicatecrash
或者如果你使用的是Xcode 5 從下方路徑獲得:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKitBase.framework/Versions/Current/Resources/symbolicatecrash
為了使用這個工具,你需要用安裝Xcode恰當路徑導出 DEVELOPER_DIR 環(huán)境變量:
export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
把你的.crash文件.app文件和.dSYM文件放在同一個目錄下然后運行:
symbolicatecrash -v ScaryCrash.crash > Symbolicated.crash
你可能需要顯示應用應用程序二進制:
symbolicatecrash -v ScaryCrash.crash ./Crasher.app/Crasher > Symbolicated.crash
如果你使用在Crasher例子中發(fā)現(xiàn)的便利腳本,需要冗長的標記:
sh symbolicate6.sh ScaryCrash.crash ./Crasher.app/Crasher > Symbolicated.crash
如果你使用在Crasher例子中發(fā)現(xiàn)的便利腳本,需要冗長的標記:
sh symbolicate6.sh ScaryCrash.crash ./Crasher.app/Crasher > Symbolicated.crash
驗證符號化
如果符號化不能工作,仔細檢查你攫取的.dSYM或者.app文件是否正確。你可以通過交叉引用崩潰的報告中的UUID和應用程序二進制中的UUID:
dwarfdump –uuid Crasher.app/Crasher
結果:

在dSYM文件中:
dwarfdump –uuid Crasher.app.dSYM/Contents/Resources/DWARF/Crasher
結果:

和你的崩潰報告中的UUID進行比較:

從symbolicatecrash工具冗長的日志里,同樣列出它找出的UUID。
排查 "Symbolicatecrash" 工具
如果你還是困惑,請認真檢查symbolication日志。symbolication工具嘗試找出你應用中與UUID相匹配的相應文件以及每個動態(tài)框架,尋找著你的應用程序名稱或者UUID 并看出是否匹配。

如果Spotlight不能找到你的.dSYM文件,你可能碰到這樣一個日志樣例:

或者有一個無效的.dSYM:

或者有任何其他無效的輸入:

在Xcode 6 版本中的symbolicatecrash工具嘗試解決一些再Xcode 5 版本中面臨的Spotlight問題。如果你遇到問題,他可能是Spotlight中一個文件的索引問題,嘗試:
mdimport -g /Applications/Xcode.app/Contents/Library/Spotlight/uuid.mdimporter .
使用命令行工具鏈
我們可以深入 和使用開發(fā)者命令行工具鏈來一行行的符號化棧追蹤的內(nèi)存地址。如果你在過去使用這個方法中遇到問題,那可能是因為在最近幾年.crash文件根式改變了。
首先,讓我們再看看我們崩潰報考中的棧追蹤:

最左邊的十六進制值,0x000aeef6,是棧地址。第二個十六進制值,0xa8000,是應用程序的加載地址。以加號為開始的數(shù)字,28406,是棧地址和加載地址的差值。 0x00aeef6 = 0xa8000 + 0x6EF6
。你將會發(fā)現(xiàn)在我們的崩潰報告底部的“Binary Images”,它是動態(tài)庫內(nèi)存地址范圍列表。我們的二進制文件的起始地址在堆棧跟蹤加載地址相匹配。

下一步,為了更好的測量,我們將驗證可執(zhí)行文件包含蹦潰的架構,不論使用file或者lipo -info命令:
file Crasher.app/Crasher
結果:

現(xiàn)在我們?nèi)蔽溲b。我們經(jīng)查實atos命令來將我們的地址轉(zhuǎn)換成調(diào)試符號。注意我們?nèi)绾翁峁┘虞d地址,它在我們指定崩潰的架構的棧地址后面:
atos -arch armv7 -o Crasher.app/Crasher -l 0xa8000 0x000aeef6
結果:

就是這樣。如果你有興趣繼續(xù)鉆研,研讀Mach-O對象文件格式以及Mach-O命令行實用工具,也就是otool和lipo命令。
更多閱讀
更多全面的文檔,請查看:
Technical Note TN2151: Understanding and Analyzing iOS Application Crash Reports
Technical Q&A QA1765: How to Match a Crash Report to a Build
Mach-O Programming Topics
Objc.io on Mach-O Executables