你的一个Mac应用程序崩溃了吗?如果你从用户那里得到了一份崩溃报告,或者从Sentry那里得到了一份没有符号的崩溃日志,我将指导你如何将其解码为你可以用来调试崩溃的东西。
对于我自己的应用程序Recut,我已经添加了Sentry库来捕获崩溃报告。不管是什么原因,Sentry并没有将我的崩溃报告符号化。我已经上传了dSYMs,但它似乎对它们视而不见。所以。我就自己把它们符号化吧!
下面是如何手动操作的,我还编写了一个Ruby脚本来符号化整个崩溃报告。
1.从Sentry下载未符号化的崩溃报告。
在错误报告中,选择Raw 和Unsymbolicated ,然后点击下载。在你选择Raw之前,下载按钮不会出现。不要把它作为默认的Symbolicated ,否则下载的日志会有一堆<redacted> ,而这些地方应该是内存地址。

2.制作一个新的空文件夹
然后打开一个终端,cd 到你的新文件夹。我们将在这里复制必要的文件,因为它们都需要在一个地方才能正确地符号化。
3.打开Xcode和组织者
在Xcode中,在Window菜单下,点击Organizer来打开它。
这里面包含了你的应用程序的所有存档的构建。
4.找到正确的版本
将崩溃日志中的信息(或Sentry中的信息)与Xcode的组织者中的版本列表相匹配,并选择一个匹配的版本。
除非所有的版本都吻合,否则符号化将无法正常工作(或者根本无法工作?
在我的例子中,我使用的是2.0.1版本,构建552。

5.把文件从版本中复制出来
右键单击发行版,并选择在Finder中显示。
这将打开一个Finder窗口,里面有一个单一的.xcarchive 文件。
右键单击该xcarchive,并选择显示软件包内容。
你应该看到一堆这样的文件夹。

我们需要的文件在两个地方。
- 从
dSYMs:把所有东西都复制到你创建的文件夹中。 - from
Products/Applications: 将你的应用程序复制到同一文件夹中。
请确保你复制了这些文件!不要移动它们。
这个xcarchive是你进入王国的钥匙......如果你失去了这些文件,你将无法再象征性地编写崩溃报告。所以不要管原始文件,只管复制。
6.运行symbolicator工具
你应该有一个预装的命令行工具,叫做atos 。从它的man 页面,它的工作是 "将数字地址转换为二进制图像或进程的符号"。
现在在你的文件夹中,你应该至少有这3样东西:
- 崩溃报告文件(一个文本文件)
- YourApp.app.dSYM
- YourApp.app
你可以通过将几个内存地址插入atos 来手动符号化一个单行。例如,这里是我的应用程序中崩溃的前几行:
Thread 0 Crashed:
0 Recut 0x204302872 0x204296000 + 444530
1 Recut 0x204308b5c 0x204296000 + 469852
2 Recut 0x204308afe 0x204296000 + 469758
为了查找发生崩溃的函数和文件,我将使用前两个内存地址并运行atos:
atos -o Recut.app/Contents/MacOS/Recut -arch x86_64 -l 0x204296000 0x204302872
这样就可以打印出崩溃的位置,我就可以去找它了:
closure #1 in WaveDataManager.samplesForResolution(_:) (in Recut) (WaveDataManager.swift:150)
7.运行一个脚本来自动符号化一切
我写了一个Ruby脚本,在每个相关的行上运行atos 命令,并一次性地将整个崩溃报告符号化。它就在GitHub的gist中。
要使用它:
- 下载它
- 使其可执行
chmod +x ./symbolicate.rb - 在你的文件上运行它。
symbolicate.rb 53c91214f29a42f1a0d19f86b7236e70.crash x86_64 Recut.app Recut.app.dSYM
这将打印出崩溃报告,但其中有你自己应用程序的调用符号:
Thread 0 Crashed:
0 Recut 0x204302872 closure #1 in WaveDataManager.samplesForResolution(_:) (in Recut) (WaveDataManager.swift:150)
1 Recut 0x204308b5c thunk for @callee_guaranteed () -> () (in Recut) (<compiler-generated>:0)
2 Recut 0x204308afe thunk for @escaping @callee_guaranteed () -> () (in Recut) (<compiler-generated>:0)
...
你可以通过-g ,对输出进行着色,以突出与你的应用程序的代码相对应的行。
默认情况下,它隐藏了不包含任何对你的应用程序代码的调用的线程。它还隐藏了崩溃报告结尾处的二进制文件的大列表。你可以用标志来关闭这些。
这里有完整的使用信息:
Usage: symbolicate -g -b -t [crash_log] [arch] [app_bundle] [dsym]
The crash log, app, and dSYM should all be in the current working directory.
In Xcode: Window > Organizer
right-click the release, Show in Finder
right-click the xcarchive, Show Package Contents
copy files from `dSYMs` and `Products/Applications` into a new empty folder
copy the crash log to the same folder
-g Colorize the output to highlight this app's lines
-b Show the 'Binary Images' section (by default this is omitted for brevity)
-t Show all threads, including ones that have no calls to your app
crash_log text file from Sentry
arch x86_64 or arm64 (get this from Sentry)
app_bundle TheApp.app (in current directory)
dsym TheApp.app.dSYM (in current directory)
现在去调试吧!
我希望这能帮助你完成你自己的应用程序的调试之旅!