今天有人让我解释一下断点调试的原理,我就想先解释一下int3指令,就写了一篇短文。 单字节指令int3的二进制码是0xcc,它的效果是: 就这么简单。剩下的就看信号处理程序如何发挥了。 我给出一个简单的代码,演示一下一个程序的 自我单步跟踪 如何实现: 来吧,看看效果: 文章很短,可以仔细体会一下。 关于int3指令,下面这个链接解释了为什么int3是单字节指令: 浙江温州皮鞋湿,下雨进水不会胖。
#include <stdio.h> #include <sys/mman.h> #include <signal.h> unsigned char old; unsigned char *inst; // RIP距离stack的当前位置正好192字节,详情参见rt_sigframe结构 #define PC_OFFSET 192 // value ++指令从main函数的第106字节开始,这个是从objdump -D看出来的。 static int i = 106; // 这是我们单步跟踪的变量。 int value = 0; // 打断点需要两步: // 1. 保存原始单字节指令。 // 2. 替换为int3指令。 void breakpoint(char *inst) { old = *inst; *inst = 0xcc; } void trap(int unused) { unsigned long *p; // 恢复断点需要两步: // 1. 恢复单字节为保存的指令。 // 2. PC寄存器回退一个字节。 p = (unsigned long*)((unsigned char *)&p + PC_OFFSET); // 可以在这里来一个命令行查询更详细的程序当前状态,我这里仅仅一行打印,说明问题够了。 printf("current RIP: :%lx value:%dn", *p, value); inst[i] = old; *p = *p - 1; // 单步跟踪value的值: // value ++正好需要15个字节的指令。 i += 15; // 设置新的断点为下一个value ++ breakpoint(&inst[i]); } int main(int argc, char **argv) { unsigned char *page; unsigned long rip; signal(SIGTRAP, trap); inst = (unsigned char *)main; // addr按照4096对齐 page = (unsigned char *)((unsigned long)inst & 0xfffffffffffff100); // 让main函数可写。 mprotect((void *)page, 4096, PROT_WRITE|PROT_READ|PROT_EXEC); // 设置第一个断点为第一个value ++。 breakpoint(&inst[i]); value ++; value ++; value ++; value ++; value ++; value ++; printf("value is %dn", value); }
[root@localhost test]# ./int3test current RIP: :4006c6 value:0 current RIP: :4006d5 value:1 current RIP: :4006e4 value:2 current RIP: :4006f3 value:3 current RIP: :400702 value:4 current RIP: :400711 value:5 current RIP: :400720 value:6 value is 6
https://www.cs.columbia.edu/~junfeng/09sp-w4118/lectures/int3/int3.txt
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算