iOS崩溃日志分析

什么是崩溃日志

iOS的App在崩溃时,系统会记录下当前的每个线程的调用栈信息等等,并保存到设备中。这些信息汇总起来就是我们所说的崩溃日志。

iOS崩溃日志收集的几种方式

  1. 通过Xcode的Window > Devices进入设备管理,使用View Device Logs查看
  2. 通过第三方SDK上传用户的崩溃日志,比如使用友盟,BugHD,Bugly等等
  3. 通过Apple后台搜集崩溃日志,可以在Organizer里直接查看线上的崩溃日志。但是如果用户选择不上传诊断信息,就看不到日志了。

为什么要符号化

从iOS设备采集的原始崩溃日志记录的都是调用栈地址

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0:
0   libsystem_kernel.dylib          0x000000019959cb3c 0x19959c000 + 2876
1   libsystem_platform.dylib        0x0000000199679534 0x199674000 + 21812
2   libobjc.A.dylib                 0x0000000198c5b200 0x198c44000 + 94720
3   libobjc.A.dylib                 0x0000000198c6443c 0x198c44000 + 132156
4   CoreFoundation                  0x0000000184190cbc 0x184064000 + 1232060
......

这样的崩溃日志是无法使用的,通过符号化可以将它转换成可读的日志

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0:
0   libsystem_kernel.dylib          0x000000019959cb3c syscall_thread_switch + 8
1   libsystem_platform.dylib        0x0000000199679534 _os_lock_handoff_lock_slow + 120
2   libobjc.A.dylib                 0x0000000198c5b200 spinlock_t::lockTwo(spinlock_t*, spinlock_t*) + 52
3   libobjc.A.dylib                 0x0000000198c6443c objc_storeWeakOrNil + 120
4   CoreFoundation                  0x0000000184190cbc _NSObjectStoreWeak + 80
5   CoreFoundation                  0x00000001841167f8 -[_CFXNotificationObjcObserverRegistration initWithObserver:parent:] + 92
......

怎样符号化

大多数iOS程序员应该都知道使用View Device Logs查看设备日志时会自动符号化崩溃日志,但有时候可以符号化,但有时候却不行。
为什么呢?除了通过View Device Logs自动符号化文件,还有没有其他方式可以手动符号化崩溃日志呢?下面会一一解答这些问题。

符号化的原理

dSYM文件

dSYM文件(符号文件)是存储了类名和方法名等调试信息的文件。在release模式下,build后会有.app.dSYM文件。
debug模式下调试信息在可执行文件中,所以不会生成dSYM文件。符号化就是通过在dSYM文件查找地址对应的方法名来实现的。

Xcode的View Device Logs符号化时如何寻找符号文件

每个Crash日志都记录了它所对应符号文件的uuid,打开一个crash文件,可以看到类似于下面这行的信息

Binary Images:    
0x10006c000 - 0x100073fff Demo1 arm64  <2cf1790547ff3a1cac055152319617ba> /var/mobile/Containers/Bundle/Application/7E6DE925-0B33-4699-89F7-05381876AD81/Demo1.app/Demo1

例子中的App名字是Demo1,符号文件所对应的uuid就是2cf1790547ff3a1cac055152319617ba。当符号化这个崩溃日志的时候,符号化工具会通过这个uuid去寻找对应的dSYM文件,如果找到了就可以正确的符号化了。
由此我们就可以知道,使用View Device Logs查看崩溃日志时,有时不能符号化的原因就是没有查到对应的dSYM文件。因为每次build都会导致uuid发生变化,所以大部分的崩溃日志所对应的dSYM文件其实都被覆盖掉了。

通过符号化命令行工具深入了解符号化的过程

在Xcode7.0中可以在一下路径找到符号化命令行工具

/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash

可以为这个工具设置alias:

alias symbolicatecrash="/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash"

这时候直接调用的话会报Error: "DEVELOPER_DIR" is not defined at ...这样的错误,只要设置环境变量DEVELOPER_DIR就行了 。
export 'DEVELOPER_DIR'="/Applications/Xcode.app/Contents/Developer"

后面我都会直接使用symbolicatecrash进行命令行下的符号化

Xcode就是通过这个工具符号化崩溃日志的

在符号化之前我们先准备好几样东西:
  1. 原始的崩溃日志
  2. dSYM文件
  3. symbolicatecrash可执行文件

我们先查看crash日志是否和符号文件是匹配的,下面的命令将提取dSYM文件的uuid

xcrun dwarfdump --uuid Demo1.app.dSYM/Contents/Resources/DWARF/Demo1

我提取出来的uuid是:

UUID: 2CF17905-47FF-3A1C-AC05-5152319617BA (arm64) Demo1.app.dSYM/Contents/Resources/DWARF/Demo1

崩溃日志的uuid是:

0x10006c000 - 0x100073fff Demo1 arm64  <2cf1790547ff3a1cac055152319617ba> /var/mobile/Containers/Bundle/Application/7E6DE925-0B33-4699-89F7-05381876AD81/Demo1.app/Demo1

都是 2cf1790547ff3a1cac055152319617ba,所以使用这个dSYM文件既可以符号化上面的崩溃日志。

用symbolicatecrash来符号化崩溃日志
symbolicatecrash demo1.crash Demo1.app.dSYM -o processed.crash

符号化后的crash文件将会被写入processed.crash中,
然后我们来看看如果把Demo1.app.dSYM去掉会怎样,为了看到符号化的过程,我们可以加上 -v

symbolicatecrash demo1.crash -o processed.crash -v

我们主要看Demo1的符号化过程,其他系统调用其实也会在这个过程中被符号化。#后面是我添加的注释

-- [2cf1790547ff3a1cac055152319617ba] fetching symbol file for Demo1    #开始寻找Demo1的符号文件    
Running mdfind "com_apple_xcode_dsym_uuids == 2CF17905-47FF-3A1C-AC05-5152319617BA"    #使用Spotlight 搜索uuid为2CF17905-47FF-3A1C-AC05-5152319617BA的dsym文件    
#接下来是使用file,lipo,otool等来分析dSYM的相关信息
.
.
-- [2cf1790547ff3a1cac055152319617ba] MATCH (spotlight): ...  #确认找到对应的dSYM文件
.
.
atos -arch arm64 -l 0x10006c000 -o '..../Demo1.app.dSYM/Contents/Resources/DWARF/Demo1' 0x00000001000706e8 0x0000000100070a80

我们看到最后会发现实际上symbolicatecrash是使用atos来寻找调用栈地址对应的调试符号的。

我们来看一下atos所使用的参数:

  1. -arch 所运行设备的架构,有arm64,armv7等等
  2. -l 二进制镜像运行时加载的地址
  3. -o 后面是符号文件或者含有调试符号的可执行文件(debug编译所产生的可执行文件默认是包含调试符号的)。
  4. 再后面就是需要符号化的调用栈地址,5 Demo1 0x00000001000706e8 0x10006c000 + 18152,0x00000001000706e8就是其中的一个地址。

二进制镜像运行时加载的地址通过如下方式获得

Binary Images:        
0x10006c000 - 0x100073fff Demo1 arm64  <2cf1790547ff3a1cac055152319617ba> /var/mobile/Containers/Bundle/Application/7E6DE925-0B33-4699-89F7-05381876AD81/Demo1.app/Demo1

中的0x10006c000就是这个崩溃日志所对应的二进制镜像加载地址。

综上所述,symbolicatecrash主要帮我们做了两件事情,匹配到对应的dSYM文件,使用atos符号化每个调用栈地址。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容