atos和dwarfdump不会象征我的地址

Mac*_*n13 11 dwarf symbolicate ipad ios airbrake

我通过AirBrake.io收到了一份没有象征意义的崩溃报告.由于崩溃报告与Apple崩溃日志的格式不完全相同,我不能像往常一样将它放在XCode上,因此我从我的XCode归档中获取完全相同的版本,试图在命令行上对其进行符号化.结果如下:

$ atos -o kidsapp.app/kidsapp 0x0002fc4c
0x0002fc4c (in kidsapp)
Run Code Online (Sandbox Code Playgroud)

我绝对相信我使用的是与崩溃报告相同的版本.所以我也尝试过使用dwarfdump:

$ dwarfdump --lookup 0x0002fc4c --arch armv7 kidsapp.app.dSYM
----------------------------------------------------------------------
 File: kidsapp.app.dSYM/Contents/Resources/DWARF/kidsapp (armv7)
----------------------------------------------------------------------
Looking up address: 0x000000000002fc4c in .debug_info... not found.
Looking up address: 0x000000000002fc4c in .debug_frame... not found.
Run Code Online (Sandbox Code Playgroud)

也没有结果.除了使用错误的dSYM文件还有什么别的我可以做错吗?我知道这是正确的,因为这是AirBrake崩溃报告中提到的版本,它在我的XCode档案中.

欢迎任何想法/提示!

NSP*_*mer 24

我使用以下算法来弄清楚:

slide+ stack address- load address=symbol address

stack address 是我从堆栈转储崩溃报告中获得的十六进制值(不是.crash文件,只是堆栈转储).

slide是运行时LC_SEGMENT cmd的vmaddr otool -arch armv7 -l APP_BINARY_PATH.我的通常最终是0x00001000.

load address是一件复杂的事情.它实际上是主线程的最底层堆栈地址与运行时包含符号的二进制部分的FIRST地址之间的差异dwarfdump --arch armv7 --all DSYM_BINARY_PATH.这只是main函数的符号地址.因此,如果你最底部的崩溃地址是0x8000而你的主函数的符号地址是0x2000那么你的load address是0x6000.

现在有了所有这些部分,我可以计算符号地址并将其放入atos或dwarfdump : dwarfdump --lookup SYM_ADDR --arch armv7 APP_BINARY_PATH.

转储示例(你可以看到它load address是0x00003af4):

----------------------------------------------------------------------

文件:/Users/user/Desktop/MyApp.xcarchive/dSYMs/MyApp.app.dSYM/Contents/Resources/DWARF/MyApp(armv7)

----------------------------------------------------------------------

0x00000024:[0x00003af4 - 0x00003b4e)main

0x00000098:[0x00003b50 - 0x00003d8c) - [MyAppDelegate application:didFinishLaunchingWithOptions:]

...转储的其余部分

最困难的部分是意识到我所包含的2个静态库中的一个在链接到我的应用程序的二进制文件之前已经剥离了它们的符号!这留下了巨大的符号地址空白,所以我只得到了我在dSYM中需要的符号的三分之二.

一定要在你的静态库的Xcode项目设置为NO,这样当你反对它链接,你可以在符号拉到你的应用程序的二进制文件(以后可以剥离)以下标志:COPY_PHASE_STRIP,DEAD_CODE_STRIPPING,和STRIP_INSTALLED_PRODUCT.

现在您可能会问,"如果堆栈转储不包含main函数,我该怎么办,因为它不在主线程上,因此我无法获取main函数的堆栈地址?".对此,我会回答:"我没有一点c'的线索!".只需交叉手指,希望您可以获得包含符号地址的堆栈跟踪,或使用模拟Apple崩溃日志的崩溃报告系统,如PLCrashReporter.

[编辑2013年5月26日] -

我注意到它load address确实是mach-o二进制文件的地址.虽然我上面描述的内容经常可以工作 - 但实际上并不正确.这可以通过CRASH REPORT获得,但是这个答案的重点是在没有崩溃报告时提供崩溃的符号.我最好的方法是找出load address想要表示的时间,这是通过确保我记录下来load addressstack addresses.

我个人创建了一个用于记录崩溃(不是崩溃报告)的系统,并将它们发送到S3存储桶,我可以在以后检索它们以进行调试.当我启动我的应用程序时slide,如果我的应用程序崩溃并且我发送了一个,那么我将缓存,使用load addressmain function address使用stack addresses.

注意:dyld函数使用 #include <mach-o/dyld.h>

slide =返回的地址 _dyld_get_image_vmaddr_slide(0)

load address =返回的地址 _dyld_get_image_header(0)

main function address= [NSThread callStackReturnAddresses]在主线程上调用时的最后一个地址

在紧急时间我敢肯定,登录[NSThread callStackReturnAddresses][NSThread callStackSymbols]以及可通过具有这种方法来检索架构:

- (NSString*) arch
{
    NSString* arch =
#ifdef _ARM_ARCH_7
        @"armv7";
#elif defined (_ARM_ARCH_6)
        @"armv6";
#else
        nil;
#endif

    return arch;
}
Run Code Online (Sandbox Code Playgroud)

我还不知道如何区分armv7和armv7s.

所以这可能有助于将来.我计划将我学到的所有东西都变成一个简单的崩溃工具 - 比natos工具(可能是natos v2)更好.

我已经更新了natos以支持load address手动提供:https://github.com/NSProgrammer/natos

  • 我已经创建了一个命令行工具来完成所有艰苦的工作.只需要1)xcarchive路径,2)主函数的堆栈地址符号,3)所需符号的堆栈地址,4)感兴趣的体系结构.它位于github:https://github.com/nob1984/natos (3认同)

Ker*_*rni 9

首先检查dSYM是否真的是该应用程序的正确版本:

dwarfdump --uuid kidsapp.app/kidsapp
dwarfdump --uuid kidsapp.app.dSYM
Run Code Online (Sandbox Code Playgroud)

两者都应该返回相同的结果.

接下来检查dSYM是否包含任何有效内容

dwarfdump --all kidsapp.app.dSYM
Run Code Online (Sandbox Code Playgroud)

这至少应该提供一些信息not found.

我猜dSYM已经腐败了.通常,您可能希望使用崩溃报告器,该报告器为您提供包含所有线程和最后异常回溯信息的完整崩溃报告.我建议使用基于PLCrashReporter的东西,例如QuincyKit(Mac上的开源SDK +服务器+符号)或HockeyApp(开源SDK +付费服务+服务器端符号)(注意:我是开发人员之一!)