iOS Crash分析必備:符號化系統(tǒng)庫方法

如果你有過分析iOS崩潰日志的經(jīng)驗,一定經(jīng)??吹饺罩纠锍霈F(xiàn)很多<redacted>的字段。這篇文章就是幫助開發(fā)者將這些字段符號化為對應(yīng)的系統(tǒng)庫方法名。

如果你已經(jīng)掌握了這方面的知識,就直接去這里iOS-System-Symbols,下載我整理好的系統(tǒng)庫符號文件吧。

符號化的作用

當(dāng)獲取到app的crash日志時,第一步就是將其符號化。作用是把日志堆棧中的方法調(diào)用顯示出來,對于來自app內(nèi)部的方法,還能直接給出方法對應(yīng).m文件的所在行。

符號化前(這里項目的Build Settings里的Strip Style設(shè)為了Debugging Symbols,所以這里能直接看到MyApp的方法名。更多和symbol相關(guān)的設(shè)置,請看這里):

Thread 7:
0   libsystem_kernel.dylib          0x000000018efb416c 0x18efb3000 + 4460 (mach_msg_trap + 8)
1   libsystem_kernel.dylib          0x000000018efb3fdc 0x18efb3000 + 4060 (mach_msg + 72)
2   MyApp                           0x000000010091e558 0x1000bc000 + 8791384 (ksmachexc_i_handleExceptions + 148)
3   libsystem_pthread.dylib         0x000000018f097860 0x18f094000 + 14432 (<redacted> + 240)
4   libsystem_pthread.dylib         0x000000018f097770 0x18f094000 + 14192 (_pthread_start + 284)

符號化后:

Thread 7:
0   libsystem_kernel.dylib          0x000000018efb416c mach_msg_trap + 8
1   libsystem_kernel.dylib          0x000000018efb3fdc mach_msg + 72
2   MyApp                           0x000000010091e558 ksmachexc_i_handleExceptions (KSCrashSentry_MachException.c:233)
3   libsystem_pthread.dylib         0x000000018f097860 _pthread_body + 240
4   libsystem_pthread.dylib         0x000000018f097770 _pthread_body + 0

可以發(fā)現(xiàn),frame 3里libsystem_pthread.dylib<redacted>變成了_pthread_body,frame 2里MyAppksmachexc_i_handleExceptions變成了更為完整的ksmachexc_i_handleExceptions (KSCrashSentry_MachException.c:233),直接給出了方法及其所在文件和行數(shù)。

詳細的符號化方法,請參考符號化iOS Crash文件的3種方法。這里就不重復(fù)了。

需要注意的是,很多時候,crash日志里并不會有MyApp的調(diào)用,而全都是系統(tǒng)庫的調(diào)用:

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x000000018b816f30 0x18b7fc000 + 110384 (objc_msgSend + 16)
1   UIKit                           0x0000000192e0a79c 0x192c05000 + 2119580 (<redacted> + 72)
2   UIKit                           0x0000000192c4db48 0x192c05000 + 297800 (<redacted> + 312)
3   UIKit                           0x0000000192c4d988 0x192c05000 + 297352 (<redacted> + 160)
4   QuartzCore                      0x00000001900d6404 0x18ffc5000 + 1119236 (<redacted> + 260)
5   libdispatch.dylib               0x000000018bc551c0 0x18bc54000 + 4544 (<redacted> + 16)
6   libdispatch.dylib               0x000000018bc59d6c 0x18bc54000 + 23916 (_dispatch_main_queue_callback_4CF + 1000)
7   CoreFoundation                  0x000000018cd79f2c 0x18cc9d000 + 905004 (<redacted> + 12)
8   CoreFoundation                  0x000000018cd77b18 0x18cc9d000 + 895768 (<redacted> + 1660)
9   CoreFoundation                  0x000000018cca6048 0x18cc9d000 + 36936 (CFRunLoopRunSpecific + 444)
10  GraphicsServices                0x000000018e729198 0x18e71d000 + 49560 (GSEventRunModal + 180)
11  UIKit                           0x0000000192c80628 0x192c05000 + 505384 (<redacted> + 684)
12  UIKit                           0x0000000192c7b360 0x192c05000 + 484192 (UIApplicationMain + 208)
13  MyApp                           0x0000000100016e54 0x100004000 + 77396 (_mh_execute_header + 77396)
14  libdyld.dylib                   0x000000018bc885b8 0x18bc84000 + 17848 (<redacted> + 4)

