gdb单步调试底层实现原理

我,子牙老师,一个手写过操作系统、编程语言、Java虚拟机、docker、Ubuntu系统,玩透Windows内核、Linux内核的...硬核男人

关于gdb调试器,我已经写了三篇硬核文章了《从零手写gdb调试器》《调试器是如何让代码停下来的》《gdb调试器底层实现原理》,今天开启它的第四篇:gdb单步调试代码的底层实现原理

国内关于gdb调试器相关的资料非常少,如果你对调试器底层实现感兴趣,欢迎关注公众号【硬核子牙】,看调试器系列文章。如果你想写一个自己百分百控股的调试器,欢迎学习我的课程《从零手写gdb调试器》

什么是单步调试,就是这三个按钮

从左到右:step over,单步步过。step into,单步步入。step out,单步步出。本篇文章主要谈step into,中间那个。因为step over、step out的实现要依赖step into。step over、step out,后面再写文章细讲

看完本篇文章,你能学到单步步入的全部:

  1. 单步步入的底层实现原理
  2. 实战:不依赖Linux内核自实现单步步入
  3. 调试Linux内核看单步步入在内核层是如何实现的
  4. Linux内核是在何时清除单步标识的
  5. 调试Linux内核论证单步标识清除

以下,enjoy

单步步入底层原理

单步步入的底层实现,是依赖CPU实现的。在CPU内部,有一个寄存器叫状态寄存器:elfags,长这样

其中第8位对研究单步调试非常关键:TF位,单步标志位。记住TF这两个单词,等下看Linux内核源码会看到。

这个TF是如何工作的呢?

当CPU执行完一条机器指令后,会瞄一眼自己的EFLAGS寄存器,如果其中的 TF(Trap Flag)位为1,就会触发一个调试异常(#DB),它是异常向量号1,属于硬件异常,由 CPU自动产生

你可能注意到了EFLAGS中的第9位,IF(Interrupt Flag)位,中断使能控制位。如果这位为0,即关闭中断,会影响单步调试吗?答案是不会。这个位只影响中断,不影响异常。这个位一般是1,因为中断是一直在发生的

所以EFALGS的值如果是0x3**,就表示开启了单步调试功能。接下来咱们实战一下

自实现单步步入

为了实战演示,我给我写的调试器增加了两个功能:开启单步、关闭单步,本质就是修改ELFAGS寄存器的第8位

来看下实战效果。我在main函数处下断点,让程序跑到这个位置停下来,当前的CPU所处位置是0x400542

看下elfags寄存器的值

0x246,没有开启单步调试。我如果现在执行continue,程序就运行结束了。我执行step命令,开启单步调试功能

接下来我执行continue,看它是单步执行还是执行结束

可以看到,是单步执行的。再看下TF位的值

发现还在,所以你现在执行continue,它会一直单步走。但是gdb的单步,你会发现它不是一直生效,它只生效一次,那gdb是何时清除TF位的呢?留个问题,后面会讲到

执行step_del清除TF位,再执行continue,让程序执行结束

一切如我们所愿。自己写的调试器,精准控制程序运行,酷不酷?

Linux内核层实现单步步入

gdb是如何实现单步调试的呢?

使用ptrace函数,request=PTRACE_SINGLESTEP,进入Linux内核做了什么呢?就找重点代码,设置EFLAGS的TF位

最终会执行到这个函数

找到核心代码了!

Linux内核清除单步标识

前面说过,gdb的单步调试是一次性的,言外之意就是执行了一次单步,就会清空EFLAGS中的TF位,这个清空的动作是gdb做的还是Linux内核做的呢?

Linux内核做的!什么时候做的呢?其实研究Linux内核需要一种这样的思维:就是如果这个功能你来实现,你会选择在哪个时机做呢?

答案是,1号#DB硬件异常的处理逻辑里。你仔细想想,是不是这里是最合适的?

至此,gdb调试器的单步调试功能的底层实现原理,就全部讲完了。step over、step out,下篇安排。关注公众号【硬核子牙】,看调试器系列硬核文章

最后再打个小广告,如果你想学习手写操作系统及实战Linux内核,如果你对调试器底层实现感兴趣,同时想写一个自己可以百分百控制的调试器,调试你自己写的操作系统,欢迎去我公众号【硬核子牙】看我之前的文章,了解课程详情。

相关推荐
Dovis(誓平步青云)4 小时前
《剖析 Linux 文件系统:架构、原理与实战操作指南》
linux·运维·服务器
千百元4 小时前
centos查线程数
linux·运维·centos
---学无止境---4 小时前
Linux中基数树标签相关操作函数的实现
linux
or77iu_N4 小时前
Linux 解压安装(安装tomcat)
linux·运维·tomcat
海棠蚀omo5 小时前
Linux操作系统-父进程的等待:一个关于回收与终结的故事
linux·操作系统
乌萨奇也要立志学C++5 小时前
【Linux】Ext系列文件系统 从磁盘结构到文件存储的原理剖析
android·linux·缓存·1024程序员节
软安科技5 小时前
专有软件使用Linux内核的用户头文件违反GPL吗?| 开源合规场景
linux·开源软件·开源协议
A-刘晨阳5 小时前
K8S 二进制集群搭建(一主两从)
linux·运维·云原生·容器·kubernetes
egoist20236 小时前
[linux仓库]信号处理[进程信号·伍]
linux·信号处理·写时拷贝·软中断·硬件中断·缺页中断·时钟中断