这个案例是从tombstone入手,进行了crash日志分析,tombstone一般在开头,都会阐明崩溃的大致问题,一般来说空指针类型的崩溃是最容易通过ida、addr2line、objdump找到相关代码的。
崩溃现场
tombstone墓碑文件日志提示崩溃的地址0x835be0
yaml 复制代码 pid: 3382, tid: 3821, name: dTi >>> com.xx.xx.xx <<< signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x835be0 rax 00000000000000e1 rbx 00007fff6ef15d78 rcx 00000000000003d0 rdx 00007fff6ef15d80 r8 00007fff6ef15d80 r9 00007fff50295a68 r10 00007fff6f16c940 r11 0000000000000055 r12 000000000000004b r13 0000000000000e10 r14 0000000000835be0 r15 0000000000836000 rdi 0000000000835be0 rsi 00000000052a85ec rbp 0000000000835000 rsp 00007fff502958d0 rip 00007fff6eb8bb2d
iad加载so文件,然后打开hex dump
视图
在hex dump视图下,我们跳转到0x835be0
再按下快捷键F5
此时就会生成该地址对应的C语言伪代码,提示崩溃的代码是在第11行
而add2line给出的位置是,基本正确,伪代码和源码只是写法不一样而已,逻辑都一样
这个函数对应的lua binding逻辑是
c++ 复制代码 int lua_register_cocos2dx_studio_VisibleFrame(lua_State* tolua_S) { tolua_usertype(tolua_S,"ccs.VisibleFrame"); tolua_cclass(tolua_S,"VisibleFrame","ccs.VisibleFrame","ccs.Frame",nullptr); tolua_beginmodule(tolua_S,"VisibleFrame"); tolua_function(tolua_S,"new",lua_cocos2dx_studio_VisibleFrame_constructor); // 这个函数 tolua_function(tolua_S,"isVisible",lua_cocos2dx_studio_VisibleFrame_isVisible); tolua_function(tolua_S,"setVisible",lua_cocos2dx_studio_VisibleFrame_setVisible); tolua_function(tolua_S,"create", lua_cocos2dx_studio_VisibleFrame_create); tolua_endmodule(tolua_S); std::string typeName = typeid(cocostudio::timeline::VisibleFrame).name(); g_luaType[typeName] = "ccs.VisibleFrame"; g_typeCast["VisibleFrame"] = "ccs.VisibleFrame"; return 1; }
对应的lua代码就是
复制代码
ccs.VisibleFrame.setVisible
rdi和地址一样,那么就是第一个参数的问题
参数
如果能够得到崩溃时的堆栈参数信息,对排查这个问题也非常有帮助。
当参数少于7个时, 参数从左到右
放入寄存器
:
rdi, rsi, rdx, rcx, r8, r9。
当参数为7个以上时, 前 6 个与前面一样, 但后面的依次从右向左
放入栈
中,即和32位汇编一样。
参数个数大于 7 个的时候
H(a, b, c, d, e, f, g, h);
- a->%rdi
- b->%rsi
- c->%rdx
- d->%rcx
- e->%r8
- f->%r9
- h->8(%esp)
- g->(%esp)
- call H