這時候就必須符號化系統(tǒng)庫了。符號化后的日志:

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x000000018b816f30 objc_msgSend + 16
1   UIKit                           0x0000000192e0a79c -[UISearchDisplayController _sendDelegateDidBeginDidEndSearch] + 72
2   UIKit                           0x0000000192c4db48 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
3   UIKit                           0x0000000192c4d988 -[UIViewAnimationState animationDidStop:finished:] + 160
4   QuartzCore                      0x00000001900d6404 CA::Layer::run_animation_callbacks(void*) + 260
5   libdispatch.dylib               0x000000018bc551c0 _dispatch_client_callout + 16
6   libdispatch.dylib               0x000000018bc59d6c _dispatch_main_queue_callback_4CF + 1000
7   CoreFoundation                  0x000000018cd79f2c __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
8   CoreFoundation                  0x000000018cd77b18 __CFRunLoopRun + 1660
9   CoreFoundation                  0x000000018cca6048 CFRunLoopRunSpecific + 444
10  GraphicsServices                0x000000018e729198 GSEventRunModal + 180
11  UIKit                           0x0000000192c80628 -[UIApplication _run] + 684
12  UIKit                           0x0000000192c7b360 UIApplicationMain + 208
13  MyApp                           0x0000000100016e54 main (main.m:15)
14  libdyld.dylib                   0x000000018bc885b8 start + 4

可以看出是UISearchControllerdelegate導(dǎo)致的問題,檢查一下就發(fā)現(xiàn)UISearchDisplayControllerdelegateassign的,是由于點擊搜索條的同時pop了界面導(dǎo)致的crash。

從這里可以發(fā)現(xiàn),符號化系統(tǒng)庫是很有必要的。

如何符號化系統(tǒng)庫

符號化自己app的方法名,需要編譯ipa時生成的dySYM文件。而要將系統(tǒng)庫的<redacted>符號化為完整的方法名,也需要系統(tǒng)庫的符號文件。

1. 匹配對應(yīng)的符號文件版本

系統(tǒng)庫符號文件不是通用的,而是對應(yīng)crash所在設(shè)備的系統(tǒng)版本和CPU型號的。

crash日志中有這樣兩個信息:

Code Type:       ARM-64
OS Version:      iOS 10.2 (14C82)

Code Type表示此設(shè)備的CPU為armv7、armv7s還是arm64

OS Version表示此設(shè)備的系統(tǒng)版本號,括號中的字符串代表了此系統(tǒng)的build號??梢栽谶@里查找build號:iOS SDK,iOS version history。

2. 將對應(yīng)版本的符號文件放到指定目錄

這時候,把獲取到的對應(yīng)版本的符號文件放到Mac的~/Library/Developer/Xcode/iOS DeviceSupport目錄下,再使用符號化iOS Crash文件的3種方法里提到的Xcode自帶的符號化工具symbolicatecrash進行符號化。這個工具會自動搜索系統(tǒng)庫符號文件。

獲取系統(tǒng)符號文件的4個方法

從真機上獲取

大部分系統(tǒng)庫符號文件只能從真機上獲取,蘋果也沒有提供下載。
當(dāng)你用Xcode第一次連接某臺設(shè)備進行真機調(diào)試時,會看到Xcode顯示Processing symbol files,這時候就是在拷貝真機上的符號文件到Mac系統(tǒng)的/Users/xxx/Library/Developer/Xcode/iOS DeviceSupport目錄下。

目錄下的10.2(14C82)這樣的文件夾就是對應(yīng)的符號文件,通常都有1-3GB的大小,很占用空間,動不動就累積成3、40GB。很多講清理Mac垃圾文件的教程都會說要刪除這個目錄下的文件,真是坑爹。正確做法是做成壓縮包保存到外部硬盤里,需要符號化的時候再重新解壓到此目錄。

尋找蘋果官方的下載地址

之前watch的調(diào)試出現(xiàn)bug時,有人找出過幾個watch的符號文件下載地址。見No symbols for paired Apple Watch。
但是我嘗試按照對應(yīng)的命名格式,并沒有找到iOS符號文件的下載地址。

從已解密的固件中提取符號文件

某些已經(jīng)被破解的固件可以直接提取系統(tǒng)文件,但是未破解的固件(較新的固件和arm64的固件),無法用這種方式獲取。

固件解密步驟:

