bugly崩溃排查2:luajit编译调试

简介: bugly崩溃排查2:luajit编译调试

luajit是什么

简单说,是lua语言的另一个实现版本,唯一区别的是,加入了jit功能。

JIT是just in time的缩写,也就是即时编译。

编译luajit

前置说明

luac文件是加密后的代码,并不是luac的代码才会在luajit模式下运行,加密和luajit是2个任何不相关的东西,不要混淆,这是一个理解的误区。

如果使用了luajit的库,那么lua代码才会在luajit模式下运行,因为luajit编译出来的是lua51.dll,和lua官方编译出来的文件名是一致的。

代码是在luajit的情况下崩溃的,所以必须让项目的lua代码运行在luajit模式下,为了方便测试,我选择了使用win32进行编译测试。

win32编译

luajit的win32编译非常简单,作者已经帮我们写好了bat编译脚本,切换到Visual Studio Command Prompt


image.png



输入msvcbuild.bat很顺利就在当前目录下生成了lua51.lib

msvcbuild.bat的解读

不使用msvcbuid.bat,自己搭建luajit的vs项目,这篇文章可以参考,编译脚本我们还是需要好好理解下,有助于我们了解更多的细节。

  1. 先编译了minilua.c,链接生成了minilua.exe


cl /nologo /c /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE 
    /D_CRT_STDIO_INLINE=__declspec(dllexport)__inline 
    host\minilua.c
link /nologo /out:minilua.exe minilua.obj
  1. 生成src/host/buildvm_arch.h,host/.gitignore里面忽略了这个文件,也印证了这个文件是需要动态生成的
  2. 复制代码
minilua ..\dynasm\dynasm.lua -LN -D WIN -D JIT -D FFI -o host\buildvm_arch.h vm_x86.dasc

image.png

  1. 编译buildVM相关的源码,生成buildVM.exe,这里用到了上一步生成的buildvm_arch.h文件,不过对于cmake来说,它只关心c文件,不会影响cmake的编写


cl /nologo /c /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_STDIO_INLINE=__declspec(dllexport)__inline /arch:SSE2 /I "." /I ..\dynasm host\buildvm*.c
link /nologo /out:buildvm.exe buildvm*.obj
  1. 使用buldVM.exe,生成了一些中间文件有obj.h.lua,也就是-o参数后边的文件
buildvm -m peobj   -o lj_vm.obj
buildvm -m bcdef   -o lj_bcdef.h    lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c
buildvm -m ffdef   -o lj_ffdef.h    lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c
buildvm -m libdef  -o lj_libdef.h   lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c
buildvm -m recdef  -o lj_recdef.h   lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c
buildvm -m vmdef   -o jit\vmdef.lua lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c
buildvm -m folddef -o lj_folddef.h  lj_opt_fold.c
  1. 编译lj_\*.clib_\*.c,链接生成lua51.dll,最关键的一步之前的所有准备都是为这一步准备的
cl  /nologo /c /O2 /W3 
    /D_CRT_SECURE_NO_DEPRECATE 
    /D_CRT_STDIO_INLINE=__declspec(dllexport)__inline 
    /arch:SSE2 /MD /DLUA_BUILD_AS_DLL 
    lj_*.c 
    lib_*.c
link /nologo /release /DLL /out:lua51.dll lj_*.obj lib_*.obj
1. 编译luajit.c,链接生成luajit.exe
2. bash
3. 复制代码
cl /nologo /c /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_STDIO_INLINE=__declspec(dllexport)__inline /arch:SSE2 luajit.c
link /nologo /release /out:luajit.exe luajit.obj lua51.lib
  1. 最后就是一些清理工作了,至此生成的文件为lua51.lib lua51.dll luajit.exe

编译luajit可能遇到的报错

手动搭建vs项目编译luajit时,你一定会遇到这个问题:


2>lib_jit.obj : error LNK2019: 无法解析的外部符号 _lj_vm_cpuid,函数 _jit_cpudetect 中引用了该符号
2>lib_math.obj : error LNK2019: 无法解析的外部符号 _lj_vm_floor,函数 _random_seed 中引用了该符号
2>lj_vmmath.obj : error LNK2001: 无法解析的外部符号 _lj_vm_floor

lj_vm_xx好多函数都是在lj_vm.h中定义的,发现的确是没有lj_vm_cpuid的实现,luajit快的一个原因就是lj_vm_xx之类的函数都是用反汇编实现的,这也导致你就没有办法通过vs进行完整的编译luajit,只能通过官方提供的msvcbuild.bat进行编译。

调试luajit的解决办法

通过msvcbuild.bat编译出来debug版本,然后将lua51.dlllua51.liblua51.pdb(这个非常重要,能够调试跳转到源码全部靠他)文件提供给exe使用,最后是勉强跑起来了

命令参数debug无法通过cmake设置,只能自己手动设置了

image.png



现在也能跳转到lua_cpcall了,但是像lj_vm_cpcall这个就无法跳转了,只能从堆栈中查看反汇编看到的结果:


image.png

image.png


不过经过这番折腾,勉强可以跑起来了luajit,并且在对应的源码位置打断点,是可以进行调试的

尝试触发lj_meta_chach

image.png

简单测试了下,目前发现调用该函数是在lua_close的时候,游戏关闭或者被强行退出,也会有可能触发该函数,但是崩溃就有点无法理解了

也有可能是lua gc触发的,也有可能是我的lua脚本太简单,看来还是需要放到项目中进行验证。

至此,我们已经大致了解编译调试luajit的办法了,下一步就是放到cocos2dx中实际跑起来。



目录
相关文章
|
6月前
|
编解码 Ubuntu
记录一次Gstreamer运行报错排查
记录一次Gstreamer运行报错排查
|
移动开发 NoSQL 网络协议
掌握GDB调试工具,轻松排除bug(下)
掌握GDB调试工具,轻松排除bug
|
C++ Windows
使用 windbg gflags dumpbin 排查应用程序启动错误
使用 windbg gflags dumpbin 排查应用程序启动错误
|
3月前
|
缓存 Java
Electron V8排查问题之避免V8FatalErrorCallback崩溃问题如何解决
Electron V8排查问题之避免V8FatalErrorCallback崩溃问题如何解决
59 0
|
5月前
|
运维 NoSQL Ubuntu
深入理解Linux中的"crash"命令:内核崩溃的调试利器
`crash`是Linux内核崩溃调试工具,用于分析内核崩溃转储文件,提供GDB-like的交互式CLI。通过加载`vmcore`文件和内核映像,管理员可以查看系统状态、调用栈、内存布局等。安装`crash`可使用包管理器,如`apt-get`或`yum/dnf`。尽管有学习曲线且依赖转储文件,但`crash`在系统故障排查中极其重要。
|
6月前
|
Android开发
|
缓存 Android开发 C++
[√]Android平台ParticleSystem内存泄露的排查过程
[√]Android平台ParticleSystem内存泄露的排查过程
74 1
|
JSON C++ 数据格式
《C++避坑神器·二十二》VS能正常运行程序,但运行exe程序无响应解决办法
《C++避坑神器·二十二》VS能正常运行程序,但运行exe程序无响应解决办法
157 0
|
存储 监控 NoSQL
J3D在UOS+KIRIN崩溃3:GLProfile正确初始化及解决办法
J3D在UOS+KIRIN崩溃3:GLProfile正确初始化及解决办法
88 0