断点之软件断点的一些基本知识(INT3)
软件断点:
断点异常(INT 3) 属于陷阱类异常,当CPU 产生异常时候,其程序指针是指向导致异常的下一条指令,但是我们观察到的是
却指向当前的导致异常的这条指令(想计算机组成原理的实验 IP)
原因:在中断到调试器的时候,会把所有断点位置恢复成原先的指令,再交给用户
也就是DEC ebx
2.当我们设置断点的时候,调试器会把这里的本来指令的第一个字节保存起来 然后写入INT3指令,因为INT3为0xCC(11001100)一个
字节,所以设置和取消断点时候也只需要保存和恢复一个字节。
VC6把断点的设置信息(断点所在的文件和行位置)保存在和项目文件相同位置且相同主名称的一个.opt文件中,但是他不会保存
每个断点处应该被INT3指令替换掉的那个字节
原因:1.替换是在启动调试和时候和调试过程中动态执行的
2.我们可以在非调试状态下去注释行设置断点,它仅仅是记住该断点的位置信息,当真正调试时候(即被调试程序RUN起来),VC6才会取出OPT文件中的断点记录(我叫做静态罢了,虽然不贴切),射到目标代码的内存映像中,也就是保存此位置的原来的指令的第一个字节,再替换为0xCC,这叫做落实断点
3.断点命中(应用程序调试)执行例程函数
保存当前上下文,寄存器内容
断点指令我们在用户模式下的程序代码中,所以我们从用户模式要到内核模式,断点也是异常么,所以流程为:
有异常的进程正在被调试-->内核例程会把这个异常以调试事件的形式分发给用户模式的调试器。(内核的调试子系统函数会等待调试器的恢复,收到回复后,调试子系统的函数会层层返回,最后返回到异常处理例程,异常处理例程执行中断指令,让被调试的程序继续执行)
4.恢复执行
第一次调试返回后恢复之前的指令,那下次调试呢,调试器是利用单步执行标志,即执行完后又再一次的下断点到这
就可以多次在这里中断调试
5.INT3的特别用途
0xCC在汉语中是烫烫中,CC又是INT 3的指令的机器码,今天我才知道这不是偶然是编译器故意的,
1,为了辅助调试原来是编译器在调试版本时候会
用0XCC来填充刚刚分配好的缓冲区,这样堆栈溢出的时候。直接到INT 3指令中断到调试器
2.内存对齐(填充函数或者代码段末尾的空闲区域)c3->ret
6.局限性