浅析Lua调试器的实现
摘要 本文简单介绍了如何实现一个Lua调试器,实现Lua调试器的目的仅仅是寄希望借此熟悉Lua源代码。所编写的Lua调试器功能越强,表明你对Lua源码越了解。 正文 先前用lua写过一些应用,感觉Lua是一个很小巧的语言,Lua源代码无疑是研究语言相关的首选。“Lua虽小,五脏俱全”!为了研究Lua源代码,就打算着手写一个简单的Lua调试器,发现其中还是有些收获的,特记录如下。 作为一个调试器,应该支持一些最简单而又常用的功能,比如:单步跟踪、输出调试信息、设置断点等。要探索如何实现Lua调试器,还是带着这些问题去找答案吧。本文使用的开发环境为:win7,lua 5.1.4源代码。 1.Lua虚拟机是如何暂停的? Lua虚拟机和普通的CPU一样,包含两部分:数据存储区和逻辑控制区。数据存储区对应着CPU的寄存器、状态等,在Lua中实际上就是lua_State。逻辑控制区对应着CPU的每条指令的具体实现。Lua虚拟机逻辑控制区的相关的源代码位于lvm.c中。其中,执行Lua指令的函数为luaV_execute。 为了方便调试,函数luaV_execute在执行每条Lua指令之前,会去查找是否存在调试钩子(hook):存在的话,去执行钩子。然后,判断Lua虚拟机的状态是否为暂停,若是的话就返回,而不执行当前Lua指令。若不存在调试钩子,则正常执行Lua指令。 1: if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && 2: (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
3: traceexec(L,pc); // 内部会执行相应的钩子函数 4: if (L->status == LUA_YIELD) { // 钩子函数是否将状态转为暂停? 5: L->savedpc = pc - 1;
6: return; // 此处离开函数luaV_execute,导致虚拟机暂停执行 7: }
8: base = L->base; 9: }
由此想到一个办法可以让Lua虚拟机暂停: 2.Lua虚拟机是如何继续执行的? 了解了Lua虚拟机是如何暂停之后,就很容易看到,可以采用如下步骤:首先,将Lua虚拟机的状态设置为0(正常状态),然后执行函数luaV_execute即可。这两步操作可以采用Lua的C函数lua_resume即可。 3.Lua调试器的其它功能该如何实现? 其它的一些功能,比如:获取Lua虚拟机中的一些信息,这些还是比较容易实现的。因为,一旦Lua虚拟机暂停后,可以通过查找lua_State中的信息来查询,具体怎么查询,那就取决于你对lua源代码的熟悉程度了。反正都在lua_State里面,可以直接获取的。 4.Lua调试器究竟该怎么实现? 考虑到,调试器可能是命令行版本的,也可能是包含界面的调试器。可以考虑将调试器作为一个库来实现,然后这个库提供了一些接口,方便和前台衔接。一下就是我封装的一些接口,仅供参考: 1: ECode luad_init(const char * filename);
2: ECode luad_command_step(int * pErr); 3: ECode luad_command_go(int * pErr); 4: ECode luad_command_bk(int line); 5: ECode luad_command_bkinfo(int ** ppBklines,int * pNum); 6: int luad_currentline(); 7: Boolean luad_is_script_ended();
这个库加上前段的命令输入控制,就很容易做出一个命令行版的Lua调试器了。同理,做界面版的也很容易。下面是我写的Lua调试器命令行版运行截图。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |