解析 crash log(一)

PJHubs_xx發表於2019-03-18

原文地址:PJ 的 iOS 開發之路

前言

在負責的產品中有最近一段時間有極個別使用者老是反饋有偶爾閃退的情況,而且就這幾個使用者反覆出現,其它使用者,甚至就坐在他邊上的使用者進行了一樣的操作都沒有任何問題。

剛開始丟了個重現構建的新包給這幾位使用者將就的用著,但直到今天 PM 受不了了,讓我無論如何都要想辦法解決這個問題,但我也一臉懵逼啊,按照使用者的操作路徑來看我也沒能復現,甚至分析平臺都抓不到對應資訊,更何況這還是個企業級應用,沒上到 AppStore,也就沒法從 iTunes Connect 中拿到崩潰日誌。

所以開始醞釀了一個事情......

分析問題

為了快速定位到問題所在,PM 和 leader 再三的跟使用者進行交流,大家都沒有一個比較好的方案,最後我厚著臉皮讓使用者照著下面這張圖從裝置中匯出了一份崩潰日誌傳送給我:

圖1 從裝置中匯出日誌的步驟

從真機中拿到這份 ips 檔案後就好辦了很多,如果此時直接開啟這個檔案,可以看到如下圖所示內容:

圖2 未符號化內容

能夠拿到真機的情況下,

  • 在不刪掉 app 的情況下直接除錯;
  • 無法復現問題,則把真機插入電腦,開啟 Xcode -> Window -> Devices and Simulators -> View Device Logs,直接找到需要的 log;

在拿不到真機的情況下,先來直接講解一個能夠解決問題的流程:

第一步:ips 檔案

“死皮賴臉”的讓使用者通過圖 1 所示方法匯出一份最新的 .ips 檔案,並讓使用者分享給自己,並把檔名修改為 .crash 字尾,使其標識為 crash 型別;

第二步:.dSYM 檔案

.dSYM 檔案(debugging SYMBols,除錯符號表)。從打包機(如果是通過打包機隔離構建的話)或本機上匯出一份與使用者裝置中安裝的 app 版本一致的 .dSYM 檔案,該檔案中詳細的記錄了 16 進位制下的函式地址的對映資訊。

需要注意的是,Xcode 的預設設定是會在 release 和 debug 環境下已經配置好了 archive 時自動帶出 .dSYM 檔案,如果你發現開啟包內容時並沒有發現 .dSYM 檔案,可以到 Xcode 的 Build Settings 中檢視 Debug Infomation Format 欄位的配置進行修改。

.dSYM 檔案對於後續排查問題十分重要,每一次 release 版本都最好要儲存對應的 dSYM 檔案或把整個 Archives 檔案進行儲存;

第三步:symbolicatecrash 工具

symbolicatecrash 工具。該工具跟隨 Xcode,是獲取符號化結果的最方便工具。symbolicatecrash 的地址視 Xcode 的安裝路徑而定,大致的地址為:

你的Xcode安裝路徑/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash
複製程式碼

第四步:獲取崩潰程式碼資訊

有了 .ips 檔案、.dSYM 檔案和 symbolicatecrash 工具後就可以直接進行解析日誌了~因為我把這三個檔案都統一放在了一個資料夾中,所以實際上命令看起來會是這樣:

./symbolicatecrash ./yourApp.crash ./yourApp.dSYM > crash.log

如果在輸入這條命令時告知找不到 DEVELOPER_DIR,可以匯出一份:

export DEVELOPER_DIR="你的Xcode安裝位置/Xcode.app/Contents/Developer"
複製程式碼

對輸出的結果重定向到了當前路徑下的 crash.log 中,此時開啟該檔案,看到的內容是這樣的:

未完全符號化

很崩潰啊!重要的細節一個都沒有展示出來!隨後我換了一個思路,我們重新回到第三步

回到第三步:atos 命令

關於 atos 命令的描述,可以使用 man atos 檢視具體資訊:

...
DESCRIPTION
     The atos command converts numeric addresses to their symbolic equiva-
     lents.  If full debug symbol information is available, for example in a
     .app.dSYM sitting beside a .app, then the output of atos will include
     file name and source line number information.
...
複製程式碼

這是一個專用於 macOS 的控制檯工具,從描述中可以看出,可以將地址轉換為實際二進位制影象的符號化字串(實際程式碼)。上文中說到的 symbolicatecrash 工具是 apple 基於 atos 方便開發者進行的優化封裝,但不知為何我的 symbolicatecrash 並不能完整的符號化所有 crash log 中的內容。所以現在將直接使用 atos 進行符號化,操作稍微繁瑣一些,我們可以把對應的命令修改為:

atos -o yourApp.dSYM/Contents/Resources/DWARF/yourApp -arch arm64 -l 0x104e40000 0x0000000104f90198

arm64 為 Xcode 中設定的支援的 CPU 架構,按需修改。0x104e400000x0000000104f90198 這兩個地址是什麼意思呢?我們再看這張圖:

找到需要檢視的地址

0x104e40000local address0x0000000104f90198address,這兩個地址在不借助其它工具的前提下可以直接手算出來,如果你對手算地址感興趣的話,可以看這篇文章

通過執行上述 atos 命令,可以看到輸出了正確的資訊,如下圖所示:

正確的崩潰資訊

接下來就可以把多個地址進行解析,配合著在堆疊中的這幾個關鍵資訊基本上就可以定位到具體的 crash 程式碼檔案和行數。

其它工具

關於符號化奔潰報告,還有以下幾種:

  • dwarfdump。這個工具用來應付普通的 crash 日誌符號化完全是小題大做,但不排除某些極端下的情況。這個我沒使用過,不做展開。
  • lldblldb 在日常使用 Xcode 進行開發的過程中已經非常熟悉了,是 Xcode 的預設偵錯程式。這部分我也沒試過,大家可以自行搜尋進行嘗試。

總結

後續如果有時間會學習著開發一套適合自己業務流程的 crash 分析平臺,依賴於內部的分析平臺會受限很多,部分情況下不能滿足需求,只能依靠自己動手去改造,如果你對自建 crash 分析平臺感興趣的話,可以參考這篇文章

相關文章