1.下載對應(yīng)版本的.ipsw固件,直接解壓,解壓后里面有幾個.dmg格式的鏡像文件,最大的.dmg文件就是系統(tǒng)鏡像。
2.從Firmware_Keys找到對應(yīng)固件的解密key(頁面上Root Filesystem字段的key)。
3.用一個dmg工具進行解密,下載地址。使用方式:cd到解壓后的ipsw文件夾,執(zhí)行./dmg extract xxx-xxxx-xxx.dmg dec.dmg -k <key>。extract后面跟兩個參數(shù),分別是系統(tǒng)鏡像dmg的名字和解密后的文件名,-k 后面填寫第2步獲取到的key,如果key不對,解密會失敗。
4.等待。最終會生成一個dec.dmg文件,雙擊打開即可加載系統(tǒng)鏡像。

提取符號文件方法:
參考聊聊從iOS固件提取系統(tǒng)庫符號中的二、系統(tǒng)庫符號提取部分。

update:目前大多數(shù)固件都能解密了,而且iOS 10之后蘋果不再進行加密,因此之后都可以用這個方式獲取符號文件。

下載舊版本Xcode,提取SDK

舊版本的Xcode里包含了對應(yīng)的iPhoneSDK,可以從中獲得符號文件。
路徑是/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/。里面的System/Library里就可以看到framework,而且同時包含了armv7,armv7s,arm643個平臺的版本。

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/version.plist可以查看是哪個版本。把iPhoneOS.sdk文件夾的名字改成對應(yīng)的CFBundleVersion (ProductBuildVersion)格式,然后在里面加一層Symbols子文件夾,把System,Library,usr都放進Symbols里,就可以和其他符號文件一樣使用了。

但是當(dāng)iOS版本只包含了bug修復(fù),而沒有改變API,Xcode就不會有附帶對應(yīng)的SDK,還是需要從真機上獲取。而且從Xcode7開始,蘋果用tbd文件代替了真機符號文件,所以這個方法也失效了。
參考:Xcode software image for user iOS in order to symbolicate iOS calls, Missing iOS symbols at “~/Library/Developer/Xcode/iOS DeviceSupport”。

獲取符號文件的難題

這個時候,游戲就開始了:

  • 很多時候crash日志只給出了系統(tǒng)的調(diào)用棧,不能直接定位到自己app的代碼,因此需要符號化系統(tǒng)庫。
  • 用戶的crash來自各種系統(tǒng)版本,需要對應(yīng)版本的系統(tǒng)符號文件才能符號化。
  • 系統(tǒng)庫符號文件只能從真機上獲取,蘋果沒有提供下載。
  • iOS 7.0(11A465)iOS 10.2(14C92)一共有50個build版本,公司的測試機是不會覆蓋到這么變態(tài)的完整度的。
  • 同一個版本,有時候會給iPhone和iPad、甚至6和6s提供不同build的固件。
  • 某些版本是某些機子的特供版,例如10.0.3(14A551)是iPhone 7和 7 Plus獨有的,這就更加大了收集難度。
  • 同一個iOS版本可能有多個build,例如10.1(14B72)10.1(14B72c),蘋果覺得更新幅度太小,就沒有提升版本號。
  • 除了build號的區(qū)別,符號文件在不同CPU平臺上也有區(qū)別,意味著來自4s(armv7)和6s(arm64)的符號文件,即便build號是一樣的,也無法通用。所以50個build號又要翻倍,達到了88個,所以精確來說我只是收集了(63/88)的進度。幸運的是,arm64機型的系統(tǒng)庫里附帶了armv7s

規(guī)則好厲害的收集游戲啊。收集品其實還有稀有度的區(qū)別,其中最厲害的應(yīng)該是10.0,這是iPhone 7和7 Plus獨有的出廠系統(tǒng),而且沒有固件可以下載,因此即便有iPhone 7也不能通過刷機來得到10.0

其實我一直很奇怪為什么很少見到開發(fā)者抱怨找不到系統(tǒng)符號文件,從而召集大家進行收集并分享,猜測可能的原因是:

  • 懶。遇到無法符號化的問題,沒有去解決。
  • 有些公司可能很早就開始對crash日志自動符號化了,因此很早就開始收集符號文件。只要一直跟著蘋果的每一個版本升級,收集起來還是挺簡單的。而這些資源,開發(fā)者并不會注意到可以共享出來。
  • crash收集和符號化使用的是第三方服務(wù),第三方平臺會幫助符號化系統(tǒng)庫。

