gpt4 book ai didi

ios - atos 和 dwarfdump 不会代表我的地址

转载 作者:技术小花猫 更新时间:2023-10-29 10:41:34 32 4
gpt4 key购买 nike

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

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

我绝对确定我使用的是与崩溃报告来源相同的版本。所以我也尝试了 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.

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

欢迎任何想法/提示!

最佳答案

我使用了以下算法来计算:

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是复杂的一 block 。它实际上是主线程的最底部堆栈地址与运行时我的二进制文件中包含符号的部分的第一个地址之间的差异 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):

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

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

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

0x00000024: [0x00003af4 - 0x00003b4e) main

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

... the rest of the dump

最困难的部分是意识到我包含的 2 个静态库之一在链接到我的应用程序的二进制文件之前删除了它们的符号!这留下了巨大的符号地址缺口,所以我最终只得到了我的 dSYM 中所需符号的三分之二。

确保在您的静态库 xcode 项目中将以下标志设置为 NO,这样当您链接到它时,您可以将符号拉入您的应用程序的二进制文件(稍后可以删除):COPY_PHASE_STRIP , DEAD_CODE_STRIPPING , 和 STRIP_INSTALLED_PRODUCT .

现在你可能会问,“如果堆栈转储不包括 main 函数,我该怎么办,因为它不在主线程上,所以我无法获取 main 函数的堆栈地址?”。对此我会回答,“我他妈的一点线索都没有!”。祈祷你能得到包含符号地址的堆栈跟踪,或者使用模仿 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;
}

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

所以这在将来可能会有所帮助。我计划利用我所学的一切并将其变成一个简单的崩溃工具——比 natos 工具(可能是 natos v2)更好。

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

关于ios - atos 和 dwarfdump 不会代表我的地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10242766/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com