断点原理程序(断点程序调试器原理代码)「断点调试 原理」

对于程序员来说,debug的时间往往比写程序的时间还要长
尤其对我这种专写bug为主的程序员来说,一个好的调试器意味着早点下班和休息
现在方便的调试器很多,有著名的Visual Studio(VS)等IDE,也有免费的Windbg和GDB等等
加个断点也很简单,就是按一下键而已
但你有没有想过,调试器Debugger并不能控制程序的执行顺序,为什么它可以让CPU在需要的地方停住呢?今天我们就来揭开调试断点的神秘面纱,并通过一个实例来看看调试器实际都做了些什么
调试器能够随心所欲的停止程序的执行,主要通过软件断点和硬件断点两种方式
软件断点软件断点在X86系统中就是指令INT 3,它的二进制代码opcode是0xCC
当程序执行到INT 3指令时,会引发软件中断
操作系统的INT 3中断处理器会寻找注册在该进程上的调试处理程序
从而像Windbg和VS等等调试器就有了上下其手的机会
我们先通过一个例子来看看调试器都倒了什么鬼:#include int main (){// This loop takes some time so that we// get a chance to examine the address of// the breakpoint at the second printffor (int i = 1; i < 100000000; i++) printf(\"Hello World!\");for (int i = 1; i < 10000000; i++) printf(\"Hello World!\");return 0;} 这是一个比较傻的Hello World程序
我们用Windbg打开它,并设置一个断点:这时Windbg会将自己Attach到该程序的进程,通过程序PE文件的debug节找到调试信息
在调试信息里面找到加断点行所在的机器代码,并把头一个字节用WriteProcessMemory()函数换成0xCC(INT 3)
让我们来验证一下:推荐点开全屏看,可能更清楚注意左边是Windbg窗口,右边是用Process view打开的进程空间,左右的红框是对应的
在我们设置断点之前,左右的内容是完全一样的,这里要特别注意printf编译出来的第一个二进制代码0x68
接下来我们设置断点,并开始运行,那100万个printf让我们有充分的时间,看看发生了什么:我们会发现push操作代码0x68600e2900的第一个字节被windbg换成了0xCC也就是INT 3
这样windbg就可以在执行到这里时被调度
不一会,windbg的断点到了:到达断点后,操作符又被还原为0x68,似乎什么都没有发生,用户被蒙在鼓里,是不是很有意思?实际上,一般情况下,调试器维护了一大组调试断点,在并把他们都换成了INT 3
在被调度回来后,会都填回去,并通过现在的地址判断是到了那个断点
软件断点没有数目限制
硬件断点X86系统提供8个调试寄存器(DR0~DR7)和2个MSR用于硬件调试
其中前四个DR0~DR3是硬件断点寄存器,可以放入内存地址或者IO地址,还可以设置为执行、修改等条件
CPU在执行的到这里并满足条件会自动停下来
硬件断点十分强大,但缺点是只有四个,这也是为什么所有调试器的硬件断点只能设置4个原因
我们在调试不能修改的ROM时,只能选择这个,所以要省着点用,在一般情况下还是尽量选择软件断点
还有个INT 1是单步调试命令,这里略过
其他Visual Studio有个有趣的特性是debug编译后,会把0xcc(INT 3)填入代码的空隙,这样一旦程序越界就会被VS捕捉而容易发现错误
而0xCCCC在中国的GBK编码是“烫”
有中国程序员翻看内存到代码段会发现很多\"烫烫烫\",不明所以,以为发生了什么神奇的事情
有些程序越界也会打出\"烫烫烫\":有的用户被吓得够呛,以为计算机过热了,喊烫了,赶紧关机,十分搞笑
断点原理程序(断点程序调试器原理代码)
(图片来源网络,侵删)

联系我们

在线咨询:点击这里给我发消息