IOS錯誤日志抓取和分析


在調試自己和別人的IOS App時,發生Crash是非常正常的情況,分析這些Crash的主要手段之一就是分析Crash發生時產生的錯誤日志。對於未越獄的IOS設備,獲取錯誤日志主要通過Xcode自帶的日志獲取功能,但是這種方式有以下兩點限制: 


1.只能獲取開發者自己開發的App的日志,無法獲取第三方App的日志。 
2.自動化工作難度較高(錯誤日志收集,錯誤日志整理等)。

 

文中,筆者首先簡單介紹了一下使用Xcode抓取和分析錯誤日志的方法,然后為了克服上面的兩個缺陷,筆者調研了一套可自動化的第三方App在本地測試的錯誤日志抓取方法。最后,筆者簡單介紹了一下IOS錯誤日志的基本構成,供讀者進行日志分析和分類收集參考。

 

錯誤日志的獲取

方法1: 使用Xcode獲取錯誤日志

 

對於自己研發並在測試機上測試的應用,我們可以通過Xcode來分析測試過程中的錯誤日志。但是App一但發布到AppStore,那么我們如何獲取用戶在使用過程中產生的錯誤日志呢?為了解決這一問題,蘋果官方提供了一套供App開發者使用的基於Xcode工具的解決方案。

 

對於App在測試機上運行的情況,Xcode支持獲取Apple機器的Log的情況。打開Xcode並打開自己開發的AppProject,在Window->Devices中,找到對應的設備 

點擊View Device Logs 

圖片

 

在此處可以查看設備的日志信息,確認測試機連接到Mac,即可看到已經符號化完成的錯誤日志 

圖片

 

對於在AppStore已經發布的App產生的錯誤日志,在Window->Organizer中,找到對應的App,在Crashes目錄中找到AppStore下載的其他使用者使用過程中產生的錯誤日志。

 

圖片

 

方法2: 使用命令行獲取錯誤日志

 

蘋果官方提供的方案雖然能夠成功的獲取錯誤日志,但是有一個前提,那就是用戶必須是App的開發者,如果我們需要獲取第三方開發者開發的App的錯誤日志,那么上述方法就不能正確的工作了。適用於這一場景的可行方案之一,是使用libimobiledevice庫中的idevicecrashreport命令來獲取。

 
libimobiledevice庫:libimobiledevice 是Github上的一個開源庫,主要提供和未越獄的蘋果IOS設備通信的服務。包括App安裝,系統日志獲取,設備信息獲取和錯誤日志獲取等能力(其他具體的服務能力可以參考libimobiledevice的官網:http://www.libimobiledevice.org/)。

本文具體主要使用idevicecrashreport和ideviceinstaller命令。

 

假設你獲取的第三方App的Ipa已經發布到App Store,那么你可以直接從App Store上下載並測試。如果未發布到App Store,則需要使用ideviceinstaller命令安裝該App到指定的手機。具體的command如下:

圖片

出現如下日志后安裝成功(IOS > 9的設備使用ideviceinstaller會出現Segmentation fault,但是不影響App本身的安裝) 

圖片

 

然后就可以愉快地測試App了:)

 

App出現Crash后,ios設備本身保留了CrashReport。為了將設備上的CrashReport拷貝到本機,就需要使用idevicecrashreport命令了。具體的command如下:

圖片

如果需要在設備上保留錯誤日志,使用-k選項;如果需要將crashreport單獨存放,使用-e選項。 


導出后的文件結構如下所示: 

圖片

 

其中wifi為IOS的wifi信息,此處我們並不關心。我們關注其中CrashDemo開頭的兩個后綴為ips的文件(CrashDemo是我用來測試的App名)。使用Xcode打開一個ips文件。如下所示: 

圖片

圖片

 

這樣我們就成功得到了App的錯誤日志。

 

該方法的優點: 

  1. 可以獲取第三方App的錯誤日志。 

  2. 方法全部通過命令行方式進行獲取,方便編寫shell進行自動化獲取 

 

該方法的缺點: 
無法獲得AppStore上使用者相關的錯誤日志。

 

 

錯誤日志的符號化

