zoukankan      html  css  js  c++  java
  • IOS错误日志抓取和分析

    在调试自己和别人的IOS App时,发生Crash是非常正常的情况,分析这些Crash的主要手段之一就是分析Crash发生时产生的错误日志。对于未越狱的IOS设备,获取错误日志主要通过Xcode自带的日志获取功能,但是这种方式有以下两点限制: 


    1.只能获取开发者自己开发的App的日志,无法获取第三方App的日志。 
    2.自动化工作难度较高(错误日志收集,错误日志整理等)。

    文中,笔者首先简单介绍了一下使用Xcode抓取和分析错误日志的方法,然后为了克服上面的两个缺陷,笔者调研了一套可自动化的第三方App在本地测试的错误日志抓取方法。最后,笔者简单介绍了一下IOS错误日志的基本构成,供读者进行日志分析和分类收集参考。

    错误日志的获取

    方法1: 使用Xcode获取错误日志

    对于自己研发并在测试机上测试的应用,我们可以通过Xcode来分析测试过程中的错误日志。但是App一但发布到AppStore,那么我们如何获取用户在使用过程中产生的错误日志呢?为了解决这一问题,苹果官方提供了一套供App开发者使用的基于Xcode工具的解决方案。

    对于App在测试机上运行的情况,Xcode支持获取Apple机器的Log的情况。打开Xcode并打开自己开发的AppProject,在Window->Devices中,找到对应的设备 

    点击View Device Logs 

    图片

    在此处可以查看设备的日志信息,确认测试机连接到Mac,即可看到已经符号化完成的错误日志 

    图片

    对于在AppStore已经发布的App产生的错误日志,在Window->Organizer中,找到对应的App,在Crashes目录中找到AppStore下载的其他使用者使用过程中产生的错误日志。

    图片

    方法2: 使用命令行获取错误日志

    苹果官方提供的方案虽然能够成功的获取错误日志,但是有一个前提,那就是用户必须是App的开发者,如果我们需要获取第三方开发者开发的App的错误日志,那么上述方法就不能正确的工作了。适用于这一场景的可行方案之一,是使用libimobiledevice库中的idevicecrashreport命令来获取。

     
    libimobiledevice库:libimobiledevice 是Github上的一个开源库,主要提供和未越狱的苹果IOS设备通信的服务。包括App安装,系统日志获取,设备信息获取和错误日志获取等能力(其他具体的服务能力可以参考libimobiledevice的官网:http://www.libimobiledevice.org/)。

    本文具体主要使用idevicecrashreport和ideviceinstaller命令。

    假设你获取的第三方App的Ipa已经发布到App Store,那么你可以直接从App Store上下载并测试。如果未发布到App Store,则需要使用ideviceinstaller命令安装该App到指定的手机。具体的command如下:

    图片

    出现如下日志后安装成功(IOS > 9的设备使用ideviceinstaller会出现Segmentation fault,但是不影响App本身的安装) 

    图片

    然后就可以愉快地测试App了:)

     

    App出现Crash后,ios设备本身保留了CrashReport。为了将设备上的CrashReport拷贝到本机,就需要使用idevicecrashreport命令了。具体的command如下:

    图片

    如果需要在设备上保留错误日志,使用-k选项;如果需要将crashreport单独存放,使用-e选项。 


    导出后的文件结构如下所示: 

    图片

    其中wifi为IOS的wifi信息,此处我们并不关心。我们关注其中CrashDemo开头的两个后缀为ips的文件(CrashDemo是我用来测试的App名)。使用Xcode打开一个ips文件。如下所示: 

    图片

    图片

    这样我们就成功得到了App的错误日志。

    该方法的优点: 

    1. 可以获取第三方App的错误日志。 

    2. 方法全部通过命令行方式进行获取,方便编写shell进行自动化获取 

     

    该方法的缺点: 
    无法获得AppStore上使用者相关的错误日志。

    错误日志的符号化

    我们可以注意到,上述第二种错误日志的获取方法所获取到的日志,日志中的堆栈信息并不像Android等错误日志中的堆栈信息那样打印出了调用的堆栈,而是使用段基址 + 偏移地址的格式显示。除此之外,对于错误信息,也进行了相关的处理。为了能够正确的分析错误,我们需要对这些地址进行符号化,从而将日志翻译成能够处理的信息。一般来说,符号化日志需要开发者提供编译App后生成的dsym文件,该文件包含了App编译后的所有类和函数的地址信息。但是如果我们需要分析第三方开发者的App,那么我们是无法获得该App的dsym文件的。下面给出了无dsym文件场景下符号化日志信息的方法。

    不带dsym文件的日志符号化

    使用symbolicate符号化错误日志文件 

    symbolicate:symbolicate是github开源的三方脚本,该脚本使用xcode自带的符号化工具symbolicatecrash进行符号化。symbolicate支持两种符号化的方法。使用App的dsym文件和使用App的ipa解压后的App文件夹。 


    那么为什么不直接使用xcode的symbolicatecrash命令进行符号化呢?这一点我们可以通过分析symbolicate.sh的源码来了解。 


    通过分析源码,我们可以看出xcode自带的symbolicatecrash工具的主要缺陷有两点: 


    1. 工具随着Xcode版本有着比较大的变更。 
    2. 缺少对错误日志UUID和App有效性的校验。

    在我们的场景中,我们没有App的dsym文件,所以我们主要依赖App的ipa解压后的文件夹来进行调试,解压ipa可以使用mac自带的unzip命令

    图片

    解压后的app目录在appdirpath/Payload目录下,在Finder中显示如下: 

    图片

    symbolicate脚本的使用方法如下:

    图片

    符号化后的错误日志文件如下: 

    图片

    可以看见,堆栈信息的部分的已经完成了符号化,现在我们可以开始错误日志的分析了。

    错误日志的分析

    在完成了错误日志的符号化之后,接下来就是对错误日志的分析了,苹果官方提供的错误日志格式还是非常详细的。下面简单介绍错误日志(CrashReport)的基本格式。

    CrashReport基本格式

    IOS在以下两种情况下会产生错误日志: 
    1.应用违反操作系统规则。 
    2.应用中有Bug。

    1中“违反操作系统规则“主要包括watchdog终止,用户强制结束和低内存终止三种情况。 


    2则是应用本身导致的问题。 


    1和2的日志格式不同,本文主要介绍2的情况下产生的错误日志的基本格式。

    下图是一个错误日志的例子 

    图片

    整个错误日志分为进程信息、Crash信息、Crash异常、线程回溯、线程状态和二进制映像6个部分。 


    进程信息:包括Crash的ID(Incident Identifier),设备的Model和标识符(CrashReporter Key和Hardware Model),App信息(Path、Identifier、Version和CodeType),以及启动的进程信息(Process、ParentProcess)。 


    Crash信息:包括Crash发生的时间和系统号 


    Crash异常:包括异常类型(Exception Type)和异常码(Exception Codes)。此处对经常出现的异常码汇总如下(苹果的异常码还是很生动的) 


    0x8badf00d:(ate bad food)这个异常码表示该异常是由watchdog终止引发的。 
    0xbad22222:这个异常码表示该异常是由VoIP被过于频繁重启引发的。

     
    0xdeadl0cc:(dead lock)这个异常码表示该异常是由于App长期占用系统资源而被系统强行终止引发的异常。 


    0xdeadfa11:(dead fail)这个异常码表示该异常是由用户强制终止引发的。

    线程回溯信息

    回溯信息包括四列: 

    帧编号 
    二进制库的名称 
    调用方法的地址 
    第四列分为两个子列,一个基本地址和一个偏移量。

    对于未符号化的日志,这一列的内容比较难以理解

    图片

    对于符号化后的日志,该列内容如下:

    图片

    分别为该进程调用的函数名称和对应的代码行号

    线程状态:Crash中寄存器中的值(不常用,堆栈信息足以完成大部分的Crash分析) 


    二进制映像:Crash发生时已经载入的二进制文件

    以上就是本文的全部内容了,文中涉及到的开源库的Github地址如下: 


    libimobiledevice: https://github.com/libimobiledevice/libimobiledevice 


    symbolicate: https://github.com/JohnWong/symbolicate

    日行一善, 日写一撰
  • 相关阅读:
    iOS 面试题汇总
    iOS管理文件和目录
    文件管理
    Cocoapods依赖管理
    IOS开发几何类方法 CGGeometry.h文件
    CGContext
    respondsToSelector的相关使用
    Java数组5作业(2015-8-27)
    Java错误1(2015-8-27)
    Java数组4(2015-8-27)
  • 原文地址:https://www.cnblogs.com/xiyuan2016/p/14296632.html
Copyright © 2011-2022 走看看