调试代码大部分都是真的代码行进行运行时调式,可是有时候我们想知道某个变量的变化情况,对于庞大的代码,对每一个读写该变量的位置进行log不太现实,鉴于该问题x86体系就提出了hwbp机制,linux也整合了该机制。
代码说明一切:
-
#include <linux/module.h> /* Needed by all modules */^M
-
#include <linux/kernel.h> /* Needed for KERN_INFO */^M
-
#include <linux/init.h> /* Needed for the macros */^M
-
#include <linux/kallsyms.h>^M
-
^M
-
#include <linux/perf_event.h>^M
-
#include <linux/hw_breakpoint.h>^M
-
#include <asm/rwsem.h>^M
-
struct perf_event * __percpu *sample_hbp;^M
-
^M
-
/*static char ksym_name[KSYM_NAME_LEN] = "pid_max";^M
-
module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);^M
-
MODULE_PARM_DESC(ksym, "Kernel symbol to monitor; this module will report any"^M
-
" write operations on the kernel symbol");^M
-
*/^M
-
static int pid=0;^M
-
static struct task_struct *gtsk=NULL;^M
-
module_param(pid,int,S_IRUGO);^M
-
MODULE_PARM_DESC(pid,"pid of process to monitor mm rwsem");^M
-
^M
-
enum rwsem_waiter_type {^M
-
RWSEM_WAITING_FOR_WRITE,^M
-
RWSEM_WAITING_FOR_READ^M
-
};^M
-
^M
-
struct rwsem_waiter {^M
-
struct list_head list;^M
-
struct task_struct *task;^M
-
enum rwsem_waiter_type type;^M
-
};^M
-
^M
-
static void sample_hbp_handler(struct perf_event *bp,^M
-
struct perf_sample_data *data,^M
-
struct pt_regs *regs)^M
-
{^M
-
printk(KERN_INFO " value is changed\n");^M
-
dump_stack();^M
-
printk(KERN_INFO "Dump stack from sample_hbp_handler\n");^M
-
struct rwsem_waiter *waiter;^M
-
if (list_empty(&(gtsk->mm->mmap_sem.wait_list)))^M
-
printk(KERN_INFO "sem list empty");^M
-
list_for_each_entry(waiter,&(gtsk->mm->mmap_sem.wait_list),list)^M
-
printk(KERN_INFO "sem list pid %d",waiter->task->pid);^M
-
}^M
-
^M
-
static int __init hw_break_module_init(void)^M
-
{^M
-
int ret = 0;^M
-
struct perf_event_attr attr;^M
-
^M
-
struct task_struct *tsk = NULL;^M
-
for_each_process(tsk)^M
-
{^M
-
if (tsk->pid == pid)^M
-
{^M
-
gtsk = tsk;^M
-
break;^M
-
}^M
-
}^M
-
if (tsk == &init_task)^M
-
goto fail;^M
-
^M
-
hw_breakpoint_init(&attr);^M
-
/*attr.bp_addr = kallsyms_lookup_name(ksym_name);*/
-
attr.bp_addr = (__u64)&(tsk->mm->mmap_sem.count);
-
printk("addr of data is %p",&(tsk->mm->mmap_sem.count));
-
attr.bp_len = HW_BREAKPOINT_LEN_4;^M
-
attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
-
^M
-
sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler, NULL);
-
if (IS_ERR((void __force *)sample_hbp)) {
-
ret = PTR_ERR((void __force *)sample_hbp);
-
goto fail;^M
-
}^M
-
^M
-
printk(KERN_INFO "HW Breakpoint for rwsem write installed\n");^M
-
^M
-
return 0;^M
-
^M
-
fail:^M
-
printk(KERN_INFO "Breakpoint registration failed\n");^M
-
^M
-
return ret;^M
-
}^M
-
^M
-
static void __exit hw_break_module_exit(void)^M
-
{^M
-
unregister_wide_hw_breakpoint(sample_hbp);^M
-
printk(KERN_INFO "HW Breakpoint for rwsem %d write uninstalled\n", pid);^M
-
}^M
-
^M
-
module_init(hw_break_module_init);^M
-
module_exit(hw_break_module_exit);^M
-
^M
-
MODULE_LICENSE("GPL");^M
-
MODULE_AUTHOR("K.Prasad");^M
-
MODULE_DESCRIPTION("ksym breakpoint");
阅读(6529) | 评论(0) | 转发(0) |