最近落格输入法遇到了几个比较难以复现的问题——关键是它不会导致崩溃。这就让崩溃统计功能根本无效,具体表现为在某些情况下输入法会突然卡住几秒,叫人十分恼火。后来我想到,macOS自带活动管理器中,有个“采样”功能,可以看到对应进程当前的执行(调用)状态,那我是不是可以用它来分析错误原因呢?
在和用户沟通后,我得到了一个类似这样的采样报告:
1 2 3 4 5 6 7 8 9 10 |
2713 -[IMKSignPostInputController deactivateServer:] (in InputMethodKit) + 326 [0x7fff471f91eb] + 2713 ??? (in LogInputMac2) load address 0x102d32000 + 0x22fb1 [0x102d54fb1] + 2713 ??? (in LogInputMac2) load address 0x102d32000 + 0x22aa3 [0x102d54aa3] + 2713 ??? (in LogInputMac2) load address 0x102d32000 + 0x3b586 [0x102d6d586] + 1774 ??? (in LogInputMac2) load address 0x102d32000 + 0x64a7c [0x102d96a7c] + ! 1774 -[IMKTracingTextInput stringFromRange:actualRange:] (in InputMethodKit) + 197 [0x7fff4714b4e1] + ! 1774 os_activity_apply_f (in libsystem_trace.dylib) + 66 [0x7fff20333811] + ! 1774 __51-[IMKTracingTextInput stringFromRange:actualRange:]_block_invoke (in InputMethodKit) + 94 [0x7fff4714b58a] + ! 1774 __51-[IMKTracingTextInput stringFromRange:actualRange:]_block_invoke_2 (in InputMethodKit) + 70 [0x7fff4714b5f5] + ! 1774 -[IMKLoggingTextInput stringFromRange:actualRange:] (in InputMethodKit) + 192 [0x7fff471d8b76] |
在执行完我程序的代码后,很快就到了卡住的地方,显然,应该是我调用的某个 API 触发了系统的 Bug 之类的,所以我只要能找到具体是哪里调用的,调用了什么,应该就很容易定位问题了,具体到这个例子中,就是 1774 ??? (in LogInputMac2) 代表了什么。
于是看着后边的地址,我猜它应该和崩溃记录差不多,也是需要 dSym 来解析的,只是这一次没有现成的功能来用了,我们需要手动计算这个地址(当然只是手动调用比较底层的工具罢了,真手算还是不必了)
atos
atos 命令是 Xcode 自带的,我们使用的各种自动解析崩溃日志的工具,也都是在它之上进行构建,所以第一步,我们先找到那个对应的 dSym 文件(希望你还找得到)。
得到文件后,我们使用命令来解析它的 uuid,要和采样数据中的结果一致:
1 2 |
Binary Images: 0x102d32000 - 0x102e79fff +com.logcg.inputmethod.LogInputMac2 (2.4.3 Beta - 2340) <21095D7E-0244-3994-9322-6F4A99BCD198> /Library/Input Methods/LogInputMac2.app/Contents/MacOS/LogInputMac2 |
在采样数据下方,就是二进制映像,这里显示了你程序的版本以及其 uuid。找到对应的 dSym 后,我们用命令 xcrun dwarfdump --uuid LogInputMac2.app.dSYM/Contents/Resources/DWARF/LogInputMac2 来查看 dSym 中包含的架构和对应的 uuid,比如我的就是:
1 2 3 |
$xcrun dwarfdump --uuid LogInputMac2.app.dSYM/Contents/Resources/DWARF/LogInputMac2 UUID: 21095D7E-0244-3994-9322-6F4A99BCD198 (x86_64) LogInputMac2.app.dSYM/Contents/Resources/DWARF/LogInputMac2 UUID: 77AC203D-8F6F-3486-B1AE-3F3AB539A8A3 (arm64) LogInputMac2.app.dSYM/Contents/Resources/DWARF/LogInputMac2 |
你看,和采样中对应的就是 x86_64 的那个。
然后我们进入 atos 的交互模式,首先找到你程序的虚拟地址开始点,比如这一行中 2713 ??? (in LogInputMac2) load address 0x102d32000 + 0x22aa3 [0x102d54aa3] 我的起始点就是 0x102d32000 你会发现其他行中,这个起始点都是相同的,只有后边的地址不同,拿到这个起始点后,我们执行命令:
1 |
atos -arch x86_64 -o "LogInputMac2.app.dSYM/Contents/Resources/DWARF/LogInputMac2" -l 0x102d32000 |
这时终端进入了提示符状态,里边什么都不显示,然后我们就可以输入实际地址进行换算了,还是2713这一行,末尾方括号中的地址就是程序运行的实际地址,我们输入它,atos 就会根据你的 dSym 文件把对应的代码显示出来了。
因为是交互模式,你还可以继续输入其他地址,不需要重复执行命令:
1 2 3 4 5 6 7 8 9 10 11 |
$atos -arch x86_64 -o "LogInputMac2.app.dSYM/Contents/Resources/DWARF/LogInputMac2" -l 0x102d32000 0x102d54fb1 @objc LogInputController.activateServer(_:) (in LogInputMac2) + 97 0x102d54aa3 LogInputController.deactivateServer(_:) (in LogInputMac2) (<compiler-generated>:0) 0x102d6d586 TouchBarCandidateController.displaySmartHint() (in LogInputMac2) (TouchBarCandidateController.swift:48) 0x102d96a7c IMKTextInput.stringBeforeInput.getter (in LogInputMac2) (EnhancedTextInput.swift:119) 0x102d96a47 IMKTextInput.stringBeforeInput.getter (in LogInputMac2) (EnhancedTextInput.swift:116) |
参考文献
本文由 落格博客 原创撰写:落格博客 » macOS 使用 atos 命令解析任意崩溃记录和采样数据
转载请保留出处和原文链接:https://www.logcg.com/archives/3475.html