若是你有過度析iOS崩潰日誌的經驗,必定常常看到日誌裏出現不少<redacted>
的字段。這篇文章就是幫助開發者將這些字段符號化爲對應的系統庫方法名。ios
若是你已經掌握了這方面的知識,就直接去這裏iOS-System-Symbols,下載我整理好的系統庫符號文件吧。git
當獲取到app的crash日誌時,第一步就是將其符號化。做用是把日誌堆棧中的方法調用顯示出來,對於來自app內部的方法,還能直接給出方法對應.m文件的所在行。github
符號化前(這裏項目的Build Settings
裏的Strip Style
設爲了Debugging Symbols
,因此這裏能直接看到MyApp
的方法名。更多和symbol相關的設置,請看這裏):xcode
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)
複製代碼
符號化後:bash
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
複製代碼
能夠發現,frame 3裏libsystem_pthread.dylib
的<redacted>
變成了_pthread_body
,frame 2裏MyApp
的ksmachexc_i_handleExceptions
變成了更爲完整的ksmachexc_i_handleExceptions (KSCrashSentry_MachException.c:233)
,直接給出了方法及其所在文件和行數。架構
詳細的符號化方法,請參考符號化iOS Crash文件的3種方法。這裏就不重複了。app
須要注意的是,不少時候,crash日誌裏並不會有MyApp的調用,而全都是系統庫的調用:iphone
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)
複製代碼
這時候就必須符號化系統庫了。符號化後的日誌:工具
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
複製代碼
能夠看出是UISearchController
的delegate
致使的問題,檢查一下就發現UISearchDisplayController
的delegate
是assign
的,是因爲點擊搜索條的同時pop了界面致使的crash。oop
從這裏能夠發現,符號化系統庫是頗有必要的。
##如何符號化系統庫
符號化本身app的方法名,須要編譯ipa時生成的dySYM文件。而要將系統庫的<redacted>
符號化爲完整的方法名,也須要系統庫的符號文件。
系統庫符號文件不是通用的,而是對應crash所在設備的系統版本和CPU型號的。
crash日誌中有這樣兩個信息:
Code Type: ARM-64
OS Version: iOS 10.2 (14C82)
複製代碼
Code Type
表示此設備的CPU爲armv7
、armv7s
仍是arm64
。
OS Version
表示此設備的系統版本號,括號中的字符串表明了此係統的build號。能夠在這裏查找build號:iOS SDK,iOS version history。
這時候,把獲取到的對應版本的符號文件放到Mac的~/Library/Developer/Xcode/iOS DeviceSupport
目錄下,再使用符號化iOS Crash文件的3種方法裏提到的Xcode自帶的符號化工具symbolicatecrash
進行符號化。這個工具會自動搜索系統庫符號文件。
大部分系統庫符號文件只能從真機上獲取,蘋果也沒有提供下載。 當你用Xcode第一次鏈接某臺設備進行真機調試時,會看到Xcode顯示Processing symbol files
,這時候就是在拷貝真機上的符號文件到Mac系統的/Users/xxx/Library/Developer/Xcode/iOS DeviceSupport
目錄下。
目錄下的10.2(14C82)
這樣的文件夾就是對應的符號文件,一般都有1-3GB的大小,很佔用空間,動不動就累積成三、40GB。不少講清理Mac垃圾文件的教程都會說要刪除這個目錄下的文件,真是坑爹。正確作法是作成壓縮包保存到外部硬盤裏,須要符號化的時候再從新解壓到此目錄。
以前watch的調試出現bug時,有人找出過幾個watch的符號文件下載地址。見No symbols for paired Apple Watch。 可是我嘗試按照對應的命名格式,並無找到iOS符號文件的下載地址。
某些已經被破解的固件能夠直接提取系統文件,可是未破解的固件(較新的固件和arm64
的固件),沒法用這種方式獲取。
固件解密步驟:
1.下載對應版本的.ipsw固件,直接解壓,解壓后里面有幾個.dmg
格式的鏡像文件,最大的.dmg
文件就是系統鏡像。
2.從Firmware_Keys找到對應固件的解密key(頁面上Root Filesystem
字段的key)。
3.用一個dmg
工具進行解密,下載地址。使用方式:cd
到解壓後的ipsw文件夾,執行./dmg extract xxx-xxxx-xxx.dmg dec.dmg -k <key>
。extract
後面跟兩個參數,分別是系統鏡像dmg的名字和解密後的文件名,-k 後面填寫第2步獲取到的key,若是key不對,解密會失敗。
4.等待。最終會生成一個dec.dmg
文件,雙擊打開便可加載系統鏡像。
提取符號文件方法: 參考聊聊從iOS固件提取系統庫符號中的2、系統庫符號提取
部分。
update:目前大多數固件都能解密了,並且iOS 10以後蘋果再也不進行加密,所以以後均可以用這個方式獲取符號文件。
舊版本的Xcode裏包含了對應的iPhoneSDK,能夠從中得到符號文件。 路徑是/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/
。裏面的System/Library
裏就能夠看到framework,並且同時包含了armv7
,armv7s
,arm64
3個平臺的版本。
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/version.plist
能夠查看是哪一個版本。把iPhoneOS.sdk
文件夾的名字改爲對應的CFBundleVersion (ProductBuildVersion)
格式,而後在裏面加一層Symbols
子文件夾,把System
,Library
,usr
都放進Symbols
裏,就能夠和其餘符號文件同樣使用了。
可是當iOS版本只包含了bug修復,而沒有改變API,Xcode就不會有附帶對應的SDK,仍是須要從真機上獲取。並且從Xcode7開始,蘋果用tbd
文件代替了真機符號文件,因此這個方法也失效了。 參考:Xcode software image for user iOS in order to symbolicate iOS calls, Missing iOS symbols at 「~/Library/Developer/Xcode/iOS DeviceSupport」。
這個時候,遊戲就開始了:
iOS 7.0(11A465)
到iOS 10.2(14C92)
一共有50個build版本,公司的測試機是不會覆蓋到這麼變態的完整度的。10.0.3(14A551)
是iPhone 7和 7 Plus獨有的,這就更加大了收集難度。10.1(14B72)
和10.1(14B72c)
,蘋果以爲更新幅度過小,就沒有提高版本號。armv7
)和6s(arm64
)的符號文件,即使build號是同樣的,也沒法通用。因此50個build號又要翻倍,達到了88個,因此精確來講我只是收集了(63/88)的進度。幸運的是,arm64
機型的系統庫裏附帶了armv7s
。規則好厲害的收集遊戲啊。收集品其實還有稀有度的區別,其中最厲害的應該是10.0
,這是iPhone 7和7 Plus獨有的出廠系統,並且沒有固件能夠下載,所以即使有iPhone 7也不能經過刷機來獲得10.0
。
其實我一直很奇怪爲何不多見到開發者抱怨找不到系統符號文件,從而召集你們進行收集並分享,猜想可能的緣由是:
可是我找了一下,沒有找到一家明確聲明瞭可以符號化全部系統庫的第三方平臺。從騰訊的Bugly論壇裏也能發現,有些系統方法並無符號化出來,系統庫是缺失的。(update:找到了一個國外的平臺,在stack overflow上說能符號化全部版本的系統庫,可是是收費服務,我也沒有測試)
在公司小組裏,大部分時候都是我來分析crash日誌,因此當遇到缺乏系統符號文件的狀況,就會十分無奈。不少時候,沒有符號化的crash日誌根本沒法提供有用信息。
收集不全一直讓我很不爽。以前搜刮了組內的測試機,只收集到了有限的幾個(感謝無私提供iPhone 7讓我刷機降級的同事)。終於,這週末特地跑去了一趟二手機市場尋找舊版本的設備來拷貝,總算是收集得完整了一點,可是也花了我121塊錢。
心情總算愉悅了。
其中大部分都是拷貝自arm64
設備的,armv7
的符號文件收集我是放棄了。有哪位大俠有興趣把這個遊戲玩通關的嗎?還有 tvOS 和 watchOS的符號,我也放棄了。 (update:又花了些時間從Xcode的SDK和固件裏提取了armv7s
和armv7
的固件,如今只剩下幾個arm64
的版本了)。
整理了一下傳到了網盤,地址見下方,有須要的去下載吧。
經過各類方式,目前已經收集得差很少了,只剩下最後一個10.0(14A346)
版本沒有獲得。若是哪位小夥伴有這個版本,能夠分享一下。
分享能夠直接貼下載地址,也能夠提交到這個github項目iOS-System-Symbols。若是我獲得了新的符號文件,也會在這個項目裏更新。
缺失符號的版本 | 缺失的CPU版本 | 描述 |
---|---|---|
10.0(14A346) | arm64 | iPhone 7 和 7 Plus獨佔,出廠自帶系統 |
下載地址請見這個項目:iOS-System-Symbols。若是我獲得了新的符號文件,會在這個項目裏更新。
我把裏面的那幾個dyld_shared_cache_xxxx
大文件單獨拿出來了,目的是減少壓縮包大小。若是隻是符號化的話,用不到這幾個文件,只是在真機調試的時候才須要。
這些是我已經收集到的符號文件,包括了對應的CPU信息。iOS10系統開始不支持armv7
的機器。可是iOS9如下仍是支持armv7
的。
查看是否帶有對應CPU架構的符號文件的方式:到10.2 (14C92)/Symbols/System/Library/Caches/com.apple.dyld
這樣的目錄下,會有對應的dyld_shared_cache_arm64
,dyld_shared_cache_armv7s
,dyld_shared_cache_armv7
文件,若是缺失了,就說明對應的CPU架構符號文件還不存在。(通過試驗,這幾個大文件並不影響符號化,只是在真機調試的時候纔有用,所以若是嫌太佔用空間,能夠刪去)。
版本 | 已收集到的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 | 蘋果在發佈了15C114以後,又發佈了一個低版本的15C113,以後又移除了15C113的下載地址,所以這個固件目前沒法下載。應該只是誤發佈,能夠忽略這個版本 |
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獨佔,出廠自帶系統 |
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寸獨佔,修復了變磚的問題 |
9.3.2 (13F69) | arm64,armv7s,armv7 | |
9.3.1 (13E238) | arm64,armv7s,armv7 | |
9.3(13E237) | armv7s,armv7 | 5s和更舊機型獨佔,修復了不能激活的問題 |
9.3(13E236) | armv7 | iPad2獨佔,修復了不能激活的問題 |
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 有致使變磚的bug,發佈後很快就中止推送了 |
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 |
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 |
最後再次呼籲一下,若是誰有上面缺失的符號文件,就請共享一下吧。雖然只是作一點微小的工做,可是可以有很大幫助。
不以爲填滿上面那個列表會很爽嗎?
update:如今基本上已經收集完了。
其實這些符號文件就是真機上的系統庫,包括了完整的系統庫二進制文件。有時候要反編譯某些系統framework,可是模擬器SDK裏沒有對應的framework(好比只有真機上纔有的CoreMotion.framework
),就能夠在這些真機上的系統庫裏找到了。