但是我找了一下,沒有找到一家明確聲明了能夠符號化所有系統(tǒng)庫的第三方平臺。從騰訊的Bugly論壇里也能發(fā)現(xiàn),有些系統(tǒng)方法并沒有符號化出來,系統(tǒng)庫是缺失的。(update:找到了一個國外的平臺,在stack overflow上說能符號化所有版本的系統(tǒng)庫,但是是收費服務(wù),我也沒有測試)

在公司小組里,大部分時候都是我來分析crash日志,所以當(dāng)遇到缺少系統(tǒng)符號文件的情況,就會十分無奈。很多時候,沒有符號化的crash日志根本無法提供有用信息。

系統(tǒng)符號文件下載地址

暴力收集

收集不全一直讓我很不爽。之前搜刮了組內(nèi)的測試機,只收集到了有限的幾個(感謝無私提供iPhone 7讓我刷機降級的同事)。終于,這周末特意跑去了一趟二手機市場尋找舊版本的設(shè)備來拷貝,總算是收集得完整了一點,但是也花了我121塊錢。

心情總算愉悅了。

其中大部分都是拷貝自arm64設(shè)備的,armv7的符號文件收集我是放棄了。有哪位大俠有興趣把這個游戲玩通關(guān)的嗎?還有 tvOS 和 watchOS的符號,我也放棄了。
(update:又花了些時間從Xcode的SDK和固件里提取了armv7sarmv7的固件,現(xiàn)在只剩下幾個arm64的版本了)。

整理了一下傳到了網(wǎng)盤,地址見下方,有需要的去下載吧。

目前還缺少的符號文件

通過各種方式,目前已經(jīng)收集得差不多了,只剩下最后一個10.0(14A346)版本沒有得到。如果哪位小伙伴有這個版本,可以分享一下。

分享可以直接貼下載地址,也可以提交到這個github項目iOS-System-Symbols。如果我得到了新的符號文件,也會在這個項目里更新。

缺失符號的版本 缺失的CPU版本 描述
10.0(14A346) arm64 iPhone 7 和 7 Plus獨占,出廠自帶系統(tǒng)

網(wǎng)盤下載地址

下載地址請見這個項目:iOS-System-Symbols。如果我得到了新的符號文件,會在這個項目里更新。

我把里面的那幾個dyld_shared_cache_xxxx大文件單獨拿出來了,目的是減小壓縮包大小。如果只是符號化的話,用不到這幾個文件,只是在真機調(diào)試的時候才需要。

符號文件版本列表

這些是我已經(jīng)收集到的符號文件,包括了對應(yīng)的CPU信息。iOS10系統(tǒng)開始不支持armv7的機器。但是iOS9以下還是支持armv7的。

查看是否帶有對應(yīng)CPU架構(gòu)的符號文件的方式:到10.2 (14C92)/Symbols/System/Library/Caches/com.apple.dyld這樣的目錄下,會有對應(yīng)的dyld_shared_cache_arm64,dyld_shared_cache_armv7s,dyld_shared_cache_armv7文件,如果缺失了,就說明對應(yīng)的CPU架構(gòu)符號文件還不存在。(經(jīng)過試驗,這幾個大文件并不影響符號化,只是在真機調(diào)試的時候才有用,因此如果嫌太占用空間,可以刪去)。

