程序调试 (九) —— Crash日志的获取和符号解析(一)

版本记录

版本号 时间
V1.0 2021.08.22 星期日

前言

程序总会有bug,如果有好的调试技巧和方法,那么就是事半功倍,这个专题专门和大家分享下和调试相关的技巧。希望可以帮助到大家。感兴趣的可以看下面几篇文章。
1. 程序调试 (一) —— App Crash的调试和解决示例(一)
2. 程序调试 (二) —— Xcode Simulator的高级功能(一)
3. 程序调试 (三) —— Xcode Simulator的高级功能(二)
4. 程序调试 (四) —— Xcode内存管理(一)
5. 程序调试 (五) —— 使用Build Configurations 和 .xcconfig 构建你的App(一)
6. 程序调试 (六) —— 使用Build Configurations 和 .xcconfig 构建你的App(二)
7. 程序调试 (七) —— 基于iOS的Charles Proxy教程(一)
8. 程序调试 (八) —— 基于iOS的高级Charles Proxy教程(一)

开始

我们在开发的过程中,总要遇见崩溃,有的可以通过Xcode调试解决崩溃,但是对于不好复现的崩溃或者手机拿不到没办法调试的崩溃就没办法进行调试解决崩溃了,这个时候我们就必须获取崩溃手机的崩溃日志,然后通过dSYM进行崩溃日志的反解,最终获取反解以后可以定位到符号表的日志,里面有崩溃的堆栈,通过这个堆栈就可以对崩溃进行分析了。

本文主要涉及两个方面:

  • 崩溃日志的获取
  • 崩溃日志的dSYM反解析

崩溃日志的获取

iOS设备上的应用闪退时,操作系统会生成一个崩溃报告,也叫崩溃日志,保存在设备上。

获取崩溃日志一般有下面几个方法:

1. 使用Xcode

如果你有Xcode可以使用它来获取崩溃日志,将崩溃的手机连接到Xcode上。从菜单栏上选择 Window 菜单,然后选择Devices and Simulators然后选择View Device Logs

然后就是下面这个崩溃目录:

还可以根据时间进行排序。

里面是所有的崩溃日志,可以看见,这都是解析前的,你是无法反解到符号表的。

右击你想看的日志,然后就可以选择Export Log进行导出。

2. iTunes Connect

应用提交到App Store后,你也能从 iTunes Connect 获取到用户的崩溃日志. 登录到 iTunes Connect 上, 选择 Manage Your Applications,点击相应的应用, 点击应用图标下面的 View Details 按钮, 然后点击右栏Links部分的Crash Reports

如果没有崩溃日志,试试点击Refresh按钮刷新一下。如果你的应用还卖得不多,或者刚上架不久,iTunes Connect账号上也可能还没有任何崩溃日志。

3. 使用第三方软件:itools等

如果你平时不用iTunes,而是使用itools这类第三方的软件对iPhone设备进行管理,也是没问题的。

打开itools,在你的设备下,找到“高级功能”,点击“崩溃日志”,然后将需要的日志导出到电脑里面就可以了!

开发者一般都是直接用第一种,毕竟手边有Xcode,直接也就导出来了。

4. 手机设置页面

从设置 -> 隐私 -> 分析与改进 -> 分析数据 里也可以看见崩溃的日志。



获取dSYM包

这个也是要准备的,用来反解符号用的,一般在打包机里可以直接拿到。对于大一点的公司都有专门的打包部门,直接从他们那里的入口获取就行。

下面我们就说下如果是用自己的电脑打包的情况。

自己的电脑打包
首先是用自己的电脑打包,选择Product ->Archive进行构建打包,这里注意只有真机才可以。

打完包以后,选择Window --> Organizer


然后显示下面的页面

选中自己刚打的包,右键,Show in Finder

会看到一个.xcarchive的文件。右键,显示包内容。在名为dSYMs的文件夹,里面找到.app.dSYM文件。

题外话:在名为Products文件夹中,点击进入Applications文件夹,还可以找到.app(可能不带.app后缀)文件。这个在解析崩溃中是用不到的。

已经上传到Apple Store的包

这个有两种方法。

  • Archives organizer,选择你之前提交到App StoreArchive文件选择Download dSYM

Xcode会下载dSYM文件并且把他们插入到选择的Archive中。这时候再按照前面自己的电脑打包那个步骤去取出来dSYM文件就行了。

  • 自己进入app管理后台,点击TestFlight(以前是Activity),找到你想要的构建版本,点击进入,选择构建版本元数据,点击下载dSYM。因为一般都会开启bitcode,所以下载的dSYM是一个zip包。

几个打出来的包没有.app.dSYM文件的原因

  • 1)在Build Settings中,搜索Debug Information Format,查看值是否为DWARF with dSYM File。如果选为DWARF则不会产生dSYM文件,必须选择DWARF with dSYM File才会生成符号表文件。

