X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=Documentation%2Fkprobes.txt;h=6877e71871132b92d60a603fe444f93af53f0aa1;hb=b5cf43c47b05c8deb10f9674d541dddbdec0e341;hp=30c101761d0d54f532122e8a804d376de2aa61d8;hpb=a8e98d6d51a3eb7bb061b1625193a129c8bd094f;p=pandora-kernel.git diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index 30c101761d0d..6877e7187113 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt @@ -37,6 +37,11 @@ registration function such as register_kprobe() specifies where the probe is to be inserted and what handler is to be called when the probe is hit. +There are also register_/unregister_*probes() functions for batch +registration/unregistration of a group of *probes. These functions +can speed up unregistration process when you have to unregister +a lot of probes at once. + The next three subsections explain how the different types of probes work. They explain certain things that you'll need to know in order to make the best use of Kprobes -- e.g., the @@ -92,9 +97,8 @@ handler has run. Up to MAX_STACK_SIZE bytes are copied -- e.g., 64 bytes on i386. Note that the probed function's args may be passed on the stack -or in registers (e.g., for x86_64 or for an i386 fastcall function). -The jprobe will work in either case, so long as the handler's -prototype matches that of the probed function. +or in registers. The jprobe will work in either case, so long as the +handler's prototype matches that of the probed function. 1.3 Return Probes @@ -191,9 +195,11 @@ code mapping. 4. API Reference The Kprobes API includes a "register" function and an "unregister" -function for each type of probe. Here are terse, mini-man-page -specifications for these functions and the associated probe handlers -that you'll write. See the latter half of this document for examples. +function for each type of probe. The API also includes "register_*probes" +and "unregister_*probes" functions for (un)registering arrays of probes. +Here are terse, mini-man-page specifications for these functions and +the associated probe handlers that you'll write. See the files in the +samples/kprobes/ sub-directory for examples. 4.1 register_kprobe @@ -270,9 +276,9 @@ Kprobes runs the handler whose address is jp->entry. The handler should have the same arg list and return type as the probed function; and just before it returns, it must call jprobe_return(). (The handler never actually returns, since jprobe_return() returns -control to Kprobes.) If the probed function is declared asmlinkage, -fastcall, or anything else that affects how args are passed, the -handler's declaration must match. +control to Kprobes.) If the probed function is declared asmlinkage +or anything else that affects how args are passed, the handler's +declaration must match. register_jprobe() returns 0 on success, or a negative errno otherwise. @@ -319,6 +325,43 @@ void unregister_kretprobe(struct kretprobe *rp); Removes the specified probe. The unregister function can be called at any time after the probe has been registered. +NOTE: +If the functions find an incorrect probe (ex. an unregistered probe), +they clear the addr field of the probe. + +4.5 register_*probes + +#include +int register_kprobes(struct kprobe **kps, int num); +int register_kretprobes(struct kretprobe **rps, int num); +int register_jprobes(struct jprobe **jps, int num); + +Registers each of the num probes in the specified array. If any +error occurs during registration, all probes in the array, up to +the bad probe, are safely unregistered before the register_*probes +function returns. +- kps/rps/jps: an array of pointers to *probe data structures +- num: the number of the array entries. + +NOTE: +You have to allocate(or define) an array of pointers and set all +of the array entries before using these functions. + +4.6 unregister_*probes + +#include +void unregister_kprobes(struct kprobe **kps, int num); +void unregister_kretprobes(struct kretprobe **rps, int num); +void unregister_jprobes(struct jprobe **jps, int num); + +Removes each of the num probes in the specified array at once. + +NOTE: +If the functions find some incorrect probes (ex. unregistered +probes) in the specified array, they clear the addr field of those +incorrect probes. However, other probes in the array are +unregistered correctly. + 5. Kprobes Features and Limitations Kprobes allows multiple probes at the same address. Currently, @@ -421,249 +464,15 @@ e. Watchpoint probes (which fire on data references). 8. Kprobes Example -Here's a sample kernel module showing the use of kprobes to dump a -stack trace and selected i386 registers when do_fork() is called. ------ cut here ----- -/*kprobe_example.c*/ -#include -#include -#include -#include - -/*For each probe you need to allocate a kprobe structure*/ -static struct kprobe kp; - -/*kprobe pre_handler: called just before the probed instruction is executed*/ -int handler_pre(struct kprobe *p, struct pt_regs *regs) -{ - printk("pre_handler: p->addr=0x%p, eip=%lx, eflags=0x%lx\n", - p->addr, regs->eip, regs->eflags); - dump_stack(); - return 0; -} - -/*kprobe post_handler: called after the probed instruction is executed*/ -void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags) -{ - printk("post_handler: p->addr=0x%p, eflags=0x%lx\n", - p->addr, regs->eflags); -} - -/* 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. - */ -int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr) -{ - printk("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; - kp.symbol_name = "do_fork"; - - ret = register_kprobe(&kp); - if (ret < 0) { - printk("register_kprobe failed, returned %d\n", ret); - return ret; - } - printk("kprobe registered\n"); - return 0; -} - -static void __exit kprobe_exit(void) -{ - unregister_kprobe(&kp); - printk("kprobe unregistered\n"); -} - -module_init(kprobe_init) -module_exit(kprobe_exit) -MODULE_LICENSE("GPL"); ------ cut here ----- - -You can build the kernel module, kprobe-example.ko, using the following -Makefile: ------ cut here ----- -obj-m := kprobe-example.o -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) -default: - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules -clean: - rm -f *.mod.c *.ko *.o ------ cut here ----- - -$ make -$ su - -... -# insmod kprobe-example.ko - -You will see the trace data in /var/log/messages and on the console -whenever do_fork() is invoked to create a new process. +See samples/kprobes/kprobe_example.c 9. Jprobes Example -Here's a sample kernel module showing the use of jprobes to dump -the arguments of do_fork(). ------ cut here ----- -/*jprobe-example.c */ -#include -#include -#include -#include -#include - -/* - * 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 = jdo_fork -}; - -static int __init jprobe_init(void) -{ - int ret; - my_jprobe.kp.symbol_name = "do_fork"; - - 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; -} - -static void __exit jprobe_exit(void) -{ - unregister_jprobe(&my_jprobe); - printk("jprobe unregistered\n"); -} - -module_init(jprobe_init) -module_exit(jprobe_exit) -MODULE_LICENSE("GPL"); ------ cut here ----- - -Build and insert the kernel module as shown in the above kprobe -example. You will see the trace data in /var/log/messages and on -the console whenever do_fork() is invoked to create a new process. -(Some messages may be suppressed if syslogd is configured to -eliminate duplicate messages.) +See samples/kprobes/jprobe_example.c 10. Kretprobes Example -Here's a sample kernel module showing the use of return probes to -report failed calls to sys_open(). ------ cut here ----- -/*kretprobe-example.c*/ -#include -#include -#include -#include - -/* per-instance private data */ -struct my_data { - ktime_t entry_stamp; -}; - -static const char *probed_func = "sys_open"; - -/* Timestamp function entry. */ -static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) -{ - struct my_data *data; - - if(!current->mm) - return 1; /* skip kernel threads */ - - data = (struct my_data *)ri->data; - data->entry_stamp = ktime_get(); - return 0; -} - -/* If the probed function failed, log the return value and duration. - * Duration may turn out to be zero consistently, depending upon the - * granularity of time accounting on the platform. */ -static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs) -{ - int retval = regs_return_value(regs); - struct my_data *data = (struct my_data *)ri->data; - s64 delta; - ktime_t now; - - if (retval < 0) { - now = ktime_get(); - delta = ktime_to_ns(ktime_sub(now, data->entry_stamp)); - printk("%s: return val = %d (duration = %lld ns)\n", - probed_func, retval, delta); - } - return 0; -} - -static struct kretprobe my_kretprobe = { - .handler = return_handler, - .entry_handler = entry_handler, - .data_size = sizeof(struct my_data), - .maxactive = 20, /* probe up to 20 instances concurrently */ -}; - -static int __init kretprobe_init(void) -{ - int ret; - my_kretprobe.kp.symbol_name = (char *)probed_func; - - if ((ret = register_kretprobe(&my_kretprobe)) < 0) { - printk("register_kretprobe failed, returned %d\n", ret); - return -1; - } - printk("Kretprobe active on %s\n", my_kretprobe.kp.symbol_name); - return 0; -} - -static void __exit kretprobe_exit(void) -{ - unregister_kretprobe(&my_kretprobe); - printk("kretprobe unregistered\n"); - /* nmissed > 0 suggests that maxactive was set too low. */ - printk("Missed probing %d instances of %s\n", - my_kretprobe.nmissed, probed_func); -} - -module_init(kretprobe_init) -module_exit(kretprobe_exit) -MODULE_LICENSE("GPL"); ------ cut here ----- - -Build and insert the kernel module as shown in the above kprobe -example. You will see the trace data in /var/log/messages and on the -console whenever sys_open() returns a negative value. (Some messages -may be suppressed if syslogd is configured to eliminate duplicate -messages.) +See samples/kprobes/kretprobe_example.c For additional information on Kprobes, refer to the following URLs: http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe