我正在尝试获得像Xcode listout这样的反向跟踪符号
*** First throw call stack:
(
0 CoreFoundation 0x018865e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x016098b6 objc_exception_throw + 44
2 CoreFoundation 0x01923903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x0187690b ___forwarding___ + 1019
4 CoreFoundation 0x018764ee _CF_forwarding_prep_0 + 14
5 Foundation 0x0124036c __NSFireDelayedPerform + 372
6 CoreFoundation 0x01844c46 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
7 CoreFoundation 0x0184462d __CFRunLoopDoTimer + 1181
8 CoreFoundation 0x0182c698 __CFRunLoopRun + 1816
9 CoreFoundation 0x0182bb33 CFRunLoopRunSpecific + 467
10 CoreFoundation 0x0182b94b CFRunLoopRunInMode + 123
11 GraphicsServices 0x02c249d7 GSEventRunModal + 192
12 GraphicsServices 0x02c247fe GSEventRun + 104
13 UIKit 0x0037c94b UIApplicationMain + 1225
14 CrashHandler 0x000088ad main + 141
15 libdyld.dylib 0x06244725 start + 0
16 ??? 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
我试图从NSException提取符号,如下面的代码。只有更少的信息可用。
-(void)handleException:(NSException*)exception
{
[exception callStackSymbols]//I've written this into file.
}
我得到了如下的输出
*** First throw call stack: (
0 CoreFoundation 0x326bd2bb <redacted> + 186
1 libobjc.A.dylib 0x3a33b97f objc_exception_throw + 30
2 CoreFoundation 0x326c0e07 <redacted> + 170
3 CoreFoundation 0x326bf531 <redacted> + 392
4 CoreFoundation 0x32616f68 _CF_forwarding_prep_0 + 24
5 Foundation 0x32fcb277 <redacted> + 450
6 CoreFoundation 0x326925df <redacted> + 14
7 CoreFoundation 0x32692291 <redacted> + 272
8 CoreFoundation 0x32690f01 <redacted> + 1232
9 CoreFoundation 0x32603ebd CFRunLoopRunSpecific + 356
10 CoreFoundation 0x32603d49 CFRunLoopRunInMode + 104
11 GraphicsServices 0x361b62eb GSEventRunModal + 74
12 UIKit 0x34519301 UIApplicationMain + 1120
13 CrashHandler 0x0007f421 main + 116
14 libdyld.dylib 0x3a772b20 <redacted> + 0
)
如何解码<redacted>
符号?
我参考了SO post1, SO post2,但它需要dSYM
文件,我们必须像试飞一样手动解码。没有dSYM文件,如何做到这一点?
符码化是将内存地址转换为包含以下全部或部分元素的符号的过程:
-
class name
-
method name
-
file name
-
line number
当在设备上使用应用程序符号作为应用程序二进制的一部分进行符号时,只能检索到class name
和method name
。不能用这种方法得到file name
和line number
。
当使用应用程序dSYM进行符号化时,只要在构建应用程序时可用所有信息,就可以获得所有数据。例如,当使用第三方静态库时,这些调用可能会丢失文件名和行号。
<redacted>
符号只有在设备上表示系统框架地址时才能显示系统调用。class name
和/或method name
不显示的原因是iOS内存优化。对此的解释可以在这里找到:https://devforums.apple.com/thread/171264为了表示这些地址,你需要有用于在计算机上创建堆栈跟踪的iOS版本和CPU体系结构的iOS符号,该计算机用于表示报告。
可以将这些符号作为Xcode的一部分或通过将特定iOS版本和CPU架构的设备连接到Xcode,然后将获取这些符号。请注意,例如,对于没有更新SDK的iOS错误修复版本,获取符号的唯一方法是使用设备。
计算机上的符号化可以使用Xcode管理器或手动使用symbolciatecrash.pl
脚本(Xcode的一部分)在终端手动完成。
对于Xcode或脚本的符号工作,你需要一个完整的崩溃报告,其中包含比你发布的堆栈跟踪更多的信息。
要使用atos
手动表示报告的帧地址,您还需要帧引用的每个二进制文件的加载地址,例如来自Foundation
, CoreFoundation
, UIKit
。所示的堆栈跟踪不提供此信息。这里有多个帖子在StackOverflow如何手动使用atos
。
如果没有dSYM
认证文件,就无法表示跟踪。您可以尝试使用不剥离调试符号的选项来构建代码,但我不确定。
也实现崩溃处理程序是一个非常微妙的任务,我会离开专业的;)但你可以试一试,也许还能学到新东西。