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内核,如果你对调试器底层实现感兴趣,同时想写一个自己可以百分百控制的调试器,调试你自己写的操作系统,欢迎去我公众号【硬核子牙】看我之前的文章,了解课程详情。

相关推荐
2035去旅行11 小时前
bootcmd 详细讲解
linux·嵌入式·arm·soc
陈希12312 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
女神下凡13 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
且从容.16 小时前
Ubuntu安装flume
linux·ubuntu·flume
承渊政道17 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
且从容.20 小时前
ubuntu安装flink
linux·ubuntu·flink
爱和冰阔落21 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨21 小时前
WSL2的安装与使用
linux·wsl
微小的鱼21 小时前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng1 天前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器