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内核,如果你对调试器底层实现感兴趣,同时想写一个自己可以百分百控制的调试器,调试你自己写的操作系统,欢迎看我【个人简介】详细了解我的课程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值