Unity排查定位libunity.so崩溃问题(自动+手动)

线上崩溃统计日志中经常出现一个空指针崩溃问题,关键词为 signal 11(SIGSEGV),code 1(SEGV_MAPERR),fault addr 00000000,调用链指向 libunity.so。
问题
虽然崩溃时调用链指向了 libunity.so,但具体执行了啥,调用的是哪个方法,根本无从下手,例如下面的日志,你根本不知道 libunity.00966c68 是啥:
E AndroidRuntime: at libunity.00966c68(Native Method)
E AndroidRuntime: at libunity.00965318(Native Method)
E AndroidRuntime: at libunity.005b7d18(Native Method)
E AndroidRuntime: at libunity.005b7d50(Native Method)
E AndroidRuntime: at libunity.005b7f28(Native Method)
E AndroidRuntime: at libunity.006a43d0(Native Method)
E AndroidRuntime: at libunity.006b2a70(Native Method)
因此需要找个方法将 libunity.so 调用报错转换成具体的方法名。本文以我遇到的报错为例,简要记录下 Debug 方法。
方法1:上传 so 库符号表(仅针对未混淆的 App,自动翻译)
此种方法仅作用于 Bugly 这种支持符号表上传的平台,且要求你的程序是未做过安卓代码混淆的。
Unity libunity.so 的符号表在如下目录可以找到:
Debug版:
Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Development\Symbols
发行版:
Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Symbols
根据平台不同,可找到不同的文件夹,里面的 libunity.sym.so 即为 so 库符号表。
使用 Bugly 官方工具将 libunity.sym.so 符号表传至线上统计平台,之后平台自动将 crash report 中的 so 库报错替换为调用链符号(即方法名)。
java -jar buglyqq-upload-symbol.jar
-appid [AppId]
-appkey [Appkey]
-bundleid com.test.azimiao
-version 1.0.0
-platform Android
-inputSymbol libunity.sym.so
成功上传后,bugly 后台应该有 so 符号表:
我传了,发现不行,后来问过安卓同学才知道,Unity 导出项目给他们后,他们又加了一层代码混淆。
我猜测代码混淆导致 crash 日志的字符发生变化,本应该是 libunity.so + 调用栈的报错变成了 libunity.调用栈,因此无法被 bugly 等平台自动识别。
方法2.根据符号表手动翻译
既然上传符号表行不通,则选择手动翻译。
当然这里的手动翻译不是手动去分析二进制,而是利用现有工具自己一行一行翻译。
首先在你的 ndk 文件夹里找到 arm-linux-androideabi-addr2line 这玩意,他是一个把调用栈内存地址转为行号的工具。
使用如下命令将调用栈内存地址转化为符号表对应内容并输出:
./arm-linux-androideabi-addr2line.exe -f -C -e libunity.sym.so 00966c68
如果得法,将会输出对应的方法名:
将上文中报错调用链日志一行行翻译,最终报错翻译如下:
VideoClipPlayback::DetectEndReached()
VideoPlaybackMgr::Update()
ExecutePlayerLoop(NativePlayerLoopSystem*)
PlayerLoop()
UnityPlayerLoop()
nativeRender(_JNIEnv*, _jobject*)
可以看出这是一个使用自带 VideoPlayer 时导致的崩溃。
这个例子中的报错究竟是啥
上文中用某个 libunity 报错日志举了个例子,那么这个报错的原因是什么呢?而空引用又代表了什么呢?
这其实是 Unity 自带 VideoPlayer 一个久远的 Bug:当 VideoPlayer 开始播放后又马上被销毁时,某些内部逻辑会直接使用已经被销毁的对象,导致该问题。
Unity 自称这个问题在 2018.4.35f1 及 2020.2 版本中被修复,具体内容见 Unity Issue Tracker #1241848。