Unity Native崩溃堆栈解析

Unity Native崩溃堆栈解析


前言

最近在工作中查询线上崩溃的时候发现Bugly上有些崩溃日志无法还原,即使上传了对应的符号表也无济于事。为了还原崩溃日志,定位崩溃原因,学习了一下在此记录。


崩溃日志

接入Bugly之后,手机上崩溃前的崩溃日志会被上传到Bugly上。开发人员可以在Bugly的“崩溃分析”页面中查看崩溃日志。

有些崩溃日志Bugly无法检测到能够还原的部分,也就是说即使上传了符号表,Bugly没法识别日志,也就无法自动通过上传的符号表还原日志。

比如下图崩溃:

这个时候,开发人员想定位崩溃原因,就需要手动还原崩溃信息。需要关注的内容,就是上图backtrace部分的内容。(这里只是Bugly上一种backtrace的表现形式,还有很多种表现形式,如#01 pc 000402b1 /system/lib/libc.so (pthread_kill+32) [armeabi-v7a]等)


Unity Native堆栈解析

所需文件

如果我们想要在本地手动解析/还原崩溃信息,那么就需要两个文件:

1、libunity.sym.so,即Unity的libunity库符号表。

2、addr2line,即Native堆栈解析工具。


libunity.sym.so

Unity在5.3之后就提供了libunity和libmain的符号表。

符号表的位置就在Unity路径下,根据不同的ARM架构有不同的libunity符号表。

Mac上的路径示例如下:

/…/Unity/PlaybackEngines/AndroidPlayer/Variations/il2cpp/Release/Symbols/armeabi-v7a/libunity.sym.so

/…/Unity/PlaybackEngines/AndroidPlayer/Variations/il2cpp/Release/Symbols/arm64-v8a/libunity.sym.so


注意:生成apk的Unity版本和libunity符号表的Unity版本必须一致,否则解析的内容会不正确。


addr2line

NDK中自带addr2line工具,可以通过读取符号表来解析崩溃堆栈。里面包括各种CPU架构版本,使用时需要选择对应的版本。一般来说,Android使用arm-linux-androideabi-4.9即可。

Mac上的路径示例如下:

/…/android-ndk-r16b/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line

/…/android-ndk-r16b/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-addr2line


注意:最好使用生成apk的Unity所使用的NDK中的addr2line工具。


使用方法

addr2line所支持的参数:

addr2line [-a| --addresses ] [-b bfdname | --target=bfdname] [-C | --demangle[=style]] [-e filename | --exe=filename] [-f | --function] [-s | --basename] [-i | --inlines] [-p | --pretty-print] [-j | --section=name] [-H | --help] [-V | --version] [addr addr ...]
-a --addresses:在函数名、文件和行号信息之前,显示地址,以十六进制形式。
-b --target=<bfdname>:指定目标文件的格式为bfdname。
-e --exe=<executable>:指定需要转换地址的可执行文件名。
-i --inlines : 如果需要转换的地址是一个内联函数,则输出的信息包括其最近范围内的一个非内联函数的信息。
-j --section=<name>:给出的地址代表指定section的偏移,而非绝对地址。
-p --pretty-print:使得该函数的输出信息更加人性化:每一个地址的信息占一行。
-s --basenames:仅仅显示每个文件名的基址(即不显示文件的具体路径,只显示文件名)。
-f --functions:在显示文件名、行号输出信息的同时显示函数名信息。
-C --demangle[=style]:将低级别的符号名解码为用户级别的名字。
-h --help:输出帮助信息。
-v --version:输出版本号。

使用范例:

假设崩溃backtrace的堆栈的pc寄存器内容按顺序如下:

001897d0 0019cfb0 004d1c80 00654114 00652128 0067a464 0067b5e0 0067b790 005c6964 0026868c 005c897c 005c87d0 005c875c 00603c60

在终端中执行如下命令:

/Users/apple/Downloads/android-ndk-r16b/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line -f -C -e /Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/il2cpp/Release/Symbols/armeabi-v7a/libunity.sym.so 001897d0 0019cfb0 004d1c80 00654114 00652128 0067a464 0067b5e0 0067b790 005c6964 0026868c 005c897c 005c87d0 005c875c 00603c60

可以获得结果:

core::StringStorageDefault<char>::resize(unsigned int, bool)
??:?
void SafeBinaryRead::TransferSTLStyleArray<core::basic_string<char, core::StringStorageDefault<char> > >(core::basic_string<char, core::StringStorageDefault<char> >&, TransferMetaFlags)
??:?
void NamedObject::Transfer<SafeBinaryRead>(SafeBinaryRead&)
??:?
void MonoScript::Transfer<SafeBinaryRead>(SafeBinaryRead&)
??:?
MonoScript::VirtualRedirectTransfer(SafeBinaryRead&)
??:?
SerializedFile::ReadObject(long long, ObjectCreationMode, bool, TypeTree const**, bool*, Object&)
??:?
PersistentManager::ReadAndActivateObjectThreaded(int, SerializedObjectIdentifier const&, SerializedFile*, bool, bool, PersistentManager::LockFlags)
??:?
PersistentManager::LoadObjectsThreaded(int const*, int, LoadProgress&, bool, PersistentManager::LockFlags)
??:?
LoadOperation::Perform()
??:?
AssetBundleLoadAssetOperation::Perform()
??:?
PreloadManager::ProcessSingleOperation()
??:?
PreloadManager::Run()
??:?
PreloadManager::Run(void*)
??:?
Thread::RunThreadWrapper(void*)
??:?

Native崩溃堆栈信息就这样还原了。


后记

希望后人少踩坑,没啥别的了,加油就完事了!


参考

https://support.unity.com/hc/zh-cn/articles/115000292166-%E4%BD%BFAndroid%E5%A5%94%E6%BA%83%E6%97%A5%E5%BF%97%E7%AC%A6%E5%8F%B7%E5%8C%96

https://blog.csdn.net/linxinfa/article/details/107681049

https://blog.csdn.net/Sparrowfc/article/details/78384248

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Unity中导入资源是指将外部资源文件(如图像、音频、视频等)引入到Unity项目中的过程。以下是导入资源的详细解析: 第一步是选择要导入的资源文件,并将其复制到Unity项目的Assets文件夹中。这些资源文件可以来自于本地计算机上的文件夹、其他Unity项目中的资源文件,或者从互联网上下载的资源。 第二步是打开Unity编辑器,在项目窗口中选择Assets文件夹,并点击右键选择“Import New Asset”或者直接拖拽资源文件到Unity编辑器中。如果资源文件是图片或者音频文件,Unity会自动为其创建一个对应的材质或音频剪辑。 第三步是在导入资源的过程中,Unity会根据资源类型对其进行解析和处理。对于图片资源,Unity会根据其格式(如PNG、JPEG等)将其转换为适用于游戏引擎的纹理格式,如贴图。对于音频资源,Unity会将其转换为可被游戏引擎播放的音频剪辑。 第四步是在Unity编辑器中对导入的资源进行设置和调整。例如,对于导入的图片资源,可以设置其尺寸、是否启用alpha通道、压缩质量等。对于音频资源,可以调整音频的音量、循环设置等。 最后,导入完成后,可以在Unity项目中的其他场景、脚本、动画等中使用这些导入的资源。可以通过引用资源的名称或者路径,在代码中获取和操作这些资源。 通过以上步骤,Unity可以方便地将外部资源导入到项目中,并在游戏开发过程中使用、修改和管理这些资源,从而实现游戏的各种功能和效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值