草庐IT

iOS dSYM详解和分析crash,ips文件

搬砖小工 2023-10-11 原文

先上文件,这里放上 dsym 文件夹的链接,可以自己下载放到桌面上脚本打开执行先试一试,crash文件夹可以直接使用,ips 文件夹需要修改脚本里面的路径。如有错误请帮忙指出,谢谢!转载请注明出处,喜欢的话,请点个赞吧!
github
百度网盘 码 ona1
诚通网盘 码 7701

1.什么是dSYM文件

dSYM 文件是Xcode编译后,我们会看到一个同名的 dSYM 文件,dSYM 是保存 16 进制函数地址映射信息的中转文件,存储应用程序的调试 symbols。每次编译项目或者打包的时候都会生成一个新的 dSYM 文件,当我们软件release模式打包或上线后,不会像我们在Xcode中那样直观的看到用崩溃的错误,所以对于每一个发布版本我们都很有必要保存对应的 Archives 文件。不管你集没集成类似Buyly的三方,要符号化分析crash日志还是得要用到对应的dSYM文件,如果没有生成dSYM文件,可以看一下TARGETS下Build Settings里面有没有设置,如下图,文章可能有点啰嗦,请耐心浏览。

image.png


2.什么时候会用到dSYM文件

1、APP提交审核,有闪退bug被拒,审核人员基本会上传crash文件给你,这时候就要自己符号化分析了。
2、你们编译给测试同事的包,如果你们关系好,大概率会重现一遍给你看,不然可能就是导出一个ips文件直接丢给你了,也可能还有一些不太好复现的crash。
3、自己有时候调试的时候可能会用到。

注:ips文件和crash文件不一样,Xcode13,iOS15以前设备ips文件改后缀成crash好像可以,但是之后 Apple 对符号化文件格式进行了 JSON 支持, 所以针对 iOS 15 以上产生的崩溃文件, 写入方式应该是做了调整, 所以在对 iOS 15 以上崩溃文件进行符号化时, ips改后缀会出现符号化失败, 报错 No crash report version in file 的问题,改为直接使用 CrashSymbolicator.py下面会讲到。

注:如果是发布Testflight版本,有些公司APP更新前会先提交Testflight版本公测一下,然后很多crash的日志可以通过Apple Store Connect里面对应的应用,Testflight下的反馈崩溃里面看到,可以直接Xcode打开,直接到Window->Organize->Crashes下直观看到崩溃错误


3.dSYM,ips,crash文件怎么拿到

1、dSYM
编译后Xcode13以前应该在项目的Products文件夹下,右键Show in Finder。
Xcode13后位于(/Users/用户名/Library/Developer/Xcode/DerivedData/对应的应用程序/Build/Products/Debug-iphoneos)。
打包的话位于(/Users/用户名/Library/Developer/Xcode/Archives)目录下,也可以在Xcode选择Window->Organize->Archives,Show in Finder。
2、crash
手机插上电脑Xcode选择Window->Devices and Simulators,找到对应的iphone,View Device Logs,右键Export Log。
3、ips
可能是测试同事可能其它同事可能用户,手机不能连接到电脑,可以在手机设置->隐私->分析与改进->分析数据,可以搜索对应的.ips.sycned文件然后查看导出修改成.ips的后缀就行,如果不是一眼能看到就直接搜项目名字。


4.具体怎么利用dSYM符号化分析

注:dSYM文件要和crash,ips等文件一一对应,否则符号化会失败,比如你1.0.1产生的crash,ips文件要和1.0.1编译的dSYM文件匹配,注意每次编译都会生成新的dSYM文件

1、怎么查看dSYM和ips,crash文件是否一一对应
笔者创建的项目叫Test,查看crash,ips直接双击打开查看,在下面例子图有标记,dSYM使用终端命令查看如下,Test.app.dSYM修改为对应的就行

    dwarfdump --uuid Test.app.dSYM

例子如下,终端显示的是符号 - 拼接的,crash和ips文件都是连起来的。


image.png

image.png

image.png

2、利用symbolicatecrash符号化分析crash文件

注:创建文件夹和文件夹放在哪都能自己看着办只要用到对应文件路径的时候,路径能对应就可以了,以下是笔者自己创建的方式。

image.png

首先在桌面创建一个dsym文件夹,里面再创建一个crash文件夹,dYSM文件和.crash文件拖入进去,symbolicatecrash复制进去(如果不复制工具出来,可以把文件复制到工具文件夹下执行命令),Result.crash是符号化分析后的产物,Makefile是一个用AppleScript写的一个脚本,打开执行就能得到Result.crash(前提里面写的一些路径得一一对应),还可以保存成一个应用程序双击打开执行,具体更多好玩的得自己去了解一下。symbolicatecrash工具存放在该路径下:

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

如果不一样可能是Xcode名字不一样?可以利用下面的命令去查找,如过你的Xcode就叫Xcode话,不然改成自己Xcode路径:

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

