Linux内核调试方法总结之Jprobes
Jprobes
【用途】
类似于Kprobes和Return Probes,区别在于,Kprobes可以在任意指令处插入探针,Jprobes只在函数入口插入探针,而Return Probes则是在函数返回时插入探针。
【接口说明】【参考samples/kprobes/jprobe_example.c】
#include <linux/kprobes.h>
int register_jprobe(struct jprobe *jp);
void unregister_jprobe(struct jprobe *jp);
int enable_jprobe(struct jprobe *jp);
int disable_jprobe(struct jprobe *jp);
【番外篇】
我这篇也就写点儿使用Kprobe和Jprobe的注意事项:
用Kprobe和retprobe注册的handler运行于原子(atomic)上下文,因为它们都是运行在int3的异常处理函数或调试(debug)中断的处理函数中,并且两者都是在关闭当前cpu中断的前提下执行的。相比之下,Jprobe就灵活得多了,用它注册的handler的执行环境和原始的执行环境并没有两样,堆栈环境和cpu寄存器都是相同的。
因为Jprobe执行用户注册的handler之前有保存现场(主要是int3之前的CPU寄存器的值)的工作,所以Jprobe的handler是没有办法破坏寄存器的值的,但是可以改变堆栈中的变量的值,Kprobe将没有这些限制,它对系统具有完全的访问权限,另一方面,Kprobe也比Jprobe危险得多,如果只是简单的打印一些系统信息,推荐用Jprobe,不要冒险!
Jprobe机制和用户空间的setjmp和longjmp的实现比较类似,事实上,它的内核代码的注释部分也是如此作类比的,所以用register_jprobe注册的代码段,最后必须要用jprobe_return进行返回,当然,如果你想让它一去不复返除外。这点就象用kprobe注册的handler必须是可以返回的函数一样。目前,能想到的就这么多了。
BTW: 看kprobe的内核代码的时侯,发现有的地方还是有些缺陷的,比如说某些地方用preempt_disable()关闭了抢占,但是当函数出错返回的时侯,并没有打开抢占。不知道最新的内核有没有修复这些细节,懒得去看了,应该没有哪个正式的发型版会打开这个选项的。所以文章标题中所提到的注入的可能性也就比较小了,本来这个东西出现的背景就是为了方便内核开发者的调试工作!
【实例】
/*jprobe_test.c */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uio.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
/*
* Jumper probe for do_fork.
* Mirror principle enables access to arguments of the probed routine
* from the probe handler.
*/
/* Proxy routine having the same arguments as actual do_fork() routine */
long jdo_fork(
unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user * parent_tidptr,
int __user * child_tidptr) {
printk("jprobe: clone_flags=0x%lx, stack_size=0x%lx, regs=0x%p\n", clone_flags, stack_size, regs);
/* Always end with a call to jprobe_return(). */
jprobe_return();
/*NOTREACHED*/
return 0;
}
static struct jprobe my_jprobe = {
.entry = (kprobe_opcode_t *) jdo_fork
};
int init_module(void) {
int ret;
my_jprobe.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork");
if (!my_jprobe.kp.addr) {
printk("Couldn't find %s to plant jprobe\n", "do_fork");
return -1;
}
if ((ret = register_jprobe(&my_jprobe)) <0) {
printk("register_jprobe failed, returned %d\n", ret);
return -1;
}
printk("Planted jprobe at %p, handler addr %p\n", my_jprobe.kp.addr, my_jprobe.entry);
return 0;
}
void cleanup_module(void) { unregister_jprobe(&my_jprobe); printk("jprobe unregistered\n"); }
MODULE_LICENSE("GPL");
Linux内核调试方法总结之Jprobes的更多相关文章
- Linux内核调试方法总结
Linux内核调试方法总结 一 调试前的准备 二 内核中的bug 三 内核调试配置选项 1 内核配置 2 调试原子操作 四 引发bug并打印信息 1 BUG()和BUG_ON() 2 ...
- Linux内核调试方法总结【转】
转自:http://my.oschina.net/fgq611/blog/113249 内核开发比用户空间开发更难的一个因素就是内核调试艰难.内核错误往往会导致系统宕机,很难保留出错时的现场.调试内核 ...
- 【转】Linux内核调试方法总结
目录[-] 一 调试前的准备 二 内核中的bug 三 内核调试配置选项 1 内核配置 2 调试原子操作 四 引发bug并打印信息 1 BUG()和BUG_ON() 2 dump_sta ...
- Linux内核调试方法【转】
转自:http://www.cnblogs.com/shineshqw/articles/2359114.html kdb:只能在汇编代码级进行调试: 优点是不需要两台机器进行调试. gdb:在调试模 ...
- Linux内核调试方法总结之反汇编
Linux反汇编调试方法 Linux内核模块或者应用程序经常因为各种各样的原因而崩溃,一般情况下都会打印函数调用栈信息,那么,这种情况下,我们怎么去定位问题呢?本文档介绍了一种反汇编的方法辅助定位此类 ...
- Linux内核调试方法总结之栈帧
栈帧 栈帧和指针可以说是C语言的精髓.栈帧是一种特殊的数据结构,在C语言函数调用时,栈帧用来保存当前函数的父一级函数的栈底指针,当前函数的局部变量以及被调用函数返回后下一条汇编指令的地址.如下图所示: ...
- Linux内核调试方法总结之序言
本系列主要介绍Linux内核死机.异常重启类稳定性问题的调试方法. 在Linux系统中,一切皆为文件,而系统运行的载体,是一类特殊的文件,即进程.因此,我尝试从进程的角度分析Linux内核的死机.异常 ...
- Linux内核调试方法总结之ddebug
[用途] Linux内核动态调试特性,适用于驱动和内核各子系统调试.动态调试的主要功能就是允许你动态的打开或者关闭内核代码中的各种提示信息.适用于驱动和内核线程功能调试. [使用方法] 依赖于CONF ...
- Linux内核调试方法总结之调试宏
本文介绍的内核调试宏属于静态调试方法,通过调试宏主动触发oops从而打印出函数调用栈信息. 1) BUG_ON 查看bug处堆栈内容,主动制造oops Linux中BUG_ON,WARN_ON用于调试 ...
随机推荐
- Spring如何读取xml配置文件的
我们通过一个小案例来看xml解析过程. 1. 导包 <dependencies> <!-- xml解析工具 --> <dependency> <groupId ...
- 检验Excel中数据是否与数据库中数据重复
#region 记录Excel中的重复列 /// <summary> /// 记录Excel中的重复列 /// </summary> /// <param name=&q ...
- ThinkPHP视图css和js加上版本号防止缓存
前台模块中,我的所有控制器都继承BaseController,虽然ThinkPHP中我们提供了两个配置项 'TMPL_CACHE_ON' => false,// 禁止模板编译缓存 'HTML_C ...
- Ionic创建混合App(二)
ionic 2 启动应用进入欢迎引导页 1.首先,使用CLI命令,创建引导页面 ionic g page welcome 2.需改welcome.html模板文件 <ion-slides pag ...
- nmblookup - 基于TCP/IP上的NetBIOS客户用于查询NetBIOS名字的程序
总览 SYNOPSIS nmblookup [-M] [-R] [-S] [-r] [-A] [-h] [-B <broadcast address>] [-U <unicast a ...
- macOS安装wget
brew install wget 或者 curl -O http://ftp.gnu.org/gnu/wget/wget-1.13.4.tar.gz tar xzvf wget-1.13.4.tar ...
- Mixly-指令
串口: 向串口监视器输出数据 十进制 Serial.println(ir_item,HEX); 向串口监视器输出数据---十六进制 通信: 接收11脚的红外信号,把接收到的数据 ...
- 封装storage
export const local = { getItem(key) { let value = localStorage.getItem(key) if (/^\{.*\}$/.test(valu ...
- js 文件下载 兼容ie
前置条件:后台接口返回二进制流文件 一.设置前端请求的的 responseType: 'blob' 二.接收请求数据并调用下载 var content = res.data // 接口返回的二进制流v ...
- 从1G到5G,移动通信发展之路
2G取代1G是历史的必然,诺基亚是2G时代的领航者. 3G是个“半吊子”系统,2G手机只能打电话.发短信,上网很困难.3G的通信标准将信息的传输率提高了一个数量级,这是一个飞跃,它使得移动互联网得以实 ...