bugly反馈的崩溃信息
# GLThread 1244(26758)
SIGSEGV(SEGV_MAPERR)
#00 pc 0000000000aa3f58 /data/app/~~WpLbOJpUH515iuTdzLuwtA==/com.yddm.haiwai.game-WSEzvXvmgpQhb_dCQmuisg==/split_config.arm64_v8a.apk
#01 pc 0000000000aafb84 /data/app/~~WpLbOJpUH515iuTdzLuwtA==/com.yddm.haiwai.game-WSEzvXvmgpQhb_dCQmuisg==/split_config.arm64_v8a.apk
0xaa3f58addr2line结果: lj_meta_cache0xaafb84addr2line结果:rec_call_setuplj_record.c:?
信息很少,只能从这个函数下手,bugly的系统日志也看了并没有看到任何有用的信息
尝试 ida 反汇编排查问题
定位崩溃代码的源码位置
iad的0xaa3f58view如下
反汇编代码
源码lj_meta.c
/* Negative caching of a few fast metamethods. See the lj_meta_fast() macro. */
cTValue *lj_meta_cache(GCtab *mt, MMS mm, GCstr *name)
{
cTValue *mo = lj_tab_getstr(mt, name);
lj_assertX(mm <= MM_FAST, "bad metamethod %d", mm);
if (!mo || tvisnil(mo)) { /* No metamethod? */
// 根据反汇编的源码推断,大概率是运行到这里的代码出现了崩溃
// 请注意这个位置,在后续的排查过程中,我们会对这个位置下个钩子
mt->nomm |= (uint8_t)(1u<<mm); /* Set negative cache flag. */
return NULL;
}
return mo;
}
调用lj_meta_cache的地方
从ida的引用结果来看,我们并没有发现rec_call_setup,所以很可能是bugly给出的堆栈不够精细,rec_call_setup很可能间接的调用。
不过严谨起见,我们还是从源码验证下ida给出的引用。
这里因为lj_meta_cache的调用被宏lj_meta_fastg、lj_meta_fast替代
#define lj_meta_fastg(g, mt, mm) \
((mt) == NULL ? NULL : ((mt)->nomm & (1u<<(mm))) ? NULL : \
lj_meta_cache(mt, mm, mmname_str(g, mm)))
#define lj_meta_fast(L, mt, mm) lj_meta_fastg(G(L), mt, mm)
所以需要搜下源码里面调用 lj_meta_fastg、lj_meta_fast的地方
-
lj_gc_separateudata
-
gc_finalize
-
lj_cf_ffi_new:注意这个ffi
-
lj_meta_tget
-
lj_meta_tset
-
lj_meta_equal
-
propagatemark
和源码全部对上了,太强了,特别是这个propagatemark的引用
可能的猜测
我看到都是和gc有关的函数,之前对lua gc并不是非常的熟悉,甚至都不知道lua还有gc。
尝试搜索这些函数,google给出了一个可能的原因,有反馈是死循环、或者超大循环导致的崩溃,我也尝试了编写对应的测试例,这种只会导致ANR(Application Not responding),也就是应用程序未响应,最终会被系统主动kill掉,崩溃日志给出的sign是abort,和我要排查的并不是一回事。
下一步排查思路
至此,我还是不能确定这个崩溃到底是怎么回事,即使知道了相关的调用关系,但是对于这样一个非常基础的函数,如果我们无法稳定复现bug,我们还是没有办法去修复它。
下一步我会转向从luajit入手排查这个bug。