atos和dwarfdump不会象征我的地址

我通过AirBrake.io收到了一个没有符号的崩溃报告。 由于崩溃报告的格式与Apple crashlog格式不同,因此我不能像往常一样将其放在XCode上,所以我从XCode存档中采用了完全相同的版本,试图在命令行上对其进行符号化。 结果如下:

$ atos -o kidsapp.app/kidsapp 0x0002fc4c 0x0002fc4c (in kidsapp) 

我确定我使用的是与崩溃报告相同的内部版本。 所以我也试过了侏儒转储:

 $ 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. 

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

任何想法/提示,欢迎!

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

 dwarfdump --uuid kidsapp.app/kidsapp dwarfdump --uuid kidsapp.app.dSYM 

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

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

 dwarfdump --all kidsapp.app.dSYM 

这应该至less给一些信息,而not found

我想dSYM是腐败的。 一般来说,你可能想使用一个崩溃报告器,它给你一个完整的崩溃报告,包含所有线程和最后的exception回溯信息。 我推荐使用基于PLCrashReporter的东西,例如QuincyKit(开源SDK +服务器+你的mac上的符号)或HockeyApp(开源SDK +付费服务+服务器端符号)(注:我是其中一个开发者!)

我用下面的algorithm来解决它:

slide + stack addressload address = symbol address

stack address是从我的堆栈转储崩溃报告(不是.crash文件,只是堆栈转储)获得的hex值。

在运行otool -arch armv7 -l APP_BINARY_PATH时, slide是LC_SEGMENT cmd的otool -arch armv7 -l APP_BINARY_PATH 。 通常我的结果是0x00001000。

load address是复杂的一块。 它实际上是主线程最底层的堆栈地址与运行dwarfdump --arch armv7 --all DSYM_BINARY_PATH时包含符号的二进制部分的FIRST地址之间的dwarfdump --arch armv7 --all DSYM_BINARY_PATH 。 这只是mainfunction的象征性地址。 所以如果你最底下的崩溃地址是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)主

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

剩下的转储

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

请确保在静态库xcode项目中将下列标志设置为NO,以便在链接到它时,可以将符号COPY_PHASE_STRIP应用程序的二进制文件(稍后可以剥离): COPY_PHASE_STRIPDEAD_CODE_STRIPPINGSTRIP_INSTALLED_PRODUCT

现在你可能会问:“如果堆栈转储不包含主函数,因为它不在主线程中,所以我不能获取主函数的堆栈地址,我该怎么办?”。 对此,我会回答,“我没有一个想法的线索!” 希望你能得到一个包含符号地址的堆栈跟踪,或者使用一个模拟苹果的崩溃日志的崩溃报告系统,比如PLCrashReporter。

[编辑2013年5月26日] –

它引起了我的注意, load address确实是mach-o二进制文件的地址。 虽然我上面描述的可以经常工作 – 这实际上并不正确。 这可以通过CRASH REPORT得到,但是这个答案的重点是当你没有崩溃报告时提供崩溃的符号。 当我想要表示符号时,最好的办法是确定我用stack addressesloggingload address

我亲自创build了一个logging崩溃(而不是崩溃报告)的系统,并将它们发送到S3存储桶,以便稍后可以检索它们以进行debugging。 当我开始我的应用程序,我cachingslideload 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)返回的地址_dyld_get_image_header(0)

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

在崩溃的时候我肯定会logging[NSThread callStackReturnAddresses][NSThread callStackSymbols]以及可以通过这种方法检索的体系结构:

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

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

所以这可能有助于未来。 我打算把我学到的所有东西都变成一个简单的碰撞工具 – 比natos工具(可能是natos v2)更好。

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

对于某些时间没有像Load Address这样的值的人:

 Jan 14 11:02:39 Dennins-iPhone AppName[584] <Critical>: Stack Trace: ( 0 CoreFoundation 0x2c3084b7 <redacted> + 150 1 libobjc.A.dylib 0x39abec8b objc_exception_throw + 38 2 CoreFoundation 0x2c21cc35 CFRunLoopRemoveTimer + 0 3 AppName 0x0005a7db AppName + 272347 

我创build了一个简单的bash来帮助我debugging:

 #! /bin/bash read -p "[Path] [App Name] [Stack Address] [Relative Address] " path appName runtimeAddress relativeAddress loadAddress=`echo "obase=16;ibase=10;$((runtimeAddress-relativeAddress))" | bc` atos -o $path/Payload/$appName.app/$appName -l $loadAddress $runtimeAddress -arch armv7 

它只是读取应用程序的path,应用程序名称,运行时地址和“+”信号(十进制值)后的值,然后查找加载地址的值以运行atos命令。

我觉得这个post可能会帮助你, https://stackoverflow.com/a/12559150/1773317 。 乔的提交解决了我的问题。

原因是我的.app和.dSYM文件不能被聚光灯索引,所以我的XCode不能正确地表示崩溃信息。