若是你有过度析iOS崩溃日志的经验,必定常常看到日志里出现不少<redacted>
的字段。这篇文章就是帮助开发者将这些字段符号化为对应的系统库方法名。ios
若是你已经掌握了这方面的知识,就直接去这里iOS-System-Symbols,下载我整理好的系统库符号文件吧。git
当获取到app的crash日志时,第一步就是将其符号化。做用是把日志堆栈中的方法调用显示出来,对于来自app内部的方法,还能直接给出方法对应.m文件的所在行。github
符号化前(这里项目的Build Settings
里的Strip Style
设为了Debugging Symbols
,因此这里能直接看到MyApp
的方法名。更多和symbol相关的设置,请看这里):面试
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)
复制代码
符号化后:xcode
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
复制代码
做为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个个人iOS交流群:413038000,无论你是小白仍是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 你们一块儿交流学习成长!bash
能够发现,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。
从这里能够发现,符号化系统库是颇有必要的。
符号化本身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
),就能够在这些真机上的系统库里找到了。
做者:黑超熊猫zuik