如果你有過分析iOS崩潰日志的經(jīng)驗生棍,一定經(jīng)常看到日志里出現(xiàn)很多<redacted>
的字段媳谁。這篇文章就是幫助開發(fā)者將這些字段符號化為對應(yīng)的系統(tǒng)庫方法名涂滴。
如果你已經(jīng)掌握了這方面的知識,就直接去這里iOS-System-Symbols晴音,下載我整理好的系統(tǒ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里MyApp
的ksmachexc_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
可以看出是UISearchController
的delegate
導(dǎo)致的問題袁铐,檢查一下就發(fā)現(xiàn)UISearchDisplayController
的delegate
是assign
的揭蜒,是由于點擊搜索條的同時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)庫符號文件只能從真機上獲取涯竟,蘋果也沒有提供下載。
當你用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
,arm64
3個平臺的版本娇唯。
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/version.plist
可以查看是哪個版本。把iPhoneOS.sdk
文件夾的名字改成對應(yīng)的CFBundleVersion (ProductBuildVersion)
格式寂玲,然后在里面加一層Symbols
子文件夾塔插,把System
,Library
,usr
都放進Symbols
里,就可以和其他符號文件一樣使用了拓哟。
但是當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日志煌恢,所以當遇到缺少系統(tǒng)符號文件的情況骇陈,就會十分無奈。很多時候瑰抵,沒有符號化的crash日志根本無法提供有用信息你雌。
系統(tǒng)符號文件下載地址
暴力收集
收集不全一直讓我很不爽。之前搜刮了組內(nèi)的測試機二汛,只收集到了有限的幾個(感謝無私提供iPhone 7讓我刷機降級的同事)婿崭。終于,這周末特意跑去了一趟二手機市場尋找舊版本的設(shè)備來拷貝肴颊,總算是收集得完整了一點氓栈,但是也花了我121塊錢。
心情總算愉悅了婿着。
其中大部分都是拷貝自arm64
設(shè)備的颤绕,armv7
的符號文件收集我是放棄了幸海。有哪位大俠有興趣把這個游戲玩通關(guān)的嗎?還有 tvOS 和 watchOS的符號奥务,我也放棄了物独。
(update:又花了些時間從Xcode的SDK和固件里提取了armv7s
和armv7
的固件,現(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)庫里找到了坐搔。