版本 已收集到的CPU版本 描述
11.2.6 (15D100) arm64
11.2.5 (15D60) arm64
11.2.2 (15C202) arm64
11.2.1 (15C153) arm64
11.2 (15C114) arm64
11.2 (15C113) none 蘋果在發(fā)布了15C114之后,又發(fā)布了一個低版本的15C113,之后又移除了15C113的下載地址,因此這個固件目前無法下載。應(yīng)該只是誤發(fā)布,可以忽略這個版本
11.1.2 (15B202) arm64
11.1.1 (15B150) arm64
11.1 (15B101) arm64 iPad Pro2 12.9-inch and iPad Pro 10.5-inch only
11.1 (15B93) arm64
11.0.3 (15A432) arm64
11.0.2 (15A421) arm64
11.0.1 (15A403) arm64 iPhone 8 and 8 Plus only
11.0.1 (15A402) arm64
11.0 (15A372) arm64
10.3.3 (14G60) arm64,armv7s
10.3.2 (14F91) arm64,armv7s iPad mini4(Cellular) only
10.3.2 (14F90) arm64,armv7s iPad (5th gen) only
10.3.2 (14F89) arm64,armv7s
10.3.1 (14E304) arm64,armv7s
10.3 (14E277) arm64,armv7s
10.2.1 (14D27) arm64,armv7s
10.2 (14C92) arm64,armv7s
10.1.1 (14B150) arm64,armv7s
10.1.1 (14B100) arm64,armv7s
10.1 (14B72c) arm64,armv7s
10.1 (14B72) arm64,armv7s
10.0.3 (14A551) arm64,armv7s
10.0.2 (14A456) arm64,armv7s
10.0.1 (14A403) arm64,armv7s
10.0(14A346) none iPhone 7 和 7 Plus獨占,出廠自帶系統(tǒng)
9.3.5 (13G36) arm64,armv7s,armv7
9.3.4 (13G35) arm64,armv7s,armv7
9.3.3 (13G34) arm64,armv7s,armv7
9.3.2(13F72) arm64,armv7s iPad Pro 9.7寸獨占,修復(fù)了變磚的問題
9.3.2 (13F69) arm64,armv7s,armv7
9.3.1 (13E238) arm64,armv7s,armv7
9.3(13E237) armv7s,armv7 5s和更舊機型獨占,修復(fù)了不能激活的問題
9.3(13E236) armv7 iPad2獨占,修復(fù)了不能激活的問題
9.3(13E234) arm64,armv7s 6s, 6s Plus and iPad Pro 9.7寸獨占
9.3 (13E233) arm64,armv7s,armv7
9.2.1 (13D20) arm64,armv7s iPhone 6 和更新的機型獨占
9.2.1 (13D15) arm64,armv7s,armv7
9.2 (13C75) arm64,armv7s,armv7
9.1 (13B143) arm64,armv7s,armv7
9.0.2(13A452) arm64,armv7s,armv7
9.0.1(13A404) arm64,armv7s,armv7
9.0 (13A344) arm64,armv7s,armv7
8.4.1 (12H321) arm64,armv7s,armv7
8.4 (12H143) arm64,armv7s,armv7
8.3 (12F70) arm64,armv7s,armv7 iPhone獨占
8.3 (12F69) arm64,armv7s,armv7 iPad獨占
8.2 (12D508) arm64,armv7s,armv7
8.1.3 (12B466) arm64,armv7s,armv7
8.1.2 (12B440) arm64,armv7s,armv7
8.1.1 (12B436) arm64,armv7s iPhone 6 和更新的機型獨占
8.1.1 (12B435) armv7s,armv7 5s和更舊機型獨占
8.1 (12B411) arm64,armv7s,armv7 iPhone獨占
8.1 (12B410) arm64,armv7s,armv7 iPad獨占
8.0.2 (12A405) arm64,armv7s,armv7
8.0.1(12A402) armv7s,armv7 8.0.1有導(dǎo)致變磚的bug,發(fā)布后很快就停止推送了
8.0 (12A366) arm64,armv7s 6 Plus獨占
8.0 (12A365) arm64,armv7s,armv7
7.1.2 (11D257) armv7s,armv7
7.1.1 (11D201) arm64,armv7s,armv7
7.1 (11D167) arm64,armv7s,armv7
7.0.6 (11B651) arm64,armv7s,armv7
7.0.4 (11B554a) arm64,armv7s,armv7
7.0.3 (11B511) arm64,armv7s,armv7
7.0.2(11A501) armv7s,armv7
7.0.1(11A470a) armv7s 5s 和 5c 獨占
7.0(11A465) arm64,armv7s,armv7

機型對應(yīng)CPU架構(gòu)

CPU 機型
armv6 iPhone, iPhone2, iPhone3G, iPod Touch 1 and 2
armv7 iPhone3GS, iPhone4, iPhone4S,iPad, iPad2, iPad3(The New iPad), iPad mini,iPod Touch 3G, iPod Touch4, iPod Touch5
armv7s iPhone5, iPhone5C, iPad4(iPad with Retina Display)
arm64 iPhone5S, iPad Air, iPad mini2(iPad mini with Retina Display), iPhone6, iPhone6s, iPhone7, iPhone7s and any new device in the future

結(jié)束語

最后再次呼吁一下,如果誰有上面缺失的符號文件,就請共享一下吧。雖然只是做一點微小的工作,但是能夠有很大幫助。

不覺得填滿上面那個列表會很爽嗎?

update:現(xiàn)在基本上已經(jīng)收集完了。

額外提示

其實這些符號文件就是真機上的系統(tǒng)庫,包括了完整的系統(tǒng)庫二進制文件。有時候要反編譯某些系統(tǒng)framework,但是模擬器SDK里沒有對應(yīng)的framework(比如只有真機上才有的CoreMotion.framework),就可以在這些真機上的系統(tǒng)庫里找到了。

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容