xv6(riscv)上实现kprobe

kprobelinux实现原理

Linux要使用kprobe一种是有两种方法,一是模块(Module)挂载到内核上就像挂载驱动一样,二是通过debugfs。

Linux里面kprobe的实现比较完善,而且要在一个大系统里运行好各种判断都要滴水不漏,考虑的情况相当多。但是如果简单来讲kprobe的实现就包含下面几步:

1)注册初始化kprobe。每个kprobe对应一个kprobe结构体,该结构中记录着插入点(就是编译后的内核的特定位置),以及该插入点本来对应的指令original_opcode。

2)替换原有指令。用kprobe的时候,将插入点位置的指令替换为一条异常(BRK)指令(x86 int3,riscv ebreak),让CPU执行到插入点时产生异常,进入核心函数kprobe_int3_handler。

3)异常处理函数中执行pre_handler,然后利用CPU提供的单步调试(single-step),设置好相应的寄存器,同时异常返回的地址改为原来的origin_opcode。

4)setup_singlestep()执行完后,继续执行被保存的探测点的指令,因为开启了单步调试某事,执行后再次触发异常但这次是debug。

5)将single-step 清除,执行post_handler,然后从异常态安全返回。

它的一个基本思路就是将本来执行一条指令扩展成执行kprobe->pre_handler —> 指令 —> kprobe–>post_hander。

xv6上实现的设想和问题

就相当于实现一个gdb功能内嵌的函数,老实说觉得没有比gdb调试强多少……

  1. user态肯定传的是要定位的某个函数名,怎么找到特定的函数?objdump或者nm拿到函数的地址,就相当于手写实现一个addr2line的功能。

  2. 主要是怎么把对应地址的指令进行替换成ebreak,通过中断的方式去跟踪函数/指令的前后,先让它陷入中断执行一条命令后就返回吧。


© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容