调试器是怎么让代码停下来的

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

前两天写了篇文章《从零手写gdb调试器》,就有小伙伴在后台留言
在这里插入图片描述

估计有很多小伙伴都有这样的疑惑吧,那就写篇文章细细聊聊

以下,enjoy

程序断下来的秘密

当我们点亮代码前面的红圈,本质是下断点,当CPU运行到那行代码对应的指令,程序就会断下来。感官上就是程序停下来了,有点像Java世界的STW,那一刻,世界仿佛按下了暂停键
在这里插入图片描述

有好奇的小伙伴心中就生出了疑问:为什么?奈何调试器相关的资料奇少,所以这个疑问就一直存在着,找不到答案

从gdb的角度,让程序断下来的两个方式:软件断点、硬件断点
在这里插入图片描述

软件断点的本质就是将那块内存的一字节位置改为0xCC,0xCC对应的汇编指令是int 3,即3号中断,是一个CPU软中断。是不是没概念,别急,文章后面证明给你看

硬件断点是基于CPU中的8个调试寄存器DR0-DR7实现的。其中DR4、DR5是保留的。DR6为调试状态寄存器,标识哪个断点触发了中断。DR7可以看成是调试寄存器中的控制寄存器,比如开关硬件断点。所以算下来,硬件断点最多只能下四个,即DR0-DR3。是不是没概念,别急,文章后面证明给你看

硬件断点从CPU的角度来说,是一种硬中断,2号中断

学过我的课程《手写操作系统》的都知道这张图。当我们自己写操作系统的时候,我们需要从BIOS手中接管CPU中断异常处理,就需要定义中断向量表。其中0-19是CPU固定死的,需要按这个图来配置
在这里插入图片描述

比如除零异常,对应的就是0号异常,这是CPU内部写死的,你如果不把中断向量表中index=0的位置定义成除零异常处理例程,你写的操作系统就乱套了

你是不是想知道操作系统中的中断向量表长啥样,其实没啥神奇的就是一个数组,如图
在这里插入图片描述

但是这里面每个value有点复杂,是一个中断门描述符。你说这东西没人教怎么学得会?我是觉得操作系统没人教是真的学不会,我自己也是跟老师学才学会的。有人教学起来还算简单,没人教根本无从学起
在这里插入图片描述

CPU触发中断与异常,怎么抛给操作系统,又怎么抛给应用程序,说白了就是这些是怎么串起来的,值得深究。如果你想对CPU的中断与异常了解得更多,想自己亲身实践出来,欢迎看我的【个人简介】,了解我的课程《手写操作系统》

断点与调试器是如何关联的

以Linux系统为例,不同的OS可能不一样哦。如图
在这里插入图片描述

以软件断点为例吧:

  1. CPU高兴地执行着指令,执行到0xCC,CPU马上就兴奋了,这不是3号中断吗,要去执行中断处理程序了
  2. CPU拿出中断向量表的地址并拿到3号中断的处理程序idt_addr[3]
  3. CPU开始执行3号中断处理例程,核心逻辑就是给调试进程发送SIGTRAP信号,即5号信号
  4. 调试进程通过waitpid拿到SIGTRAP信号,开始进行相关处理:将0xCC还原成下断点前的指令,程序寄存器rip-1(为什么要这样?一两句话讲不清)
  5. 调试进程放出命令行给用户操作

这就是断点与调试器,在CPU层面、Linux内核层面、应用程序层面、调试器层面关联的秘密!也是所有调试器得以实现的基石!

论证软件断点

接下来开始论证

1、查看main函数的内存地址:0x400542,未下断点之前,这个位置的值是0x55,对应的汇编指令是push rbp
在这里插入图片描述

2、下断点,0x55变成了0xCC,对应的汇编指令是int3
在这里插入图片描述

3、执行continue,程序在断点处停下来了,0xCC又还原成0x55了
在这里插入图片描述

软件断点就是这么玩的!怎么样,写一个调试器玩底层方便吧!快来吧!

论证硬件断点

接下来论证硬件断点

1、先查看DR寄存器
在这里插入图片描述

2、查看函数hello的内存地址,并下硬件断点
在这里插入图片描述

3、查看DR寄存器是否被修改了,确实修改了
在这里插入图片描述

4、执行continue,确实停在硬件断点处了
在这里插入图片描述

这就是硬件断点的全部展示

最后再打个小广告,如果你想学习手写操作系统及实战Linux内核,如果你对调试器底层实现感兴趣,同时想写一个自己可以百分百控制的调试器,调试你自己写的操作系统,欢迎看我【个人简介】详细了解我的课程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值