首页 > 其他分享 >Lua断点调试 - 类似gdb的调试体验

Lua断点调试 - 类似gdb的调试体验

时间:2023-10-05 17:01:14浏览次数:52  
标签:debugger lua local dbg Lua 断点 调试

平时在做一个C++/Lua的项目,C++代码可以用gdb调试,但是Lua代码的调试却一直是个困扰人的难题。根据网上搜索的结果,无外乎都是用vscode插件调试,或者用socket之类的设施进行远程调试,个人都觉得太麻烦了,最好有个类似gdb那种直接在命令行中进行调试。

不过经过我在网上的搜索,终于还是找到了满足需求的调试器——debugger.lua。(项目地址 https://github.com/slembcke/debugger.lua ,下面简称dbg)

dbg的一大优点就是无需安装依赖、无需折腾各种socket,直接把lua文件扔进项目里面即可使用。调试器本身只有一个文件,并且都是只使用lua原生的debug库、io、os之类的设施实现的,支持Lua 5.x和LuaJIT。顺便一提这个是MIT协议开源的调试器,不必担心自己的项目被协议强制开源化。

虽然仓库的README里面已经写了详细的解说,但这里还是稍微记载一下自己的使用历程好了。

基本使用 - 断点与调试

[notify@npc dbg]$ ls
debugger.lua  test.lua

如图,test.lua用来进行调试功能的测试,而debugger.lua则是调试器本身。test.lua的内容如下:

local dbg = require 'debugger'

local main = function()
  local a = 123
  local b = 456
  local c = "Hello, world!"
  dbg() -- 这里就是下断点了
  print(c)
end

main()

像这样先把调试器require进来,然后使用dbg()就能实现下断点了。

使用lua test.lua去执行test.lua,此时代码执行到main函数的dbg()处了,这就是触发了断点(debugger.lua不支持像各种IDE那样点击行号下断点,但其实这种操作方法也挺不错的)

[notify@npc dbg]$ lua test.lua
debugger.lua: Loaded for Lua 5.4
break via dbg() => test.lua:8 in local 'main'
debugger.lua>

这样就进入了调试界面。输入"h"命令即可查看所有的操作:

debugger.lua> h
  <return> => re-run last command
  c(ontinue) => continue execution
  s(tep) => step forward by one line (into functions)
  n(ext) => step forward by one line (skipping over functions)
  f(inish) => step forward until exiting the current function
  u(p) => move up the stack by one frame
  d(own) => move down the stack by one frame
  w(here) [line count] => print source code around the current line
  e(val) [statement] => execute the statement
  p(rint) [expression] => execute the expression and print the result
  t(race) => print the stack trace
  l(ocals) => print the function arguments, locals and upvalues.
  h(elp) => print this message
  q(uit) => halt execution

和gdb非常类似:c=继续执行,s=单步步入函数,n=单步下一行,p则可打印出某些值的信息。除此之外,help也给出了其他相当不错的命令,比如l可以输出当前所有的局部变量以及函数的参数、上值:

debugger.lua> l
  a => 123
  b => 456
  c => "Hello, world!"

w命令可以查看当前代码(类似gdb的l命令):

debugger.lua> w
   3    local main = function()
   4      local a = 123
   5      local b = 456
   6      local c = "Hello, world!"
   7      dbg() -- 这里就是下断点了
   8 =>   print(c)
   9    end
  10    
  11    main()

输入n命令执行下一行,此时打印出Hello, world,函数也即将返回。

debugger.lua> n
Hello, world!
test.lua:9 in local 'main'

此外,打印函数栈、print、eval等操作对于熟悉gdb调试的人应该都不难理解。只能说debugger.lua的体验确实相当不错呀。

活用API

dbg()进行简单下断点已经能满足绝大多数情况的需求了,但是debugger.lua还提供了更多实用功能,除了dbg()之外我们还能用更多好用的函数解决其他方面的问题。

  • dbg.writeln(fmt, ...) : 基本上就是print(string.format(fmt .. "\n", ...))
  • dbg.pp(obj) : 输出某个object(通常是表)的看起来更加直观的形式。比如他会输出{"a" = 1, "b" = 3}而不是table: 0x55fc28e72ef0
  • dbg.auto_where = int_or_false : 这个值一般是在初始化debugger.lua的时候设置的。设为true的话,每中断一次就自动执行w命令让你看清中断在哪一行了。
  • dbg.error(error, [level]) : 类似自带的error(),但是输出错误信息后自动进入调试。
  • dbg.assert(exp, [message]) : 同上。
  • dbg.call(f, ...) : 类似pcall(),但在出错后自动进入调试。

标签:debugger,lua,local,dbg,Lua,断点,调试
From: https://www.cnblogs.com/notify-ctrl/p/17743548.html

相关文章

  • Fast-Dds源码调试方案
    1、虚拟机安装:参考ubuntufastdds安装-墨尔基阿德斯-博客园(cnblogs.com);2、Ubuntu安装gdb:sudoaptinstallgdb3、查看gdb的安装路径(默认安装在/usr/bin/gdb):whichgdb4、配置调试参数,以示例程序HelloWorldExample为例:1)、重新编译fastdds库(只编译一次就行,更换......
  • 10.3 调试事件转存进程内存
    我们继续延申调试事件的话题,实现进程转存功能,进程转储功能是指通过调试API使获得了目标进程控制权的进程,将目标进程的内存中的数据完整地转存到本地磁盘上,对于加壳软件,通常会通过加密、压缩等手段来保护其代码和数据,使其不易被分析。在这种情况下,通过进程转储功能,可以将加壳程序的......
  • 10.2 调试事件获取DLL装载
    理解了如何通过调试事件输出当前进程中寄存器信息,那么实现加载DLL模块也会变得很容易实现,加载DLL模块主要使用LOAD_DLL_DEBUG_EVENT这个通知事件,该事件可检测进程加载的模块信息,一旦有新模块被加载或装入那么则会触发一个通知事件,利用该方法并配合磁盘路径获取函数则可很容易的实现......
  • 10.3 调试事件转存进程内存
    我们继续延申调试事件的话题,实现进程转存功能,进程转储功能是指通过调试API使获得了目标进程控制权的进程,将目标进程的内存中的数据完整地转存到本地磁盘上,对于加壳软件,通常会通过加密、压缩等手段来保护其代码和数据,使其不易被分析。在这种情况下,通过进程转储功能,可以将加壳程序的......
  • 10.2 调试事件获取DLL装载
    理解了如何通过调试事件输出当前进程中寄存器信息,那么实现加载DLL模块也会变得很容易实现,加载DLL模块主要使用LOAD_DLL_DEBUG_EVENT这个通知事件,该事件可检测进程加载的模块信息,一旦有新模块被加载或装入那么则会触发一个通知事件,利用该方法并配合磁盘路径获取函数则可很容易的实......
  • 10.3 调试事件转存进程内存
    我们继续延申调试事件的话题,实现进程转存功能,进程转储功能是指通过调试API使获得了目标进程控制权的进程,将目标进程的内存中的数据完整地转存到本地磁盘上,对于加壳软件,通常会通过加密、压缩等手段来保护其代码和数据,使其不易被分析。在这种情况下,通过进程转储功能,可以将加壳程序的......
  • 无涯教程-OC - 应用调试
    无涯教程在开发应用程序时可能会犯错误,这可能导致不同类型的错误。为了修复这些错误或错误,无涯教程需要调试应用程序。选择调试器Xcode有两个调试器,即GDB和LLDB调试器,默认情况下,已选择GDB。LLDB是作为LLVM开源编译器项目一部分的调试器,您可以通过“editactiveschemes”选项来......
  • Java新特性中的Preview功能如何运行和调试
    在每个Java新版本发布的特性中,都会包含一些Preview(预览)功能,这些功能主要用来给开发者体验并收集建议。所以,Preview阶段的功能并不是默认开启的。如果想体验某个Java版本中的Preview功能,您还需要做一些设置才能把程序跑起来。下面以IDEA2023.2为例,演示为Java21开启Preview功能......
  • 10.1 调试事件读取寄存器
    当读者需要获取到特定进程内的寄存器信息时,则需要在上述代码中进行完善,首先需要编写CREATE_PROCESS_DEBUG_EVENT事件,程序被首次加载进入内存时会被触发此事件,在该事件内首先我们通过lpStartAddress属性获取到当前程序的入口地址,并通过SuspendThread暂停程序的运行,当被暂停后则我没......
  • 在 WebStorm 里调试 vue3 项目
    官方说明:https://blog.jetbrains.com/webstorm/2018/01/working-with-vue-js-in-webstorm/#:~:text=Wecandebugourapplication,andstartthedebugsession.打开WebStorm编辑器右上角的Configuration的Edit,在URL填入项目的地址并选择想要使用的Brower,点击调试之......