kernel debug tools...

This commit is contained in:
gatieme
2017-03-30 13:07:38 +08:00
parent 62b53701c3
commit 94b32eff7c
57 changed files with 108 additions and 0 deletions
@@ -0,0 +1,78 @@
# ------------------------------------------------------------------------------
#
# Makefile for the LDD-LinuxDeviceDrivers.
#
# Author: gatieme
# Create: 2016-07-29 15:50:46
# Last modified: 2016-07-29 16:10:29
# Description:
# This program is loaded as a kernel(v2.6.18 or later) module.
# Use "make install" to load it into kernel.
# Use "make remove" to remove the module out of kernel.
#
# ------------------------------------------------------------------------------
ROOT=..
#PLATFORM=$(shell $(ROOT)/systype.sh)
#include $(ROOT)/Make.defines.$(PLATFORM)
# my driver description
DRIVER_VERSION := "1.0.0"
DRIVER_AUTHOR := "Gatieme @ AderStep Inc..."
DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices"
DRIVER_LICENSE := "Dual BSD/GPL"
MODULE_NAME := test
ifneq ($(KERNELRELEASE),)
#CFG_FLAGS += -O2 -I./
#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC)
obj-m := $(MODULE_NAME).o #print_vmarea.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
make -C $(KERNELDIR) M=$(PWD) modules
modules_install:
make -C $(KERNELDIR) M=$(PWD) modules_install
insmod:
sudo insmod $(MODULE_NAME).ko
reinsmod:
sudo rmmod $(MODULE_NAME)
sudo insmod $(MODULE_NAME).ko
github:
cd $(ROOT) && make github
rmmod:
sudo rmmod $(MODULE_NAME)
test :
sudo ../injector/memInjector -l stack -m random -t word_0 --time 1 --timeout 3 -p 1
clean:
make -C $(KERNELDIR) M=$(PWD) clean
rm -f modules.order Module.symvers Module.markers
.PHNOY:
modules modules_install clean
endif
@@ -0,0 +1,78 @@
# ------------------------------------------------------------------------------
#
# Makefile for the LDD-LinuxDeviceDrivers.
#
# Author: gatieme
# Create: 2016-07-29 15:50:46
# Last modified: 2016-07-29 16:10:29
# Description:
# This program is loaded as a kernel(v2.6.18 or later) module.
# Use "make install" to load it into kernel.
# Use "make remove" to remove the module out of kernel.
#
# ------------------------------------------------------------------------------
ROOT=..
#PLATFORM=$(shell $(ROOT)/systype.sh)
#include $(ROOT)/Make.defines.$(PLATFORM)
# my driver description
DRIVER_VERSION := "1.0.0"
DRIVER_AUTHOR := "Gatieme @ AderStep Inc..."
DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices"
DRIVER_LICENSE := "Dual BSD/GPL"
MODULE_NAME := data_breakpoint
ifneq ($(KERNELRELEASE),)
#CFG_FLAGS += -O2 -I./
#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC)
obj-m := $(MODULE_NAME).o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
make -C $(KERNELDIR) M=$(PWD) modules
modules_install:
make -C $(KERNELDIR) M=$(PWD) modules_install
insmod:
sudo insmod $(MODULE_NAME).ko
reinsmod:
sudo rmmod $(MODULE_NAME)
sudo insmod $(MODULE_NAME).ko
github:
cd $(ROOT) && make github
rmmod:
sudo rmmod $(MODULE_NAME)
test :
sudo ../injector/memInjector -l stack -m random -t word_0 --time 1 --timeout 3 -p 1
clean:
make -C $(KERNELDIR) M=$(PWD) clean
rm -f modules.order Module.symvers Module.markers
.PHNOY:
modules modules_install clean
endif
@@ -0,0 +1,92 @@
/*
* data_breakpoint.c - Sample HW Breakpoint file to watch kernel data address
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* usage: insmod data_breakpoint.ko ksym=<ksym_name>
*
* This file is a kernel module that places a breakpoint over ksym_name kernel
* variable using Hardware Breakpoint register. The corresponding handler which
* prints a backtrace is invoked every time a write operation is performed on
* that variable.
*
* Copyright (C) IBM Corporation, 2009
*
* Author: K.Prasad <prasad@linux.vnet.ibm.com>
*/
// http://lxr.free-electrons.com/source/samples/hw_breakpoint/data_breakpoint.c
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/kallsyms.h>
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>
struct perf_event * __percpu *sample_hbp;
static char ksym_name[KSYM_NAME_LEN] = "pid_max";
module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);
MODULE_PARM_DESC(ksym, "Kernel symbol to monitor; this module will report any"
" write operations on the kernel symbol");
static void sample_hbp_handler(struct perf_event *bp,
struct perf_sample_data *data,
struct pt_regs *regs)
{
printk(KERN_INFO "%s value is changed\n", ksym_name);
dump_stack();
printk(KERN_INFO "Dump stack from sample_hbp_handler\n");
}
static int __init hw_break_module_init(void)
{
int ret;
struct perf_event_attr attr;
hw_breakpoint_init(&attr);
attr.bp_addr = kallsyms_lookup_name(ksym_name);
attr.bp_len = HW_BREAKPOINT_LEN_4;
attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
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;
}
printk(KERN_INFO "HW Breakpoint for %s write installed\n", ksym_name);
return 0;
fail:
printk(KERN_INFO "Breakpoint registration failed\n");
return ret;
}
static void __exit hw_break_module_exit(void)
{
unregister_wide_hw_breakpoint(sample_hbp);
printk(KERN_INFO "HW Breakpoint for %s write uninstalled\n", ksym_name);
}
module_init(hw_break_module_init);
module_exit(hw_break_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("K.Prasad");
MODULE_DESCRIPTION("ksym breakpoint");
@@ -0,0 +1,78 @@
# ------------------------------------------------------------------------------
#
# Makefile for the LDD-LinuxDeviceDrivers.
#
# Author: gatieme
# Create: 2016-07-29 15:50:46
# Last modified: 2016-07-29 16:10:29
# Description:
# This program is loaded as a kernel(v2.6.18 or later) module.
# Use "make install" to load it into kernel.
# Use "make remove" to remove the module out of kernel.
#
# ------------------------------------------------------------------------------
ROOT=..
#PLATFORM=$(shell $(ROOT)/systype.sh)
#include $(ROOT)/Make.defines.$(PLATFORM)
# my driver description
DRIVER_VERSION := "1.0.0"
DRIVER_AUTHOR := "Gatieme @ AderStep Inc..."
DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices"
DRIVER_LICENSE := "Dual BSD/GPL"
MODULE_NAME := jprobe-exam
ifneq ($(KERNELRELEASE),)
#CFG_FLAGS += -O2 -I./
#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC)
obj-m := $(MODULE_NAME).o #print_vmarea.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
make -C $(KERNELDIR) M=$(PWD) modules
modules_install:
make -C $(KERNELDIR) M=$(PWD) modules_install
insmod:
sudo insmod $(MODULE_NAME).ko
reinsmod:
sudo rmmod $(MODULE_NAME)
sudo insmod $(MODULE_NAME).ko
github:
cd $(ROOT) && make github
rmmod:
sudo rmmod $(MODULE_NAME)
test :
sudo ../injector/memInjector -l stack -m random -t word_0 --time 1 --timeout 3 -p 1
clean:
make -C $(KERNELDIR) M=$(PWD) clean
rm -f modules.order Module.symvers Module.markers
.PHNOY:
modules modules_install clean
endif
@@ -0,0 +1,57 @@
/* jprobe-exam.c */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
static struct jprobe jp;
asmlinkage long jprobe_sys_open(const char __user *filename, int flags, int mode)
{
int len = PATH_MAX;
char * tmpfilename = NULL;
if (TASK_SIZE - (unsigned long) filename < PATH_MAX) {
len = TASK_SIZE - (unsigned long) filename;
}
tmpfilename = kmalloc(len, GFP_ATOMIC);
if (tmpfilename == NULL) return 0;
if (copy_from_user(tmpfilename, filename, len)) return 0;
printk("process '%s' call open('%s', %d, %d)\n", current->comm, tmpfilename, flags, mode);
jprobe_return();
return 0;
}
int init_module(void)
{
int ret;
jp.entry = (kprobe_opcode_t *) jprobe_sys_open;
jp.kp.addr = (kprobe_opcode_t *)kallsyms_lookup_name("sys_open");
if (!jp.kp.addr) {
printk("Couldn't find the address of sys_open\n");
return -1;
}
if ((ret = register_jprobe(&jp)) <0) {
printk("register_jprobe failed, returned %d\n", ret);
return -1;
}
printk("Registered a jprobe.\n");
return 0;
}
void cleanup_module(void)
{
unregister_jprobe(&jp);
printk("jprobe unregistered\n");
}
MODULE_LICENSE("GPL");
@@ -0,0 +1,78 @@
# ------------------------------------------------------------------------------
#
# Makefile for the LDD-LinuxDeviceDrivers.
#
# Author: gatieme
# Create: 2016-07-29 15:50:46
# Last modified: 2016-07-29 16:10:29
# Description:
# This program is loaded as a kernel(v2.6.18 or later) module.
# Use "make install" to load it into kernel.
# Use "make remove" to remove the module out of kernel.
#
# ------------------------------------------------------------------------------
ROOT=..
#PLATFORM=$(shell $(ROOT)/systype.sh)
#include $(ROOT)/Make.defines.$(PLATFORM)
# my driver description
DRIVER_VERSION := "1.0.0"
DRIVER_AUTHOR := "Gatieme @ AderStep Inc..."
DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices"
DRIVER_LICENSE := "Dual BSD/GPL"
MODULE_NAME := kprobe-exam
ifneq ($(KERNELRELEASE),)
#CFG_FLAGS += -O2 -I./
#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC)
obj-m := $(MODULE_NAME).o #print_vmarea.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
make -C $(KERNELDIR) M=$(PWD) modules
modules_install:
make -C $(KERNELDIR) M=$(PWD) modules_install
insmod:
sudo insmod $(MODULE_NAME).ko
reinsmod:
sudo rmmod $(MODULE_NAME)
sudo insmod $(MODULE_NAME).ko
github:
cd $(ROOT) && make github
rmmod:
sudo rmmod $(MODULE_NAME)
test :
sudo ../injector/memInjector -l stack -m random -t word_0 --time 1 --timeout 3 -p 1
clean:
make -C $(KERNELDIR) M=$(PWD) clean
rm -f modules.order Module.symvers Module.markers
.PHNOY:
modules modules_install clean
endif
@@ -0,0 +1,87 @@
https://www.ibm.com/developerworks/cn/linux/l-cn-systemtap1/
kprobe使用实例
本文附带的包包含了三个示例模块,kprobe-exam.c是kprobes使用示例,jprobe-exam.c是jprobes使用示例,kretprobe-exam.c是kretprobes使用示例,读者可以下载该包并执行如下指令来实验这些模块:
$ tar -jxvf kprobes-examples.tar.bz2
$ cd kprobes-examples
$ make
…
$ su -
…
$ insmod kprobe-example.ko
$ dmesg
…
$ rmmod kprobe-example
$ dmesg
…
$ insmod jprobe-example.ko
$ cat kprobe-example.c
$dmesg
…
$ rmmod jprobe-example
$ dmesg
…
$ insmod kretprobe-example.ko
$ dmesg
…
$ ls -Rla / > /dev/null &
$ dmesg
…
$ rmmod kretprobe-example
$ dmesg
…
$
示例模块kprobe-exame.c探测schedule()函数,在探测点执行前后分别输出当前正在运行的进程、所在的CPU以及preempt_count(),当卸载该模块时将输出该模块运行时间以及发生的调度次数。这是该模块在作者系统上的输出:
kprobe registered
current task on CPU#1: swapper (before scheduling), preempt_count = 0
current task on CPU#1: swapper (after scheduling), preempt_count = 0
current task on CPU#0: insmod (before scheduling), preempt_count = 0
current task on CPU#0: insmod (after scheduling), preempt_count = 0
current task on CPU#1: klogd (before scheduling), preempt_count = 0
current task on CPU#1: klogd (after scheduling), preempt_count = 0
current task on CPU#1: klogd (before scheduling), preempt_count = 0
current task on CPU#1: klogd (after scheduling), preempt_count = 0
current task on CPU#1: klogd (before scheduling), preempt_count = 0
…
Scheduling times is 5918 during of 7655 milliseconds.
kprobe unregistered
示例模块jprobe-exam.c是一个jprobes探测例子,它示例了获取系统调用open的参数,但读者不要试图在实际的应用中这么使用,因为copy_from_user可能导致睡眠,而kprobe并不允许在探测点处理函数中这么做(请参看前面内容了解详细描述)。
这是该模块在作者系统上的输出:
Registered a jprobe.
process 'cat' call open('/etc/ld.so.cache', 0, 0)
process 'cat' call open('/lib/libc.so.6', 0, -524289)
process 'cat' call open('/usr/lib/locale/locale-archive', 32768, 1)
process 'cat' call open('/usr/share/locale/locale.alias', 0, 438)
process 'cat' call open('/usr/lib/locale/en_US.UTF-8/LC_CTYPE', 0, 0)
process 'cat' call open('/usr/lib/locale/en_US.utf8/LC_CTYPE', 0, 0)
process 'cat' call open('/usr/lib/gconv/gconv-modules.cache', 0, 0)
process 'cat' call open('kprobe-exam.c', 32768, 0)
…
process 'rmmod' call open('/etc/ld.so.cache', 0, 0)
process 'rmmod' call open('/lib/libc.so.6', 0, -524289)
process 'rmmod' call open('/proc/modules', 0, 438)
jprobe unregistered
示例模块kretprobe-exam.c是一个返回探测例子,它探测系统调用open并输出返回值小于0的情况。它也有意设置maxactive为1,以便示例丢失探测运行的情况,当然,只有系统并发运行多个sys_open才可能导致这种情况,因此,读者需要有SMP的系统或者有超线程支持才能看到这种情况。如果读者比较仔细,会看到在前面的命令有”ls -Rla / > /dev/null & ,那是专门为了导致出现丢失探测运行的。
这是该模块在作者系统上的输出:
Registered a return probe.
sys_open returns -2
sys_open returns -2
sys_open returns -2
sys_open returns -2
sys_open returns -2
sys_open returns -2
sys_open returns -2
sys_open returns -2
sys_open returns -2
sys_open returns -2
sys_open returns -2
sys_open returns -2
…
kretprobe unregistered
Missed 11 sys_open probe instances.
回页首
小结
本文详细地讲解了kprobe的方方面面并给出实际的例子代码帮助读者学习和使用kprobe。本文是系列文章“Linux下的一个全新的性能测量和调式诊断工具 -- Systemtap”之一,有兴趣的读者可以阅读该系列文章之二和三。
@@ -0,0 +1,73 @@
/* kprobe-exam.c */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
#include <linux/sched.h>
#include <linux/time.h>
static struct kprobe kp;
static struct timeval start, end;
static int schedule_counter = 0;
int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
printk("current task on CPU#%d: %s (before scheduling), preempt_count = %d\n", smp_processor_id(), current->comm, preempt_count());
schedule_counter++;
return 0;
}
void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
{
printk("current task on CPU#%d: %s (after scheduling), preempt_count = %d\n", smp_processor_id(), current->comm, preempt_count());
}
int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
{
printk("A fault happened during probing.\n");
return 0;
}
int init_module(void)
{
int ret;
kp.pre_handler = handler_pre;
kp.post_handler = handler_post;
kp.fault_handler = handler_fault;
kp.addr = (kprobe_opcode_t*) kallsyms_lookup_name("schedule");
if (kp.addr == NULL)
{
printk("Couldn't get the address of schedule.\n");
return -1;
}
if ((ret = register_kprobe(&kp) < 0))
{
printk("register_kprobe failed, returned %d\n", ret);
return -1;
}
do_gettimeofday(&start);
printk("kprobe registered\n");
return 0;
}
void cleanup_module(void)
{
unregister_kprobe(&kp);
do_gettimeofday(&end);
printk("Scheduling times is %d during of %ld milliseconds.\n", schedule_counter, ((end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec))/1000);
printk("kprobe unregistered\n");
}
MODULE_LICENSE("GPL");
@@ -0,0 +1,18 @@
ifneq ($(KERNELRELEASE),)
obj-m := kretprobe-exam.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
endif
@@ -0,0 +1,48 @@
/*kretprobe-exam.c*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
static struct kretprobe kretp;
static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
// Substitute the appropriate register name for your architecture --
// e.g., regs->rax for x86_64, regs->gpr[3] for ppc64.
int retval = (int) regs->ax;
if (retval < 0) {
printk("sys_open returns %d\n", retval);
}
return 0;
}
int init_module(void)
{
int ret;
kretp.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("sys_open");
if (!kretp.kp.addr) {
printk("Couldn't find sys_open.\n");
return -1;
}
kretp.handler = ret_handler,
kretp.maxactive = 1;
if ((ret = register_kretprobe(&kretp)) < 0) {
printk("register_kretprobe failed, returned %d\n", ret);
return -1;
}
printk("Registered a return probe.\n");
return 0;
}
void cleanup_module(void)
{
unregister_kretprobe(&kretp);
printk("kretprobe unregistered\n");
printk("Missed %d sys_open probe instances.\n", kretp.nmissed);
}
MODULE_LICENSE("GPL");
+115
View File
@@ -0,0 +1,115 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
printk("current task on CPU#%d: %s (before), preempt_count = %d\n",
smp_processor_id( ), current->comm, preempt_count( ));
return 0;
}
void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
{
printk("current task on CPU#%d: %s (after), preempt_count = %d\n",
smp_processor_id( ), current->comm, preempt_count( ));
}
int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
{
printk("A fault happened during probing.\n");
return 0;
}
/*
* 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 */
static 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(KERN_INFO "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( );
return 0;
}
asmlinkage __visible void __sched jschedule(void)
{
/* Always end with a call to jprobe_return(). */
jprobe_return( );
//return 0;
}
static struct jprobe my_jprobe = {
.entry = jdo_fork,
/* 注意 symbol_name与addr不能同时存在
* 参见kprobe_addr函数--http://lxr.free-electrons.com/source/kernel/kprobes.c#L1359
* 否则会提示参数错误ERR_PTR(-EINVAL);
* 内核中errno的值在http://lxr.free-electrons.com/source/include/uapi/asm-generic/errno-base.h#L25
* */
.kp = {
.symbol_name = "_do_fork",
//.addr
.pre_handler = handler_pre,
.post_handler = handler_post,
.fault_handler = handler_fault,
},
};
static int __init jprobe_init(void)
{
int ret;
//my_jprobe.kp.symbol_name = "_do_fork";
//my_jprobe.kp.addr = kallsyms_lookup_name("_do_fork");
#if 0
my_jprobe.kp.pre_handler = handler_pre;
my_jprobe.kp.post_handler = handler_post;
my_jprobe.kp.fault_handler = handler_fault;
#endif
if(my_jprobe.kp.symbol_name == NULL)
{
my_jprobe.kp.addr = (kprobe_opcode_t *)kallsyms_lookup_name("_do_fork");
printk("find _do_fork address at 0x%p\n", my_jprobe.kp.addr);
}
ret = register_jprobe(&my_jprobe);
if (ret < 0) {
printk(KERN_INFO "register_jprobe failed, returned %d\n", ret);
return -1;
}
printk(KERN_INFO "Planted jprobe at %p, handler addr %p\n",
my_jprobe.kp.addr, my_jprobe.entry);
return 0;
}
static void __exit jprobe_exit(void)
{
unregister_jprobe(&my_jprobe);
printk(KERN_INFO "jprobe at %p unregistered\n", my_jprobe.kp.addr);
}
module_init(jprobe_init)
module_exit(jprobe_exit)
MODULE_LICENSE("GPL");
@@ -0,0 +1,100 @@
/*
* 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\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\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\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\n",
p->addr, regs->flags);
#endif
#ifdef CONFIG_PPC
printk(KERN_INFO "post_handler: p->addr = 0x%p, msr = 0x%lx\n",
p->addr, regs->msr);
#endif
#ifdef CONFIG_MIPS
printk(KERN_INFO "post_handler: p->addr = 0x%p, status = 0x%lx\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\n", ret);
return ret;
}
printk(KERN_INFO "Planted kprobe at %p\n", kp.addr);
return 0;
}
static void __exit kprobe_exit(void)
{
unregister_kprobe(&kp);
printk(KERN_INFO "kprobe at %p unregistered\n", kp.addr);
}
module_init(kprobe_init)
module_exit(kprobe_exit)
MODULE_LICENSE("GPL");
@@ -0,0 +1,76 @@
# ------------------------------------------------------------------------------
#
# Makefile for the LDD-LinuxDeviceDrivers.
#
# Author: gatieme
# Create: 2016-07-29 15:50:46
# Last modified: 2016-07-29 16:10:29
# Description:
# This program is loaded as a kernel(v2.6.18 or later) module.
# Use "make install" to load it into kernel.
# Use "make remove" to remove the module out of kernel.
#
# ------------------------------------------------------------------------------
# my driver description
DRIVER_VERSION := "1.0.0"
DRIVER_AUTHOR := "Gatieme @ AderStep Inc..."
DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices"
DRIVER_LICENSE := "Dual BSD/GPL"
MODULE_NAME := ftrace_demo
MODCFLAGS:=-O6 -Wall -DMODULE -D__KERNEL__ -DLINUX -std=c99
ifneq ($(KERNELRELEASE),)
#CFG_FLAGS += -O2 -I./
#EXTRA_CFLAGS += $(C_FLAGS) $(CFG_INC) $(CFG_INC)
obj-m := $(MODULE_NAME).o #print_vmarea.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
make -C $(KERNELDIR) M=$(PWD) modules
modules_install:
make -C $(KERNELDIR) M=$(PWD) modules_install
insmod:
sudo insmod $(MODULE_NAME).ko
reinsmod:
sudo rmmod $(MODULE_NAME)
sudo insmod $(MODULE_NAME).ko
github:
cd $(ROOT) && make github
rmmod:
sudo rmmod $(MODULE_NAME)
test :
sudo ../injector/memInjector -l stack -m random -t word_0 --time 1 --timeout 3 -p 1
clean:
make -C $(KERNELDIR) M=$(PWD) clean
rm -f modules.order Module.symvers Module.markers
.PHNOY:
modules modules_install clean
endif
@@ -0,0 +1,24 @@
/*
* ftrace_demo.c
* http://www.ibm.com/developerworks/cn/linux/l-cn-ftrace3/
* http://lxr.free-electrons.com/source/include/trace/events/context_tracking.h 貌似没实现
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
static int ftrace_demo_init(void)
{
trace_printk("Can not see this in trace unless loaded for the second time\n");
return 0;
}
static void ftrace_demo_exit(void)
{
trace_printk("Module unloading\n");
}
module_init(ftrace_demo_init);
module_exit(ftrace_demo_exit);
@@ -0,0 +1,81 @@
# ------------------------------------------------------------------------------
#
# Makefile for the LDD-LinuxDeviceDrivers.
#
# Author: gatieme
# Create: 2016-07-29 15:50:46
# Last modified: 2016-07-29 16:10:29
# Description:
# This program is loaded as a kernel(v2.6.18 or later) module.
# Use "make install" to load it into kernel.
# Use "make remove" to remove the module out of kernel.
#
# ------------------------------------------------------------------------------
# my driver description
DRIVER_VERSION := "1.0.0"
DRIVER_AUTHOR := "Gatieme @ AderStep Inc..."
DRIVER_DESC := "Linux input module for Elo MultiTouch(MT) devices"
DRIVER_LICENSE := "Dual BSD/GPL"
MODULE_NAME := trace-events-sample
#MODCFLAGS:=-O2 -Wall -DMODULE -D__KERNEL__ -DLINUX -std=c99
SRC := /home/gatieme/Work/GitHub/LDD-LinuxDeviceDrivers/study/debug/trace/trace-events-sample
EXTRA_CFLAGS += -I$(SRC)
ifneq ($(KERNELRELEASE),)
obj-m := $(MODULE_NAME).o #print_vmarea.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
make -C $(KERNELDIR) M=$(PWD) modules
modules_install:
make -C $(KERNELDIR) M=$(PWD) modules_install
insmod:
sudo insmod $(MODULE_NAME).ko
reinsmod:
sudo rmmod $(MODULE_NAME)
sudo insmod $(MODULE_NAME).ko
github:
cd $(ROOT) && make github
rmmod:
sudo rmmod $(MODULE_NAME)
test :
cat /sys/kernel/debug/mydebug/a
cat /sys/kernel/debug/mydebug/b
cat /sys/kernel/debug/mydebug/subdir/c
clean:
make -C $(KERNELDIR) M=$(PWD) clean
rm -f modules.order Module.symvers Module.markers
.PHNOY:
modules modules_install clean
endif
@@ -0,0 +1,40 @@
http://blog.csdn.net/arethe/article/details/6293505]
http://lxr.free-electrons.com/source/Documentation/trace/tracepoints.txt
https://lwn.net/Articles/410200/
#1 驱动安装
-------
sudo insmod trace-events-sample.ko
#2 检查驱动
-------
cat /sys/kernel/debug/tracing/available_events | grep sample-trace
cd /sys/kernel/debug/tracing/events/sample-trace
#3 列出所有的events
-------
find /sys/kernel/debug/tracing/events -type d
cat /sys/kernel/debug/tracing/available_events
trace-cmd list
perf list 2>&1 | grep Tracepoint
#3 trace-cmd
-------
sudo trace-cmd reset
sudo trace-cmd record -e sample-trace:foo_with_template_print
sudo trace-cmd report
@@ -0,0 +1,131 @@
#include <linux/module.h>
#include <linux/kthread.h>
/*
* Any file that uses trace points, must include the header.
* But only one file, must include the header by defining
* CREATE_TRACE_POINTS first. This will make the C code that
* creates the handles for the trace points.
*/
#define CREATE_TRACE_POINTS
#include "trace-events-sample.h"
static const char *random_strings[] = {
"Mother Goose",
"Snoopy",
"Gandalf",
"Frodo",
"One ring to rule them all"
};
static void simple_thread_func(int cnt)
{
int array[6];
int len = cnt % 5;
int i;
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
for (i = 0; i < len; i++)
array[i] = i + 1;
array[i] = 0;
/* Silly tracepoints */
trace_foo_bar("hello", cnt, array, random_strings[len],
tsk_cpus_allowed(current));
trace_foo_with_template_simple("HELLO", cnt);
trace_foo_bar_with_cond("Some times print", cnt);
trace_foo_with_template_cond("prints other times", cnt);
trace_foo_with_template_print("I have to be different", cnt);
}
static int simple_thread(void *arg)
{
int cnt = 0;
while (!kthread_should_stop())
simple_thread_func(cnt++);
return 0;
}
static struct task_struct *simple_tsk;
static struct task_struct *simple_tsk_fn;
static void simple_thread_func_fn(int cnt)
{
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
/* More silly tracepoints */
trace_foo_bar_with_fn("Look at me", cnt);
trace_foo_with_template_fn("Look at me too", cnt);
}
static int simple_thread_fn(void *arg)
{
int cnt = 0;
while (!kthread_should_stop())
simple_thread_func_fn(cnt++);
return 0;
}
static DEFINE_MUTEX(thread_mutex);
int foo_bar_reg(void)
{
pr_info("Starting thread for foo_bar_fn\n");
/*
* We shouldn't be able to start a trace when the module is
* unloading (there's other locks to prevent that). But
* for consistency sake, we still take the thread_mutex.
*/
mutex_lock(&thread_mutex);
simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn");
mutex_unlock(&thread_mutex);
return 0;
}
void foo_bar_unreg(void)
{
pr_info("Killing thread for foo_bar_fn\n");
/* protect against module unloading */
mutex_lock(&thread_mutex);
if (simple_tsk_fn)
kthread_stop(simple_tsk_fn);
simple_tsk_fn = NULL;
mutex_unlock(&thread_mutex);
}
static int __init trace_event_init(void)
{
simple_tsk = kthread_run(simple_thread, NULL, "event-sample");
if (IS_ERR(simple_tsk))
return -1;
return 0;
}
static void __exit trace_event_exit(void)
{
kthread_stop(simple_tsk);
mutex_lock(&thread_mutex);
if (simple_tsk_fn)
kthread_stop(simple_tsk_fn);
simple_tsk_fn = NULL;
mutex_unlock(&thread_mutex);
}
module_init(trace_event_init);
module_exit(trace_event_exit);
MODULE_AUTHOR("Steven Rostedt");
MODULE_DESCRIPTION("trace-events-sample");
MODULE_LICENSE("GPL");
File diff suppressed because it is too large Load Diff