设置断点的原理是什么? 断点调试

断点调试(设置断点的原理是什么?)
对于程序员来说,调试通常比编写程序花费更长的时间 。尤其是对于像我这样主要写bug的程序员来说,一个好的调试器意味着早点下班休息 。现在有很多方便的调试器,包括著名的IDE如Visual Studio(VS)、免费的Windbg和GDB等 。添加断点也很简单,只需按键即可 。但是你有没有想过调试器不能控制程序的执行顺序,为什么能在需要的地方停止CPU?
今天,我们将揭开调试断点的神秘面纱,并通过一个例子来看看调试器实际上做了什么 。调试器可以随意停止程序的执行,主要是通过软件断点和硬件断点 。
软件断点在X86系统中,软件断点为指令INT 3,其二进制代码操作码为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; i100000000; i++) printf( Hello World! for资源网络网 (int i = 1; i10000000; i++) printf( Hello World! return 0;}这是一个愚蠢的你好世界节目 。我们用Windbg打开它并设置一个断点:
这时Windbg会把自己附加到程序的进程中,通过程序PE文件的调试部分找到调试信息 。在调试信息中找到断点行所在的机器码,使用WriteProcessMemory()函数将第一个字节替换为0xCC(INT 3) 。
让我们验证一下:
建议全屏打开,可能会更清晰 。
注意Windbg窗口在左边,process视图打开的process 空房间在右边,左右红框对应 。在我们设置断点之前,左右内容完全相同 。这里要特别注意printf编译的第一个二进制代码0x68 。接下来,我们设置断点并开始运行 。100万张照片给了我们足够的时间来看看发生了什么:
我们会发现推送操作码0x68600e2900的第一个字节被0xCC替换,也就是INT 3被windbg替换 。所以windbg在这里执行时可以被调度 。
过了一会儿,嗦的断点到了:
到达断点时,运算符恢复为0x68 。似乎什么都没发生,用户被蒙在鼓里 。是不是很有趣?
事实上,一般来说,调试器维护一大组调试断点,并用INT 3替换它们 。被调度回来后会被补回来,断点由当前地址判断 。软件断点的数量没有限制 。
硬件断点X86系统提供8个调试寄存器(DR0~DR7)和2个MSR用于硬件调试 。其中前四个DR0~DR3是硬件断点寄存器,可以放入内存地址或IO地址,也可以设置执行、修改等条件 。当执行到这里,条件满足时,CPU会自动停止 。
硬件断点非常强大,但缺点是只有四个,这就是为什么所有调试器只能设置四个硬件断点 。我们只能在调试不能修改的ROM时选择这个,所以要节约使用 。一般来说,我们应该尽量选择软件断点 。
还有INT 1单步调试命令,这里忽略 。
其他Visual Studio的一个有趣的特性是,调试后会在代码的空间隙填充0xcc(INT 3),这样一旦程序出界,就会被VS抓住,很容易发现错误 。0xCCCC在中国的GBK代码是“热” 。一些中国程序员在翻看内存中的代码段时会发现很多烫手的地方 。不明所以认为发生了神奇的事情 。
一些越界的程序也会被烫伤:
有些用户吓得要死,以为电脑过热,大喊热,赶紧关机,很搞笑 。
版权声明:【设置断点的原理是什么? 断点调试】本文内容由互联网用户自发贡献,该文观点仅代表作者本人 。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任 。如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 2672143071@qq.com 举报,一经查实,本站将立刻删除 。

    推荐阅读