像上面这种设置,就是测试包不会产生dSYM文件,只有release才会产生。

  • 2) 在Build Settings中,搜索Generate Debug Symbols,看一下下面的值是否都为Yes,如果为No,则不会生成符号表文件,打出来的包也就找不到.app.dSYM文件。

总之,只有Debug Information FormatDWARF with dSYM FileGenerate Debug SymbolsYES,这两个条件同时满足时,才能生成.app.dYSM文件。xcode打出去的包默认是release包,如果你把打出去的包改为了debug包,那么Debug Information Format里的debug项也要改为DWARF with dSYM File


获取symbolicatecrash

symbolicatecrash 是Xcode自带的一个分析工具,可以通过机器上的崩溃日志和应用的.dSYM文件定位发生崩溃的位置,把crash日志中的地址替换成代码相应位置。

具体可参考结合dSYM文件分析crash日志。

特别注意:可能不同版本Xcode或者mac系统不同,symbolicatecrash所在文件夹也不一样,不能用别人博客里提供的路径去找,一定要使用如下命令去找,这才是本机symbolicatecrash所在的有效路径。

终端中执行下面命令:

find /Applications/Xcode.app -name symbolicatecrash -type f

稍等就会输出symbolicatecrash路径

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/iOSSupport/Library/PrivateFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash
/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/symbolicatecrash
/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/symbolicatecrash
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/DVTFoundation.framework/symbolicatecrash
/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash

可以看见,只有最后一个是我们想要的。

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

把它粘贴出来就可以了。


崩溃日志反解析

校验匹配

注意:这一步不是必须的,当你可以确定dSYM包和崩溃日志是相互匹配的,就不用这么校验一下。其实一般情况下都是可以确定是匹配的,因为我们大多数都是根据崩溃日志的buildId号去下载的dSYM包。这里列出来这种情况,只是说一下如果你不知道是不是匹配的,这个如何确定。我们一般就是通过UUID是不是一个进行匹配。

  • 首先获取dSYMUUID
$ dwarfdump —u 文件路径/xxx.app.dSYM
或者
$ dwarfdump --uuid xxx.app.dSYM

我们看下控制台

  • 接着我们打开崩溃日志,全局搜索Binary Images

可以看见UUID是一样的。

最后需要说明的是:

同一个ipa包,不管产生多少个.crash文件,这些.crash文件的UUID都是同一个,即和这个.ipa对应的.app.dSYM文件的UUID相同。

日志解析

symbolicatecrash、解析前的崩溃日志、dSYM文件放在一个文件夹里,如下所示:

下面就是运行symbolicatecrash进行解析了。

  • cd到目标文件夹。
cd /Users/xxx/Desktop/Crash崩溃解析 
  • 执行symbolicatecrash
./symbolicatecrash /Users/xxx/Desktop/Crash崩溃解析/11.crash /Users/xxx/Desktop/Crash崩溃解析/OneTravel.app.dSYM > new_symbol.crash
  • 处理可能的报错
Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash line 69.

输入下面命令

export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer"

然后继续执行一下上面那个解析崩溃的指令。

./symbolicatecrash /Users/xxx/Desktop/Crash崩溃解析/11.crash /Users/xxx/Desktop/Crash崩溃解析/OneTravel.app.dSYM > new_symbol.crash

这样就完成解析了,下面我们就看下崩溃所在的文件夹。

new_symbol.crash就是解析以后的崩溃文件。

打开这个解析后的文件,我们看下是否已经有我们想要的符号了。

Date/Time:           2021-08-17 16:17:33.5836 +0800
Launch Time:         2021-08-17 16:17:32.4767 +0800
OS Version:          iPhone OS 14.6 (18F72)
Release Type:        User
Baseband Version:    6.71.01
Report Version:      104

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000186597c9c
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5
Terminating Process: exc handler [4581]
Triggered by Thread:  0

Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: trying to lock recursively

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libdispatch.dylib               0x0000000186597c9c _dispatch_once_wait$VARIANT$armv81.cold.1 + 28
1   libdispatch.dylib               0x0000000186560da8 _dispatch_gate_broadcast_slow$VARIANT$armv81 + 0
2   OneTravel                       0x000000010504cee8 +[DCLocationManager sharedInstance] + 5213928 (DCLocationManager.m:86)
... ...

下面就是看你如何解决这个崩溃了,下半场交给你了哈。

参考文章

  1. 使用symbolicatecrash解析崩溃日志
  2. 了解和分析iOS Crash Report
  3. ios 分析.crash日志解决偶现bug

后记

本篇主要讲述了Crash日志的获取和符号解析,感兴趣的给个赞或者关注~~~

你可能感兴趣的:(程序调试 (九) —— Crash日志的获取和符号解析(一))