iOS crash log 解析

iOS开发中,经常遇到App在开发及测试时不会有问题,但是装在别人的设备中会出现各种不定时的莫名的 crash,因为iOS设备会保存应用的大部分的 crash Log,所以可以通过 crash Log 来定位 crash 原因。

一. 获取iOS设备上的 crash log

1. 将iOS设备连接到电脑上,打开 Xcode -> Organizer -> Devices,找到该台设备,在 Device logs 中找到 crash log(后缀为 .crash 的 log 文件),将其导出即可。

2. 如果你的应用已经上架App Store,那么开发者可以通过iTunes Connect(Manage Your Applications - View Details - Crash Reports)获取用户的crash log。不过这并不是100%有效的,而且大多数开发者并不依赖于此,因为这需要用户设备同意上传相关信息,详情可参见iOS: Providing Apple with diagnostics and usage information摘要。

二. 解析iOS crash log

获取到的 crash log 中的相关信息都是 16 进制的内存地址,并不能定位崩溃的代码,所以需要将 16 进制的内存地址解析为对应的类及方法。

解析 crash log 需要使用上传应用时所发送的 .app 及 .sYSM 两个文件(所以每次上传新版本时都要保存这两个文件,不然没法解析 crash log),可以将 .app .dYSM 及crash log文件拷贝到同一个文件夹下,使用 Symbolicatecrash 进行解析。

获取 .app 及 .dYSM 文件:在iOS开发中,需要使用Xcode打包生成 .xcarchiver 文件,可以在Xcode - > Organizer - > archive 中进行管理并导出相应的 .xcarchiver 文件,.xcarchiver 文件中就包含 .app 及 .dYSM 文件。

Symbolicatecrash 是一个隐藏文件,并且独立于 Xcode,位置在:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash

在利用 Symbolicatecrash 进行解析之前,要检查 .app .dYSM 及 crash log 三个文件的uuid是否一样,只有三者都一样才能进行解析。查看三个文件的 uuid 方法如下:

1. 查看xx.app文件的uuid的方法,在 terminal.app 中输入:

$ dwarfdump --uuid xxx.app/xxx (xxx工程名)

2. 查看xx.app.dSYM文件的uuid的方法,在命令行输入:

$ dwarfdump --uuid xxx.app.dSYM (xxx工程名)

3. 查看 crash log 文件的 uuid的方法:

在 crash log 文件中,找到 Binary Images: 项目名后面第一个尖括号中的一串码就是改 crash log 文件的 uuid。

利用 Symbolicatecrash 进行解析:

在 terminal.app 中输入如下命令:

$ ./symbolicatecrash xxx.crash xxx.app.dSYM > test.log

该命令会将 crash 文件解析成 test.log 文件,test.log 就是可读的函数文件。

输入上述命令可能会出现Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash line 53.这个错误。

如果出现上述错误,输入命令:export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer,

然后继续执行./symbolicatecrash xxx.crash xxx.app.dSYM > test.log可以成功

三. 其他解析(根据地址解析):

解析某一个地址的内容

方法一:

$ xcrun atos -o xxx.app/xxx -arch armv7 0x38ad42f9 0x38ad42f9 0x38ad42f9(多个16进制地址,使用空格分开)

方法二:

$ dwarfdump -–lookup 0x000036d2 -–arch armv6 xxx.app.dSYM

如果根据以上两个方法操作,均提示找不到地址的话,可以使用方法三:

方法三:

查找以下内容所对应的地址:

(当前代码行地址 = 当前地址 + 地址偏移量,地址偏移量为十进制数值)

10  TestTransform                    0x00057132 0x4f000 + 33074

1. 先说第一种比较简单的方法利用 "当前地址" 和 "当前代码行地址"

$ xcrun atos -o TestTransform.app/TestTransform -arch armv7 0x3d000 0x0004fc5c

//输出结果:

bddeMacBook-Pro:1 baidu$ xcrun atos -o /Users/baidu/Desktop/1/TestTransform.app/TestTransform -l 0x3d000 0x0004fc5c

got symbolicator for /Users/baidu/Desktop/1/TestTransform.app/TestTransform, base address 4000

main (in TestTransform) (main.m:16)

2. 第二种相对复杂一点,涉及到地址的偏移,首先查看起始地址,即使每次iOS app启动都会加载(main module)主模块在不同的内存地址,但是dSYM文件假设你的main module加载在地址0x1000(大多数情况是这个,也有0x4000的)。

获取此地址的方法:

$ otool -arch armv7 -l /Users/cnstar-tech/crash/xxx.app/xxx  | grep -B 1 -A 10 "LC_SEGM" | grep -B 3 -A 8 "__TEXT"

调用以上方法返回结果如下:

Load command 1

cmd LC_SEGMENT

cmdsize 600

segname __TEXT

vmaddr 0x00004000

vmsize 0x00014000

fileoff 0

filesize 81920

maxprot 0x00000005

initprot 0x00000005

nsects 8

flags 0x0

看到vmaddr显示为0x00004000。

然后查看  "TestTransform 0x00057132 0x4f000 + 33074"  使用 起始地址+地址偏移量如:

0x4000 + 33074 = 0xc132   (注意:前面为前面为16进制后面为10进制相加,要都转换成10进制相加,把得出的结果转换成16进制)

就可以使用 "0xc132" 地址查看内容了:

//方法一:

$ dwarfdump --lookup 0xc132 --arch armv7 TestTransform.app.DSYM

//输出结果:

----------------------------------------------------------------------

File: TestTransform.app.DSYM/Contents/Resources/DWARF/TestTransform (armv7)

----------------------------------------------------------------------

Looking up address: 0x000000000000c132 in .debug_info... found!

0x00003947: Compile Unit: length = 0x00007b6e  version = 0x0002  abbr_offset = 0x00000000  addr_size = 0x04  (next CU at 0x0000b4b9)

0x00003952: TAG_compile_unit [1] *

AT_producer( "Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)" )

AT_language( DW_LANG_ObjC )

AT_name( "/Users/baidu/Desktop/TestTransform/TestTransform/ViewController.m" )

AT_low_pc( 0x0000a950 )

AT_stmt_list( 0x0000089f )

AT_comp_dir( "/Users/baidu/Desktop/TestTransform" )

AT_APPLE_major_runtime_vers( 0x02 )

0x00003c22:    TAG_subprogram [39] *

AT_name( "__29-[ViewController aaaaaaaaaa:]_block_invoke" )

AT_decl_file( "/Users/baidu/Desktop/TestTransform/TestTransform/ViewController.m" )

AT_decl_line( 191 )

AT_prototyped( 0x01 )

AT_APPLE_isa( 0x01 )

AT_accessibility( DW_ACCESS_public )

AT_low_pc( 0x0000c09c )

AT_high_pc( 0x0000c182 )

AT_frame_base( r7 )

0x00003c46:        TAG_lexical_block [34] *

AT_low_pc( 0x0000c0d6 )

AT_high_pc( 0x0000c17e )

Line table dir : '/Users/baidu/Desktop/TestTransform/TestTransform'

Line table file: 'ViewController.m' line 193, column 0 with start address 0x000000000000c11e

Looking up address: 0x000000000000c132 in .debug_frame... found!

0x00000160: FDE

length: 0x0000000c

CIE_pointer: 0x00000000

start_addr: 0x0000c09c __29-[ViewController aaaaaaaaaa:]_block_invoke

range_size: 0x000000e6 (end_addr = 0x0000c182)

Instructions: 0x0000c09c: CFA=4294967295+4294967295

//方法二:

$ xcrun atos -o /Users/baidu/Desktop/1/TestTransform.app/TestTransform 0xc132

//输出结果:

__29-[ViewController aaaaaaaaaa:]_block_invoke (in TestTransform) (ViewController.m:193)

四. 如何判断两个 crash log 文件的 crash 是同一个原因:

1. 可以先比较 Triggered by Thread 看看是否为同一个线程,不同,则不是同一原因。

2. 如果有 Last Exception Backtrace,可以先比较 Last Exception Backtrace 中地址的行数,行数不同则原因不同,行数如果相同可以将两个 Last Exception Backtrace 中的地址逐个进行比较,(一般最开始几行和最后几行都是调用系统函数,所以地址都是一样的),直到出现第一个不一样的地址,可以用 dwarfdump 分别解析两个地址,如果解析得到的方法不一样,则 crash 原因可不一样。

五. Xcode 中 Organizer 自动解析:

如果项目是在自己机器上打包的,可以将iOS设备连接到电脑上,这样该设备中的 crash log 就会被 Organizer 自动进行解析,如果没有自动解析,可以 右击 crash log 选择 re-symbolicate 进行解析。(之所以 Organizer 可以进行自动解析,是因为在打包的时候会建立 .app 及 .dYSM 两个文件的索引,所以可以自动解析 crash log 文件)

也可以进行手动建立索引,即将该 App 的 .app 及 .dYSM 两个文件拷贝到同一个文件夹中,然后再用 midimport foldername 命令进行手动建立索引,然后,将 crash log 文件导入 Xcode Organizer 中,就会进行自动解析。(可以批量导入 crash log 文件,批量进行解析)

六. 使用专门的 crash log 解析工具进行解析:

比如QuincyKit, Crashlytics, Flurry等。

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

推荐阅读更多精彩内容

  • 如果大家是用真机在调试的过程中出现了Crash,那么请看iOS调试之 crash log分析 前言 导读:Unde...
    KODIE阅读 6,468评论 7 12
  • iOS 开发过程中会遇到crash,有些很容易就能定位到,例如数组越界、类型不匹配、方法不存在等。但是有些就比较头...
    LoveY34阅读 8,583评论 1 4
  • 本文就捕获iOS Crash、Crash日志组成、Crash日志符号化、异常信息解读、常见的Crash五部分介绍。...
    xukuangbo_阅读 1,578评论 0 0
  • app崩溃后,从crash报告里,往往只能看到堆栈地址信息,完全不可读。要想精确知道哪里出了问题,需要把crash...
    寻雨的人阅读 947评论 0 3
  • ——蚁人 奔着科幻的主题去的,以为会有想象中的...
    丫丫zyc阅读 503评论 0 2