gdb调试lua_Lua调试工具使用及原理

前言

当我们在linux下使用c/c++开发时,可以通过gdb来调试我们编译后的elf文件。gdb支持了attch、单步运行(单行、单指令)、设置断点等非常实用的功能来辅助我们调试。当使用lua开发的时候,一般可能会使用print(打印到屏幕)或是输出日志等稍微简陋的调试方式,但如果日志输出不能满足我们需求时,比如我们需要类似断点、单步执行等更高级的调试功能,此时就必须借助第三方工具。

本文介绍了lua调试工具LuaPanda的使用,以及lua调试工具和gdb在实现上的一些区别。

gdb调试原理

先简单介绍一下gdb的原理。一般的我们将gdb这种调试进程称为tracer,被调试进程称为tracee。当进程被调试时(处于traced状态)时,每次收到任何除了SIGKILL以外的任何信号,都会暂停当前的执行,并且tracer进程可以通过waitpid来获取tracee的暂停原因。gdb使用ptrace系统调用来实现操作tracee进程

1. gdb附加到进程

当使用gdb附加到一个正在运行的进程(tracee)上时,gdb会执行类似下面的代码:

ptrace(PTRACE_ATTACH, pid, ...)

这里的pid是tracee的pid。系统调用执行后,os会给tracee进程发送一个SIGTRAP信号,然后tracee的执行将会暂停。最后gdb(tracer)可以通过系统调用waitpid来获取tracee的暂停原因,并且开始调试。

2. gdb单步执行

单步调试与上述attch类似,gdb通过下面的代码告诉tracee进程需要在运行完一个指令后暂停:

ptrace(PTRACE_SINGLESTEP, pid, ...)

当tracee执行完一个指令后,tracee也会因为收到os的SIGTRAP信号从而暂停执行。

3. gdb设置断点

设置断点稍微有点不同,首先gdb需要从调试程序的调试信息中根据行号(函数名)找到代码的内存地址,然后通过ptrace将tracee进程的代码替换成一个软中断指令:int 3。由于这个指令实际上会被编码为一个字节0xcc,因此可以很安全的与任何指令替换。

/* Look at the word at the address we're interested in */

unsigned addr = 0x8048096;

unsigned data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)addr, 0);

/* Write the trap instruction 'int 3' into the address */

unsigned data_with_trap = (data & 0xFFFFFF00) | 0xCC;

ptrace(PTRACE_POKETEXT, child_pid, (void*)addr, (void*)data_with_trap);

通过给ptrace指定PTRACE_PEEKTEXT、PTRACE_POKETEXT可以读写tracee进程的代码段的内存。最终当程序执行到int 3时,会触发一个软中断,os会给tracee进程发送SIGTRAP信号。当断点成功后,gdb会用相同的方法用原来的指令替换掉i

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值