当三个文件都在同一个文件夹下后,我们可以通过命令来得到符号化分析后的crash文件,依次执行,命令如下:注:如果不执行第二条命令会有意想不到的结果

    1 cd Desktop/dsym/crash
    2 export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer"
    3 ./symbolicatecrash Test.crash Test.app.dSYM > Result.crash

我们可以先来看看Test.crash日志符号化前后最后异常回溯长什么样子:


image.png

image.png

3、利用atos命令定位问题
其实除了symbolicatecrash工具,atos命令也能简单的分析一下,Test.app.dSYM/Contents/Resources/DWARF/Test 这里就存着具体符号

atos -o 项目名.app.dSYM/Contents/Resources/DWARF/项目名 -l 基地址 偏移后的地址
笔者使用的命令参考如下
atos -o Test.app.dSYM/Contents/Resources/DWARF/Test -l 0x1026b4000 0x1026B9904

image.png

得到的结果如上,没错就是最后异常回溯的第5行,有没有发现偏移后的地址和第6行的第一个地址是一致的,所以第1个地址是开始地址,第2个地址是基地址,第3个 + 22788就是偏移量 这是十进制的,计算如下 0x1026b4000 + 0x000005904(22788转16进制后的值)= 0x1026B9904 直接百度16进制加减法,大佬可以除外

image.png

4、利用CrashSymbolicator.py符号化解析 ips 文件
CrashSymbolicator.py脚本存放在该路径下:

/Applications/Xcode.app/Contents/SharedFrameworks/CoreSymbolicationDT.framework/Versions/A/Resources

如果不一样可能是Xcode名字不一样?可以利用下面的命令去查找,如过你的Xcode就叫Xcode话,不然改成自己Xcode路径:

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

但是这回不能像复制symbolicatecrash工具一样复制出来了,因为这个脚本import其它文件也在同一个目录下,我们可以终端命令进入到这个文件夹下把 dSYM 文件和 ips 文件放入到该文件夹下执行符号化解析命令。


image.png

下面先看两个文件的对比。

image.png

image.png
image.png

image.png

CrashSymbolicator.py 操作稍微和 symbolicatecrash 会有些不同,因为是用 python 写的脚本,所以要使用 python3 来进行调用,否则会报错。(肯定有一大波人默默的在终端输入python查看版本号发现还是2.7左右的版本,内心一顿XXX,其实python3早已经安装了,不信你们终端直接输入python3试试,如果没有那得自己安装了……

python3 CrashSymbolicator.py -d /xxx.app.dSYM -o /xxx.crash -p /xxx.ips

-d '符号表路径' -o '输出符号化路径' -p '苹果给的崩溃日志'

如果是在 CrashSymbolicator.py 文件夹下操作,dSYM 和 ips 文件需要复制到该脚本文件夹下,命令如下:

1 cd /Applications/Xcode.app/Contents/SharedFrameworks/CoreSymbolicationDT.framework/Versions/A/Resources
2 sudo python3 CrashSymbolicator.py -d Test.app.dSYM -o Result.ips -p Test.ips

5.利用AppleScript脚本快速进行符号化分析

上述在文件夹里面执行命令虽然可以完成,但是比较麻烦,笔者做了个脚本执行,下面就看看脚本里面的代码(其实就是封装了几条命令)
同样首先在之前桌面的dsym文件夹下创建一个 ips 文件夹,dYSM文件和 .ips 文件拖入进去,Makefile脚本准备好,打开执行,Result.ips文件就出来了,

image.png

Makefile.scpt代码如下:(具体语法这里就不做讲解了,用户名需要替换成自己的用户名,路径可以自行根据需要更改)

# 打开终端APP
tell application "Terminal"
    # 拼接导出ips结果命令 在此处替换对应的路径
    set pythonOrderStart to "python3 CrashSymbolicator.py"

    # 三个路径的前面的空格不要忽略了
    set dSYMPath to " -d /Users/用户名/Desktop/dsym/ips/Test.app.dSYM"
    set outfilePath to " -o /Users/用户名/Desktop/dsym/ips/Result.ips"
    set ipsPath to " -p /Users/用户名/Desktop/dsym/ips/Test.ips"

    set pythonOrderEnd to ";"

    # 第一条命令 进入CrashSymbolicator.py对应的文件夹下执行操作 因为CrashSymbolicator.py关联其它的库也在这个文件夹内
    set order1 to "cd /Applications/Xcode.app/Contents/SharedFrameworks/CoreSymbolicationDT.framework/Versions/A/Resources;"

    # 第二条命令 分析导出ips结果文件
    set order2 to pythonOrderStart & dSYMPath & outfilePath & ipsPath & pythonOrderEnd

    # 第三条命令 打开分析的结果文件
    set order3 to "open Result.ips"

    # 拼接多条命令
    set order to order1 & order2 & order3

    #多条命令执行用;分割
    do script order

end tell

有关iOS dSYM详解和分析crash,ips文件的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  5. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  6. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  7. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  8. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  9. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  10. ruby - rspec 需要 .rspec 文件中的 spec_helper - 2

    我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只

随机推荐