Linux内核调试方法总结之Kprobes
Kprobes
【用途】【参考kernel/Documentation/kprobes.txt帮助文档】
Kprobes是一个轻量级内核调试工具,同时又是其他一些更高级的内核调试工具(如perf和systemtap)的基础,在Linux 4.0内核版本中,eBPF特性也寄生于kprobe之上。
【原理】
Kprobes的主要作用是在指定函数调用前后添加自定义函数,从而实现动态探测点的功能。
Kprobes有两种使用方法:1)模块加载;2)通过debugfs操作。
【接口说明】【参考kernel/sample/kprobes】
关键结构体
#include <linux/kprobes.h>
struct kprobe {
kprobe_opcode_t *addr; /* Location of the probe point */
const char *symbol_name; /* Allow user to indicate symbol name of the probe point */
kprobe_pre_handler_t pre_handler; /* Called before addr is executed */
kprobe_pre_handler_t post_handler; /* Called after addr is executed */
kprobe_pre_handler_t fault_handler; /* Called if executing addr caused a fault */
};
注册kprobes探测点
int register_kprobe(struct kprobe *p);
注销kprobes探测点
void unregister_kprobe(struct kprobe *p);
【实例】
/*
* NOTE: This example is works on x86 and powerpc.
* Here's a sample kernel module showing the use of kprobes to dump a
* stack trace and selected registers when do_fork() is called.
* * For more information on theory of operation of kprobes, see
* Documentation/kprobes.txt
* * You will see the trace data in /var/log/messages and on the console
* whenever do_fork() is invoked to create a new process.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
/* For each probe you need to allocate a kprobe structure */
static struct kprobe kp = {
.symbol_name = "do_fork",
};
/* kprobe pre_handler: called just before the probed instruction is executed */
static int handler_pre(struct kprobe *p, struct pt_regs *regs) {
#ifdef CONFIG_X86
printk(KERN_INFO "pre_handler: p->addr = 0x%p, ip = %lx," " flags = 0x%lx\r\n", p->addr, regs->ip, regs->flags);
#endif
#ifdef CONFIG_PPC
printk(KERN_INFO "pre_handler: p->addr = 0x%p, nip = 0x%lx," " msr = 0x%lx\r\n", p->addr, regs->nip, regs->msr);
#endif
#ifdef CONFIG_MIPS
printk(KERN_INFO "pre_handler: p->addr = 0x%p, epc = 0x%lx," " status = 0x%lx\r\n", p->addr, regs->cp0_epc, regs->cp0_status);
#endif
/* A dump_stack() here will give a stack backtrace */
return 0;
}
/* kprobe post_handler: called after the probed instruction is executed */
static void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags) {
#ifdef CONFIG_X86
printk(KERN_INFO "post_handler: p->addr = 0x%p, flags = 0x%lx\r\n", p->addr, regs->flags);
#endif
#ifdef CONFIG_PPC
printk(KERN_INFO "post_handler: p->addr = 0x%p, msr = 0x%lx\r\n", p->addr, regs->msr);
#endif
#ifdef CONFIG_MIPS
printk(KERN_INFO "post_handler: p->addr = 0x%p, status = 0x%lx\r\n", p->addr, regs->cp0_status);
#endif
}
/*
* fault_handler: this is called if an exception is generated for any
* instruction within the pre- or post-handler, or when Kprobes
* single-steps the probed instruction.
*/
static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr) {
printk(KERN_INFO "fault_handler: p->addr = 0x%p, trap #%dn", p->addr, trapnr);
/* Return 0 because we don't handle the fault. */
return 0;
}
static int __init kprobe_init(void) {
int ret;
kp.pre_handler = handler_pre;
kp.post_handler = handler_post;
kp.fault_handler = handler_fault;
ret = register_kprobe(&kp);
if (ret < 0) {
printk(KERN_INFO "register_kprobe failed, returned %d\r\n", ret);
return ret;
}
printk(KERN_INFO "Planted kprobe at %p\r\n", kp.addr);
return 0;
}
static void __exit kprobe_exit(void) {
unregister_kprobe(&kp);
printk(KERN_INFO "kprobe at %p unregistered\r\n", kp.addr);
}
module_init(kprobe_init) module_exit(kprobe_exit) MODULE_LICENSE("GPL");
Linux内核调试方法总结之Kprobes的更多相关文章
- 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用于调试 ...
随机推荐
- SSM框架之AOP、动态代理、事务处理相关随笔
AOP: 原理:底层利用动态代理(两种动态代理技术都使用了) 两种实现方案: 第一种:JDK动态代理技术 实现的InvocationHandler接口,要想实现某个类的动态代理对象,必须有接口有实现类 ...
- qtreewidget 显示保存xml文件
此文是读取和存储已知结构的xml,对于未知结构的xml,可以用递归方法读取和遍历.可参考文章:Qt遍历不规则树的节点. 1.QTreewidget设置 //折叠图标(三角图标)换成自定义图标 ui-& ...
- 一些DP上的奇奇怪怪的东西
单调队列&单调栈: 有手就行.jpg 四边形不等式: 若\(w(i,j)\)满足\(\forall a\le b<c\le d,w(a,c)+w(b,d)\le w(b,c)+w(a,d ...
- Codeforces 1262E Arson In Berland Forest(二维前缀和+二维差分+二分)
题意是需要求最大的扩散时间,最后输出的是一开始的火源点,那么我们比较容易想到的是二分找最大值,但是我们在这满足这样的点的时候可以发现,在当前扩散时间k下,以这个点为中心的(2k+1)2的正方形块内必 ...
- 在centos6.4下安装python3.5
1.安装依赖包 ./configure --prefix=/usr/local/python3.5 --enable-shared make && make install yum g ...
- 【学习总结】快速上手Linux玩转典型应用-第3章-CentOS的安装
课程目录链接 快速上手Linux玩转典型应用-目录 目录 1. 虚拟机是什么 2. 在虚拟机中安装CentOS 3. 云服务器介绍 ================================== ...
- 【React 8/100】 React路由
React路由 React路由介绍 现代的前端应用大多数是SPA(单页应用程序),也就是只有一个HTML页面的应用程序.因为它的用户体验更好.对服务器压力更小,所以更受欢迎.为了有效的使用单个页面来管 ...
- javaweb新手学习之Tomcat
一.Tomcat服务器常见启动问题: (1).Java_home环境变量,由于tomcat服务器的bin目录中的一些jar文件必须使用到java类库,所以必须先配置Java_home环境变量. (2) ...
- http参数传递方式
url传参 这种在各种method(get,post,delete,put)都能使用,解析速度快 body体中的参数 application/x-www-form-urlencoded 这应该是最常见 ...
- JavaEE高级-Maven学习笔记
Maven简介 1.Maven是一款服务于Java平台的自动化构建工具. 2.构建: - 概念:以“Java源文件”.“框架配置文件”.“JSP”.“HTML”.“图片”等资源为“原料”,去“生产”一 ...