gdb到底是怎样实现的?

2019-06-08 06:23发布

gdb这个debug工具,应该无人不知吧。服务器开发和客户端开发人员应该都或多或少的通过这个工具排查问题。但有没有想过它的实现原理,为什么打断点能够在断点处停止运行?为什么能查看cpu寄存器?等等。我们就带着这些疑问接着往下看。

知识铺垫

我们都听说过系统调用,这里简单的解释下系统调用的含义。操作系统提供了一种标准的服务来让程序员实现对底层的硬件和服务的控制,比如申请、释放内存,打开、关闭文件等等,这就叫做系统调用(system calls)。

系统调用的过程比较复杂,大致流程是这样的:将相关参数放进系统调用的相关寄存器中,然后调用软中断(0x80),这个中断作用就是让一个程序从用户态陷入到内核态执行,程序将参数和系统调用号交给内核,内核来执行。

看完这个知识铺垫,估计心里猜测跟系统调用有关系了。确实不是特别高大上的技术,只是利用了Linux提供的非常优雅的方式:ptrace系统调用,用man查看以下这个系统调用。ptrace可以让父进程观察和控制其子进程的检查、执行,改变其寄存器和内存的内容。主要的作用就是大家常用的打断点的功能了,还有一个功能是打印系统调用的轨迹信息。

我们先来看下这个ptrace函数的原型:


#include 
long ptrace(enum __ptrace_request request, pid_t pid,
void *addr, void *data);

第一个参数决定了ptrace的行为与其他参数的使用方法。可取的值有:


PTRACE_ME
PTRACE_PEEKTEXT
PTRACE_PEEKDATA
PTRACE_PEEKUSER
PTRACE_POKETEXT
PTRACE_POKEDATA
PTRACE_POKEUSER
PTRACE_GETREGS
PTRACE_GETFPREGS,
PTRACE_SETREGS
PTRACE_SETFPREGS
PTRACE_CONT
PTRACE_SYSCALL,
PTRACE_SINGLESTEP
PTRACE_DETACH


下面对常用的几种模式进行说明。

  1. PTRACE_ME(跟踪我):这是相对父进程而言的。功能是指示父进程,对其进行跟踪。trace工具的实现就是用这个模式。
  2. PTRACE_GETREGS:读取寄存器的值。如果你想在系统调用或者进程停止前读取它的寄存器。这就回答了文章开头的第二个问题。
  3. PTRACE_SINGLESTEP:单步。会使内核在子进程的每一条指令执行前先将其阻塞,然后控制权交给父进程。
  4. PTRACE_PEEKDATA:设置断点。调试器怎么设置断点的呢?通常情况下,将当前需要执行的指令替换成trap指令,于是就会停在当前位置。被调试程序恢复运行以后调试器将原指令放回来就可以了。具体实现过程请接着往下看!

详细可参考《http://man7.org/linux/man-pages/man2/ptrace.2.html》

gdb三种调试方式

看完ptrace使用方法,再来看看gdb的三种调试方式。

  1. attach并调试一个已经运行的进程: 确定需要进行调试的进程id ;运行gdb,输入attch pid,如:gdb 12345。gdb将对指定进行执行如下操作:ptrace(PTRACE_ATTACH,pid,0,0)
  2. 运行并调试一个新的进程 :运行gdb,通过命令行参数或file指定目标调试程序,如gdb ./test ;输入run命令,gdb执行下述操作: 通过fork()系统调用创建一个新进程 。在新创建的子进程中调用ptrace(PTRACE_TRACEME,0,0,0) 。在子进程中通过execv()系统调用加载用户指定的可执行文件
  3. 远程调试目标主机上新创建的进程 :gdb运行在调试机,gdbserver运行在目标机,通过二者之间定义的数据格式进行通信。


断点的实现过程

再回到刚文章开头的问题,断点是怎样实现的呢?我从上面文字中知道gdb调试的实现都是建立在信号的基础上的。在使用参数为PTRACE_TRACEME或PTRACE_ATTACH的ptrace系统调用建立调试关系后,交付给目标程序的任何信号首先都会被gdb截获。

因此gdb可以先行对信号进行相应处理,并根据信号的属性决定是否要将信号交付给目标程序。

当用breakpoint 设置一个断点后,gdb会在=找到该位置对应的具体地址,然后向该地址写入断点指令INT3,即0xCC。

目标程序运行到这条指令时,就会触发SIGTRAP信号,gdb会首先捕获到这个信号。然后根据目标程序当前停止的位置在gdb维护的断点链表中查询,若存在,则可判定为命中断点。

喜欢这篇文章,请不要忘记点击右下方“在看”,谢谢!

文章来源: https://www.toutiao.com/group/6699652803918299655/