我們可以注意到,上述第二種錯誤日志的獲取方法所獲取到的日志,日志中的堆棧信息並不像Android等錯誤日志中的堆棧信息那樣打印出了調用的堆棧,而是使用段基址 + 偏移地址的格式顯示。除此之外,對於錯誤信息,也進行了相關的處理。為了能夠正確的分析錯誤,我們需要對這些地址進行符號化,從而將日志翻譯成能夠處理的信息。一般來說,符號化日志需要開發者提供編譯App后生成的dsym文件,該文件包含了App編譯后的所有類和函數的地址信息。但是如果我們需要分析第三方開發者的App,那么我們是無法獲得該App的dsym文件的。下面給出了無dsym文件場景下符號化日志信息的方法。

 

不帶dsym文件的日志符號化

 

使用symbolicate符號化錯誤日志文件 

symbolicate:symbolicate是github開源的三方腳本,該腳本使用xcode自帶的符號化工具symbolicatecrash進行符號化。symbolicate支持兩種符號化的方法。使用App的dsym文件和使用App的ipa解壓后的App文件夾。 


那么為什么不直接使用xcode的symbolicatecrash命令進行符號化呢?這一點我們可以通過分析symbolicate.sh的源碼來了解。 


通過分析源碼,我們可以看出xcode自帶的symbolicatecrash工具的主要缺陷有兩點: 


1. 工具隨着Xcode版本有着比較大的變更。 
2. 缺少對錯誤日志UUID和App有效性的校驗。

 

在我們的場景中,我們沒有App的dsym文件,所以我們主要依賴App的ipa解壓后的文件夾來進行調試,解壓ipa可以使用mac自帶的unzip命令

圖片

 

解壓后的app目錄在appdirpath/Payload目錄下,在Finder中顯示如下: 

圖片

 

symbolicate腳本的使用方法如下:

圖片

 

符號化后的錯誤日志文件如下: 

圖片

 

可以看見,堆棧信息的部分的已經完成了符號化,現在我們可以開始錯誤日志的分析了。

 

錯誤日志的分析

在完成了錯誤日志的符號化之后,接下來就是對錯誤日志的分析了,蘋果官方提供的錯誤日志格式還是非常詳細的。下面簡單介紹錯誤日志(CrashReport)的基本格式。

 

CrashReport基本格式

 

IOS在以下兩種情況下會產生錯誤日志: 
1.應用違反操作系統規則。 
2.應用中有Bug。

 

1中“違反操作系統規則“主要包括watchdog終止,用戶強制結束和低內存終止三種情況。 


2則是應用本身導致的問題。 


1和2的日志格式不同,本文主要介紹2的情況下產生的錯誤日志的基本格式。

 

下圖是一個錯誤日志的例子 

圖片

 

整個錯誤日志分為進程信息、Crash信息、Crash異常、線程回溯、線程狀態和二進制映像6個部分。 


進程信息:包括Crash的ID(Incident Identifier),設備的Model和標識符(CrashReporter Key和Hardware Model),App信息(Path、Identifier、Version和CodeType),以及啟動的進程信息(Process、ParentProcess)。 


Crash信息:包括Crash發生的時間和系統號 


Crash異常:包括異常類型(Exception Type)和異常碼(Exception Codes)。此處對經常出現的異常碼匯總如下(蘋果的異常碼還是很生動的) 


0x8badf00d:(ate bad food)這個異常碼表示該異常是由watchdog終止引發的。 
0xbad22222:這個異常碼表示該異常是由VoIP被過於頻繁重啟引發的。

 
0xdeadl0cc:(dead lock)這個異常碼表示該異常是由於App長期占用系統資源而被系統強行終止引發的異常。 


0xdeadfa11:(dead fail)這個異常碼表示該異常是由用戶強制終止引發的。

 

線程回溯信息

回溯信息包括四列: 

幀編號 
二進制庫的名稱 
調用方法的地址 
第四列分為兩個子列,一個基本地址和一個偏移量。

對於未符號化的日志,這一列的內容比較難以理解

圖片

 

對於符號化后的日志,該列內容如下:

圖片

 

分別為該進程調用的函數名稱和對應的代碼行號

 

線程狀態:Crash中寄存器中的值(不常用,堆棧信息足以完成大部分的Crash分析) 


二進制映像:Crash發生時已經載入的二進制文件

 

以上就是本文的全部內容了,文中涉及到的開源庫的Github地址如下: 


libimobiledevice: https://github.com/libimobiledevice/libimobiledevice 


symbolicate: https://github.com/JohnWong/symbolicate


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM