符号化你的iOS崩溃报告

前言

本文翻译自Symbolicating Your iOS Crash Reports。这是一篇对于iOS崩溃报告符号化的比较全面的文章。我对Symbolicatecrash工具做了比较完善的封装,一句话就可以符号化你的崩溃报告,还集成了检查UUID匹配的功能。

sh symbolicate.sh Crasher.crash Example/Crasher.app > Crasher_Symbolicated.crash

或者

sh symbolicate.sh Crasher.crash Example/Crasher.app.dsym > Crasher_Symbolicated.crash

项目地址:https://github.com/JohnWong/symbolicate

准备开始

你一定已经处理过你的app的崩溃报告,但是其堆栈回溯包含难以辨认的内存地址。作为一个开发者该怎么办呢?简单说来,你需要将调试符号应用在堆栈追踪上使其可读,这个过程被称作符号化。

但是在我们准备开始之前,你可以使用Crasher,它提供了一个示例崩溃报告让你来解码。

你应该有.crash文件。如果没有,你可以从iTunes Connect上获取,通过Xcode(Window > Devices)直接从链接的设备上获取,从连接的设备(Settings > Privacy > Diagnostics & Usage),或者亲自动手使用PLCrashReporter框架。你可能已经使用第三方崩溃报告服务,它将会在你正确设置后为你符号化崩溃报告。

依赖于你的app的构建如何配置,你需要下列文件中一个或者两者都需要:

  • 崩溃的应用构建的.app。包里包含了app的二进制,可能包含了调试符号。(如果你有一个.ipa,你可以把它当作一个.zip文件来解压出其中的.app。)
  • 崩溃的应用构建的.dSYM。如果你的.app不包含调试符号,这将是你的应用的包含调试符号的副产品。

你需要哪一个?在Xcode里,在构建设置中寻找“Strip Debug Symbols During Copy”(COPYPHASESTRIP)。当启用时,调试符号将会在你的.app中省略,并放置在一个.dSYM文件中。否则你的.app包含了这些符号。(为了混淆,调试符号在release构建中默认剥离。你大概不应该修改release配置的设置。)

但是等一下,什么是调试符号?

在我们的用途下,一个调试符号是一个程序员给一个方法所取的可读的名字。编译器通过减少这些命名的调试符号到其自身的符号来混淆代码。你不能指望这些符号在两次构建后相同,即使是你构建相同的代码两次。

检查Crash

如果你通过Xcode的Organizer从设备拉取到崩溃日志,你的崩溃报告可能自动符号化UIKit或者其他iOS框架。如果你的Xcode仍然了解你的构建,它将会自动符号化你的崩溃报告。

如果不是这种情况,那么你需要自己来符号化。

使用“Symbolicatecrash”工具来符号化

幸运的是Apple提供给我们一个脚本来检索调试符号并应用到崩溃报告上。

对于Xcode 6来说,你可以在这里找到: /Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/Current/Resources/symbolicatecrash

或者如果你在使用Xcode 5: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKitBase.framework/Versions/Current/Resources/symbolicatecrash

为了使用这个工具,你需要导出DEVELOPER_DIR环境变量到你的Xcode安装目录的合适的路径:

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

将你的.crash.app.dSYM文件放在同一个目录下并运行:

symbolicatecrash -v ScaryCrash.crash > Symbolicated.crash

你可能需要制定app的二进制:

symbolicatecrash -v ScaryCrash.crash ./Crasher.app/Crasher > Symbolicated.crash

如果你在使用Crasher的示例中方便的脚本,可以省略verbose标记:

sh symbolicate6.sh ScaryCrash.crash ./Crasher.app/Crasher > Symbolicated.crash

验证你的符号化

如果符号化并不起效,再次检查你拿到的是正确的.dSYM.app。你可以通过对比崩溃报告中构建的UUID和app二进制中的UUID来再次检查:

dwarfdump –uuid Crasher.app/Crasher

UUID: B00CDF0C-2965-3095-B1E8-6078B12D79E5 (armv7) Crasher.app/Crasher UUID: 3F3BE3C6-DD2E-3E23-A603-A18097C9317F (arm64) Crasher.app/Crasher

并且在dSYM中:

dwarfdump –uuid Crasher.app.dSYM/Contents/Resources/DWARF/Crasher

UUID: B00CDF0C-2965-3095-B1E8-6078B12D79E5 (armv7) Crasher.app.dSYM/Contents/Resources/DWARF/Crasher UUID: 3F3BE3C6-DD2E-3E23-A603-A18097C9317F (arm64) Crasher.app.dSYM/Contents/Resources/DWARF/Crasher

对于崩溃报告中的UUID:

0xa8000 – 0xaffff Crasher armv7 <b00cdf0c29653095b1e86078b12d79e5> /var/mobile/Containers/Bundle/Application/956755E3-6C66-4E87-A8BC-352FD4BE3711/Crasher.app/Crasher

symbolicatecrash工具的verbose日志也列出了其发现的UUID。

“Symbolicatecrash”工具故障排除

如果你仍然感到困惑,小心检查符号化的日志。符号化工具试图通过匹配你的app和其他动态框架的UUID来定位到合适的文件。查找你的app名称或者UUID来看是否匹配。

…….fetching symbol file for Crasher[K–[undef] Searching []…– NO MATCH Searching in Spotlight for dsym with UUID of b00cdf0c29653095b1e86078b12d79e5 ... Number of symbols in /Users/You/Workspace/Crasher.app/Crasher: 1 + 106 = 107 Found executable /Users/You/Workspace/Crasher.app/Crasher – MATCH

这里有一个你可能遇到的Spotlight无法定位到你的.dSYM的日志的示例:

Did not find executable for dsym Warning: Can't find any unstripped binary that matches version of /private/var/mobile/Containers/Bundle/Application/956755E3-6C66-4E87-A8BC-352FD4BE3711/Crasher.app/Crasher

或者其他无效输入:

fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: can't figure out the architecture type of: ./Crasher.app.dSYM.zip ./Crasher.app.dSYM.zip doesn't contain armv7 slice

Xcode 6版本的symbolicatecrash工具尝试修复一些Xcode 5版本所面对的Spotlight问题。如果你仍然有麻烦,它可能是一个Spotlight的文件索引问题。试试:

mdimport -g /Applications/Xcode.app/Contents/Library/Spotlight/uuid.mdimporter .

使用命令行工具链

我们可以更深入一步,使用开发者工具链来一行一行地符号化堆栈追踪的内存地址。如果你以前使用这种方法遇到了很大麻烦,可能是由于.crash格式在近几年变化了。

首先,我们再看一下崩溃报告中的堆栈追踪:

... 13 Crasher 0x000aeef6 0xa8000 + 28406 ...

最左边的十六进制值0x000aeef6是堆栈地址。第二个十六进制值0xa8000时应用加载的地址。前面带加号的数字28406是堆栈地址和加载地址相减的十进制值。你将会注意到崩溃报告下方的“Binary Images”是一个带有一些内存地址的动态库的列表。二进制的起始地址与堆栈追踪的加载地址是匹配的。

Binary Images: 0xa8000 – 0xaffff Crasher armv7 /var/mobile/Containers/Bundle/Application/956755E3-6C66-4E87-A8BC-352FD4BE3711/Crasher.app/Crasher

接下来,为了好好测量,我们将会使用file或者lipo -info来验证我们的可执行文件包含我们崩溃的架构:

file Crasher.app/Crasher

Crasher.app/Crasher: Mach-O universal binary with 2 architectures Crasher.app/Crasher (for architecture armv7): Mach-O executable arm Crasher.app/Crasher (for architecture arm64): Mach-O 64-bit executable

现在我们已经拿到我们需要的所有东西。我们将会使用atos来将我们的地址转换成调试符号。注意看我们如何提供加载地址,紧跟着的是特定的崩溃的架构的堆栈地址:

atos -arch armv7 -o Crasher.app/Crasher -l 0xa8000 0x000aeef6

main (in Crasher) (main.m:14)

就是这样。如果你有兴趣深入钻研,可以阅读Mach-O对象文件格式并检查Mach-O的一系列命令行工具,也就是otoollipo

时间: 2024-09-05 03:05:18

符号化你的iOS崩溃报告的相关文章

Android和Ios的crash reporter(崩溃报告采集与上传)

Crash Report,这在大型软件开发领域是很常见的功能,就是能够当程序崩溃退出后,能够将崩溃时的信息,最好是携带dmp文件发送给服务器,这样开发人员既可以获得分发出去的客户端的崩溃率统计,也可以针对出现的错误进行及时的纠正,之前在PC的端游时代,这是很常见的做法,最近进行了在手游上的关于crash report的相关研究,并且为项目编写了一个相对完善的CrashReport模块.        这个模块的来源于手游项目正式上线,但是很多玩家反馈闪退,但是我们只能听到反馈闪退,却不能找到原因

iOS崩溃调试

在iOS开发调试过程中以及上线之后,程序经常会出现崩溃的问题.简单的崩溃还好说,复杂的崩溃就需要我们通过解析Crash文件来分析了,解析Crash文件在iOS开发中是比较常见的. 现在网上有很多关于解析崩溃信息的博客,但是大多质量参差不齐,或者有些细节没有注意到.今天写一篇博客总结一下我对崩溃调试的使用和技巧,如果有哪些错误或遗漏,还请指点,谢谢! 获取崩溃信息 在iOS中获取崩溃信息的方式有很多,比较常见的是使用友盟.百度等第三方分析工具,或者自己收集崩溃信息并上传公司服务器.下面列举一些我们

iOS崩溃调试的使用和技巧总结

 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 在iOS开发调试过程中以及上线之后,程序经常会出现崩溃的问题.简单的崩溃还好说,复杂的崩溃就需要我们通过解析Crash文件来分析了,解析Crash文件在iOS开发中是比较常见的. 现在网上有很多关于解析崩溃信息的博客,但是大多质量参差不齐,或者有些细节没有注意到.今天写一篇博客总结一下我对崩溃调试的使用和技巧,如果有哪些错误或遗漏,还请指点,谢谢! 获取崩溃信息 在iOS中获取崩溃信息的方式有很多,比较常见的是

英国即将成立一个数据中心崩溃报告调查小组

为了帮助行业从像最近的英国航空公司发生的IT事故这样的事件中学习,此次中断事件在5月底的那个周末取消了数千架次的航班.目前一个即将成立的行业组织将致力于分享有关数据中心故障的数据. 如果航空公司的一架飞机发生空难,那么就会立即进行中立调查,以查明出现的问题.数据中心也可以提供这样的关键服务,但其故障或潜在的灾难通常被隐瞒,或受到涉及公司的内部查询,最终被不对外披露协议所掩盖,其结果是相同的故障将一再反复发生. 数据中心事件报告网络旨在通过建立一个中立和匿名的论坛来共享关于导致严重的IT故障或近乎

iOS的应用程序崩溃率为何高于Android

应用崩溃的主要原因之一就是目前iOS和Android操作系统的分散和混乱.随着苹果和谷歌都发布了更多的全新操作系统,应用开发人员在测试自己开发的应用时需要面临着更多的操作系统.据调查显示,12月1日到15日之间,至少有23个不同iOS系统和33个Android系统存在着应用崩溃的情况. 图:iOS应用的整体崩溃了要高于Android iOS应用的崩溃率要高于Android 应用崩溃的情况同时存在于Android和iOS两大平台,而且其中占比例最大的是iOS 5.0.1,整体崩溃率达到了28.64

为什么iOS的应用程序崩溃率高于Android

编者按:有没有想过为什么某些应用程序会如此频繁的崩溃吗?原因是多种多样的,根据你所使用的设备不同原因也是不同的,比如说苹果iOS设备(iPhone.iPad)或Android设备.本文将通过详实的统计数据为读者详细解析. 应用崩溃的主要原因之一就是目前iOS和Android操作系统的分散和混乱.随着苹果和谷歌都发布了更多的全新操作系统,应用开发人员在测试自己开发的应用时需要面临着更多的操作系统.据调查显示,12月1日到15日之间,至少有23个不同iOS系统和33个Android系统存在着应用崩溃

iOS编译过程的原理和应用

前言 一般可以将编程语言分为两种,编译语言和直译式语言. 像C++,Objective C都是编译语言.编译语言在执行的时候,必须先通过编译器生成机器码,机器码可以直接在CPU上执行,所以执行效率较高. 像JavaScript,Python都是直译式语言.直译式语言不需要经过编译的过程,而是在执行的时候通过一个中间的解释器将代码解释为CPU可以执行的代码.所以,较编译语言来说,直译式语言效率低一些,但是编写的更灵活,也就是为啥JS大法好. iOS开发目前的常用语言是:Objective和Swif

[翻译] iOS开发工具的介绍(第一部分)

IOS DEVELOPMENT TIPS & TRICKS - PART I http://blog.trifork.com/2013/12/19/ios-development-tips-tricks-part-i/   As you might know, I am very fond of developing apps for the iOS platform. I started back in mid-2009 by trying to create an app for the D

查看iOS Crash logs的方法_IOS

当应用在设备中运行发生崩溃,iOS将记录这些错误日志并且创建了崩溃报告(Crash Report).崩溃报告中包含了iOS的版本.日期.异常类型.堆栈跟踪以及其他信息. ① 在Xcode中查看崩溃报告 当应用还在开发过程中发生了崩溃,则直接可以使用Xcode Organizer来查看崩溃报告.按如下操作: 1.打开Organizer: 2.选择"Devices"选项(界面的顶部): 3.选择左侧菜单栏中的device项: 4.选择"Devices"中的"D