diff options
author | Ananth N Mavinakayanahalli <ananth@in.ibm.com> | 2008-03-04 17:28:38 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-03-04 19:35:11 -0500 |
commit | 804defea1c020d5c52985685e56986f1a399acde (patch) | |
tree | dd91b81d272522ec8e5e482408734dd290fed152 | |
parent | 9edddaa200df18e08fe0cf21036e8ae467b1363c (diff) |
Kprobes: move kprobe examples to samples/
Move kprobes examples from Documentation/kprobes.txt to under samples/.
Patch originally by Randy Dunlap.
o Updated the patch to apply on 2.6.25-rc3
o Modified examples code to build on multiple architectures. Currently,
the kprobe and jprobe examples code works for x86 and powerpc
o Cleaned up unneeded #includes
o Cleaned up Kconfig per Sam Ravnborg's suggestions to fix build break
on archs that don't have kretprobes
o Implemented suggestions by Mathieu Desnoyers on CONFIG_KRETPROBES
o Included Andrew Morton's cleanup based on x86-git
o Modified kretprobe_example to act as a arch-agnostic module to
determine routine execution times:
Use 'modprobe kretprobe_example func=<func_name>' to determine
execution time of func_name in nanoseconds.
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Acked-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | Documentation/kprobes.txt | 243 | ||||
-rw-r--r-- | samples/Kconfig | 11 | ||||
-rw-r--r-- | samples/Makefile | 2 | ||||
-rw-r--r-- | samples/kprobes/Makefile | 5 | ||||
-rw-r--r-- | samples/kprobes/jprobe_example.c | 68 | ||||
-rw-r--r-- | samples/kprobes/kprobe_example.c | 91 | ||||
-rw-r--r-- | samples/kprobes/kretprobe_example.c | 106 |
7 files changed, 287 insertions, 239 deletions
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index 83f515c2905a..be89f393274f 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt | |||
@@ -192,7 +192,8 @@ code mapping. | |||
192 | The Kprobes API includes a "register" function and an "unregister" | 192 | The Kprobes API includes a "register" function and an "unregister" |
193 | function for each type of probe. Here are terse, mini-man-page | 193 | function for each type of probe. Here are terse, mini-man-page |
194 | specifications for these functions and the associated probe handlers | 194 | specifications for these functions and the associated probe handlers |
195 | that you'll write. See the latter half of this document for examples. | 195 | that you'll write. See the files in the samples/kprobes/ sub-directory |
196 | for examples. | ||
196 | 197 | ||
197 | 4.1 register_kprobe | 198 | 4.1 register_kprobe |
198 | 199 | ||
@@ -420,249 +421,15 @@ e. Watchpoint probes (which fire on data references). | |||
420 | 421 | ||
421 | 8. Kprobes Example | 422 | 8. Kprobes Example |
422 | 423 | ||
423 | Here's a sample kernel module showing the use of kprobes to dump a | 424 | See samples/kprobes/kprobe_example.c |
424 | stack trace and selected i386 registers when do_fork() is called. | ||
425 | ----- cut here ----- | ||
426 | /*kprobe_example.c*/ | ||
427 | #include <linux/kernel.h> | ||
428 | #include <linux/module.h> | ||
429 | #include <linux/kprobes.h> | ||
430 | #include <linux/sched.h> | ||
431 | |||
432 | /*For each probe you need to allocate a kprobe structure*/ | ||
433 | static struct kprobe kp; | ||
434 | |||
435 | /*kprobe pre_handler: called just before the probed instruction is executed*/ | ||
436 | int handler_pre(struct kprobe *p, struct pt_regs *regs) | ||
437 | { | ||
438 | printk("pre_handler: p->addr=0x%p, eip=%lx, eflags=0x%lx\n", | ||
439 | p->addr, regs->eip, regs->eflags); | ||
440 | dump_stack(); | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | /*kprobe post_handler: called after the probed instruction is executed*/ | ||
445 | void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags) | ||
446 | { | ||
447 | printk("post_handler: p->addr=0x%p, eflags=0x%lx\n", | ||
448 | p->addr, regs->eflags); | ||
449 | } | ||
450 | |||
451 | /* fault_handler: this is called if an exception is generated for any | ||
452 | * instruction within the pre- or post-handler, or when Kprobes | ||
453 | * single-steps the probed instruction. | ||
454 | */ | ||
455 | int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr) | ||
456 | { | ||
457 | printk("fault_handler: p->addr=0x%p, trap #%dn", | ||
458 | p->addr, trapnr); | ||
459 | /* Return 0 because we don't handle the fault. */ | ||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | static int __init kprobe_init(void) | ||
464 | { | ||
465 | int ret; | ||
466 | kp.pre_handler = handler_pre; | ||
467 | kp.post_handler = handler_post; | ||
468 | kp.fault_handler = handler_fault; | ||
469 | kp.symbol_name = "do_fork"; | ||
470 | |||
471 | ret = register_kprobe(&kp); | ||
472 | if (ret < 0) { | ||
473 | printk("register_kprobe failed, returned %d\n", ret); | ||
474 | return ret; | ||
475 | } | ||
476 | printk("kprobe registered\n"); | ||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static void __exit kprobe_exit(void) | ||
481 | { | ||
482 | unregister_kprobe(&kp); | ||
483 | printk("kprobe unregistered\n"); | ||
484 | } | ||
485 | |||
486 | module_init(kprobe_init) | ||
487 | module_exit(kprobe_exit) | ||
488 | MODULE_LICENSE("GPL"); | ||
489 | ----- cut here ----- | ||
490 | |||
491 | You can build the kernel module, kprobe-example.ko, using the following | ||
492 | Makefile: | ||
493 | ----- cut here ----- | ||
494 | obj-m := kprobe-example.o | ||
495 | KDIR := /lib/modules/$(shell uname -r)/build | ||
496 | PWD := $(shell pwd) | ||
497 | default: | ||
498 | $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules | ||
499 | clean: | ||
500 | rm -f *.mod.c *.ko *.o | ||
501 | ----- cut here ----- | ||
502 | |||
503 | $ make | ||
504 | $ su - | ||
505 | ... | ||
506 | # insmod kprobe-example.ko | ||
507 | |||
508 | You will see the trace data in /var/log/messages and on the console | ||
509 | whenever do_fork() is invoked to create a new process. | ||
510 | 425 | ||
511 | 9. Jprobes Example | 426 | 9. Jprobes Example |
512 | 427 | ||
513 | Here's a sample kernel module showing the use of jprobes to dump | 428 | See samples/kprobes/jprobe_example.c |
514 | the arguments of do_fork(). | ||
515 | ----- cut here ----- | ||
516 | /*jprobe-example.c */ | ||
517 | #include <linux/kernel.h> | ||
518 | #include <linux/module.h> | ||
519 | #include <linux/fs.h> | ||
520 | #include <linux/uio.h> | ||
521 | #include <linux/kprobes.h> | ||
522 | |||
523 | /* | ||
524 | * Jumper probe for do_fork. | ||
525 | * Mirror principle enables access to arguments of the probed routine | ||
526 | * from the probe handler. | ||
527 | */ | ||
528 | |||
529 | /* Proxy routine having the same arguments as actual do_fork() routine */ | ||
530 | long jdo_fork(unsigned long clone_flags, unsigned long stack_start, | ||
531 | struct pt_regs *regs, unsigned long stack_size, | ||
532 | int __user * parent_tidptr, int __user * child_tidptr) | ||
533 | { | ||
534 | printk("jprobe: clone_flags=0x%lx, stack_size=0x%lx, regs=0x%p\n", | ||
535 | clone_flags, stack_size, regs); | ||
536 | /* Always end with a call to jprobe_return(). */ | ||
537 | jprobe_return(); | ||
538 | /*NOTREACHED*/ | ||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | static struct jprobe my_jprobe = { | ||
543 | .entry = jdo_fork | ||
544 | }; | ||
545 | |||
546 | static int __init jprobe_init(void) | ||
547 | { | ||
548 | int ret; | ||
549 | my_jprobe.kp.symbol_name = "do_fork"; | ||
550 | |||
551 | if ((ret = register_jprobe(&my_jprobe)) <0) { | ||
552 | printk("register_jprobe failed, returned %d\n", ret); | ||
553 | return -1; | ||
554 | } | ||
555 | printk("Planted jprobe at %p, handler addr %p\n", | ||
556 | my_jprobe.kp.addr, my_jprobe.entry); | ||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | static void __exit jprobe_exit(void) | ||
561 | { | ||
562 | unregister_jprobe(&my_jprobe); | ||
563 | printk("jprobe unregistered\n"); | ||
564 | } | ||
565 | |||
566 | module_init(jprobe_init) | ||
567 | module_exit(jprobe_exit) | ||
568 | MODULE_LICENSE("GPL"); | ||
569 | ----- cut here ----- | ||
570 | |||
571 | Build and insert the kernel module as shown in the above kprobe | ||
572 | example. You will see the trace data in /var/log/messages and on | ||
573 | the console whenever do_fork() is invoked to create a new process. | ||
574 | (Some messages may be suppressed if syslogd is configured to | ||
575 | eliminate duplicate messages.) | ||
576 | 429 | ||
577 | 10. Kretprobes Example | 430 | 10. Kretprobes Example |
578 | 431 | ||
579 | Here's a sample kernel module showing the use of return probes to | 432 | See samples/kprobes/kretprobe_example.c |
580 | report failed calls to sys_open(). | ||
581 | ----- cut here ----- | ||
582 | /*kretprobe-example.c*/ | ||
583 | #include <linux/kernel.h> | ||
584 | #include <linux/module.h> | ||
585 | #include <linux/kprobes.h> | ||
586 | #include <linux/ktime.h> | ||
587 | |||
588 | /* per-instance private data */ | ||
589 | struct my_data { | ||
590 | ktime_t entry_stamp; | ||
591 | }; | ||
592 | |||
593 | static const char *probed_func = "sys_open"; | ||
594 | |||
595 | /* Timestamp function entry. */ | ||
596 | static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | ||
597 | { | ||
598 | struct my_data *data; | ||
599 | |||
600 | if(!current->mm) | ||
601 | return 1; /* skip kernel threads */ | ||
602 | |||
603 | data = (struct my_data *)ri->data; | ||
604 | data->entry_stamp = ktime_get(); | ||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | /* If the probed function failed, log the return value and duration. | ||
609 | * Duration may turn out to be zero consistently, depending upon the | ||
610 | * granularity of time accounting on the platform. */ | ||
611 | static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | ||
612 | { | ||
613 | int retval = regs_return_value(regs); | ||
614 | struct my_data *data = (struct my_data *)ri->data; | ||
615 | s64 delta; | ||
616 | ktime_t now; | ||
617 | |||
618 | if (retval < 0) { | ||
619 | now = ktime_get(); | ||
620 | delta = ktime_to_ns(ktime_sub(now, data->entry_stamp)); | ||
621 | printk("%s: return val = %d (duration = %lld ns)\n", | ||
622 | probed_func, retval, delta); | ||
623 | } | ||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | static struct kretprobe my_kretprobe = { | ||
628 | .handler = return_handler, | ||
629 | .entry_handler = entry_handler, | ||
630 | .data_size = sizeof(struct my_data), | ||
631 | .maxactive = 20, /* probe up to 20 instances concurrently */ | ||
632 | }; | ||
633 | |||
634 | static int __init kretprobe_init(void) | ||
635 | { | ||
636 | int ret; | ||
637 | my_kretprobe.kp.symbol_name = (char *)probed_func; | ||
638 | |||
639 | if ((ret = register_kretprobe(&my_kretprobe)) < 0) { | ||
640 | printk("register_kretprobe failed, returned %d\n", ret); | ||
641 | return -1; | ||
642 | } | ||
643 | printk("Kretprobe active on %s\n", my_kretprobe.kp.symbol_name); | ||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static void __exit kretprobe_exit(void) | ||
648 | { | ||
649 | unregister_kretprobe(&my_kretprobe); | ||
650 | printk("kretprobe unregistered\n"); | ||
651 | /* nmissed > 0 suggests that maxactive was set too low. */ | ||
652 | printk("Missed probing %d instances of %s\n", | ||
653 | my_kretprobe.nmissed, probed_func); | ||
654 | } | ||
655 | |||
656 | module_init(kretprobe_init) | ||
657 | module_exit(kretprobe_exit) | ||
658 | MODULE_LICENSE("GPL"); | ||
659 | ----- cut here ----- | ||
660 | |||
661 | Build and insert the kernel module as shown in the above kprobe | ||
662 | example. You will see the trace data in /var/log/messages and on the | ||
663 | console whenever sys_open() returns a negative value. (Some messages | ||
664 | may be suppressed if syslogd is configured to eliminate duplicate | ||
665 | messages.) | ||
666 | 433 | ||
667 | For additional information on Kprobes, refer to the following URLs: | 434 | For additional information on Kprobes, refer to the following URLs: |
668 | http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe | 435 | http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe |
diff --git a/samples/Kconfig b/samples/Kconfig index 74d97cc24787..e1fb471cc501 100644 --- a/samples/Kconfig +++ b/samples/Kconfig | |||
@@ -22,5 +22,16 @@ config SAMPLE_KOBJECT | |||
22 | 22 | ||
23 | If in doubt, say "N" here. | 23 | If in doubt, say "N" here. |
24 | 24 | ||
25 | config SAMPLE_KPROBES | ||
26 | tristate "Build kprobes examples -- loadable modules only" | ||
27 | depends on KPROBES && m | ||
28 | help | ||
29 | This build several kprobes example modules. | ||
30 | |||
31 | config SAMPLE_KRETPROBES | ||
32 | tristate "Build kretprobes example -- loadable modules only" | ||
33 | default m | ||
34 | depends on SAMPLE_KPROBES && KRETPROBES | ||
35 | |||
25 | endif # SAMPLES | 36 | endif # SAMPLES |
26 | 37 | ||
diff --git a/samples/Makefile b/samples/Makefile index 8652d0f268ad..2e02575f7794 100644 --- a/samples/Makefile +++ b/samples/Makefile | |||
@@ -1,3 +1,3 @@ | |||
1 | # Makefile for Linux samples code | 1 | # Makefile for Linux samples code |
2 | 2 | ||
3 | obj-$(CONFIG_SAMPLES) += markers/ kobject/ | 3 | obj-$(CONFIG_SAMPLES) += markers/ kobject/ kprobes/ |
diff --git a/samples/kprobes/Makefile b/samples/kprobes/Makefile new file mode 100644 index 000000000000..68739bc4fc6a --- /dev/null +++ b/samples/kprobes/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # builds the kprobes example kernel modules; | ||
2 | # then to use one (as root): insmod <module_name.ko> | ||
3 | |||
4 | obj-$(CONFIG_SAMPLE_KPROBES) += kprobe_example.o jprobe_example.o | ||
5 | obj-$(CONFIG_SAMPLE_KRETPROBES) += kretprobe_example.o | ||
diff --git a/samples/kprobes/jprobe_example.c b/samples/kprobes/jprobe_example.c new file mode 100644 index 000000000000..b7541355b92b --- /dev/null +++ b/samples/kprobes/jprobe_example.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * Here's a sample kernel module showing the use of jprobes to dump | ||
3 | * the arguments of do_fork(). | ||
4 | * | ||
5 | * For more information on theory of operation of jprobes, see | ||
6 | * Documentation/kprobes.txt | ||
7 | * | ||
8 | * Build and insert the kernel module as done in the kprobe example. | ||
9 | * You will see the trace data in /var/log/messages and on the | ||
10 | * console whenever do_fork() is invoked to create a new process. | ||
11 | * (Some messages may be suppressed if syslogd is configured to | ||
12 | * eliminate duplicate messages.) | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/kprobes.h> | ||
18 | |||
19 | /* | ||
20 | * Jumper probe for do_fork. | ||
21 | * Mirror principle enables access to arguments of the probed routine | ||
22 | * from the probe handler. | ||
23 | */ | ||
24 | |||
25 | /* Proxy routine having the same arguments as actual do_fork() routine */ | ||
26 | static long jdo_fork(unsigned long clone_flags, unsigned long stack_start, | ||
27 | struct pt_regs *regs, unsigned long stack_size, | ||
28 | int __user *parent_tidptr, int __user *child_tidptr) | ||
29 | { | ||
30 | printk(KERN_INFO "jprobe: clone_flags = 0x%lx, stack_size = 0x%lx," | ||
31 | " regs = 0x%p\n", | ||
32 | clone_flags, stack_size, regs); | ||
33 | |||
34 | /* Always end with a call to jprobe_return(). */ | ||
35 | jprobe_return(); | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | static struct jprobe my_jprobe = { | ||
40 | .entry = jdo_fork, | ||
41 | .kp = { | ||
42 | .symbol_name = "do_fork", | ||
43 | }, | ||
44 | }; | ||
45 | |||
46 | static int __init jprobe_init(void) | ||
47 | { | ||
48 | int ret; | ||
49 | |||
50 | ret = register_jprobe(&my_jprobe); | ||
51 | if (ret < 0) { | ||
52 | printk(KERN_INFO "register_jprobe failed, returned %d\n", ret); | ||
53 | return -1; | ||
54 | } | ||
55 | printk(KERN_INFO "Planted jprobe at %p, handler addr %p\n", | ||
56 | my_jprobe.kp.addr, my_jprobe.entry); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static void __exit jprobe_exit(void) | ||
61 | { | ||
62 | unregister_jprobe(&my_jprobe); | ||
63 | printk(KERN_INFO "jprobe at %p unregistered\n", my_jprobe.kp.addr); | ||
64 | } | ||
65 | |||
66 | module_init(jprobe_init) | ||
67 | module_exit(jprobe_exit) | ||
68 | MODULE_LICENSE("GPL"); | ||
diff --git a/samples/kprobes/kprobe_example.c b/samples/kprobes/kprobe_example.c new file mode 100644 index 000000000000..a681998a871c --- /dev/null +++ b/samples/kprobes/kprobe_example.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * NOTE: This example is works on x86 and powerpc. | ||
3 | * Here's a sample kernel module showing the use of kprobes to dump a | ||
4 | * stack trace and selected registers when do_fork() is called. | ||
5 | * | ||
6 | * For more information on theory of operation of kprobes, see | ||
7 | * Documentation/kprobes.txt | ||
8 | * | ||
9 | * You will see the trace data in /var/log/messages and on the console | ||
10 | * whenever do_fork() is invoked to create a new process. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/kprobes.h> | ||
16 | |||
17 | /* For each probe you need to allocate a kprobe structure */ | ||
18 | static struct kprobe kp = { | ||
19 | .symbol_name = "do_fork", | ||
20 | }; | ||
21 | |||
22 | /* kprobe pre_handler: called just before the probed instruction is executed */ | ||
23 | static int handler_pre(struct kprobe *p, struct pt_regs *regs) | ||
24 | { | ||
25 | #ifdef CONFIG_X86 | ||
26 | printk(KERN_INFO "pre_handler: p->addr = 0x%p, ip = %lx," | ||
27 | " flags = 0x%lx\n", | ||
28 | p->addr, regs->ip, regs->flags); | ||
29 | #endif | ||
30 | #ifdef CONFIG_PPC | ||
31 | printk(KERN_INFO "pre_handler: p->addr = 0x%p, nip = 0x%lx," | ||
32 | " msr = 0x%lx\n", | ||
33 | p->addr, regs->nip, regs->msr); | ||
34 | #endif | ||
35 | |||
36 | /* A dump_stack() here will give a stack backtrace */ | ||
37 | return 0; | ||
38 | } | ||
39 | |||
40 | /* kprobe post_handler: called after the probed instruction is executed */ | ||
41 | static void handler_post(struct kprobe *p, struct pt_regs *regs, | ||
42 | unsigned long flags) | ||
43 | { | ||
44 | #ifdef CONFIG_X86 | ||
45 | printk(KERN_INFO "post_handler: p->addr = 0x%p, flags = 0x%lx\n", | ||
46 | p->addr, regs->flags); | ||
47 | #endif | ||
48 | #ifdef CONFIG_PPC | ||
49 | printk(KERN_INFO "post_handler: p->addr = 0x%p, msr = 0x%lx\n", | ||
50 | p->addr, regs->msr); | ||
51 | #endif | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * fault_handler: this is called if an exception is generated for any | ||
56 | * instruction within the pre- or post-handler, or when Kprobes | ||
57 | * single-steps the probed instruction. | ||
58 | */ | ||
59 | static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr) | ||
60 | { | ||
61 | printk(KERN_INFO "fault_handler: p->addr = 0x%p, trap #%dn", | ||
62 | p->addr, trapnr); | ||
63 | /* Return 0 because we don't handle the fault. */ | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int __init kprobe_init(void) | ||
68 | { | ||
69 | int ret; | ||
70 | kp.pre_handler = handler_pre; | ||
71 | kp.post_handler = handler_post; | ||
72 | kp.fault_handler = handler_fault; | ||
73 | |||
74 | ret = register_kprobe(&kp); | ||
75 | if (ret < 0) { | ||
76 | printk(KERN_INFO "register_kprobe failed, returned %d\n", ret); | ||
77 | return ret; | ||
78 | } | ||
79 | printk(KERN_INFO "Planted kprobe at %p\n", kp.addr); | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static void __exit kprobe_exit(void) | ||
84 | { | ||
85 | unregister_kprobe(&kp); | ||
86 | printk(KERN_INFO "kprobe at %p unregistered\n", kp.addr); | ||
87 | } | ||
88 | |||
89 | module_init(kprobe_init) | ||
90 | module_exit(kprobe_exit) | ||
91 | MODULE_LICENSE("GPL"); | ||
diff --git a/samples/kprobes/kretprobe_example.c b/samples/kprobes/kretprobe_example.c new file mode 100644 index 000000000000..4e764b317d61 --- /dev/null +++ b/samples/kprobes/kretprobe_example.c | |||
@@ -0,0 +1,106 @@ | |||
1 | /* | ||
2 | * kretprobe_example.c | ||
3 | * | ||
4 | * Here's a sample kernel module showing the use of return probes to | ||
5 | * report the return value and total time taken for probed function | ||
6 | * to run. | ||
7 | * | ||
8 | * usage: insmod kretprobe_example.ko func=<func_name> | ||
9 | * | ||
10 | * If no func_name is specified, do_fork is instrumented | ||
11 | * | ||
12 | * For more information on theory of operation of kretprobes, see | ||
13 | * Documentation/kprobes.txt | ||
14 | * | ||
15 | * Build and insert the kernel module as done in the kprobe example. | ||
16 | * You will see the trace data in /var/log/messages and on the console | ||
17 | * whenever the probed function returns. (Some messages may be suppressed | ||
18 | * if syslogd is configured to eliminate duplicate messages.) | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/kprobes.h> | ||
24 | #include <linux/ktime.h> | ||
25 | #include <linux/limits.h> | ||
26 | |||
27 | static char func_name[NAME_MAX] = "do_fork"; | ||
28 | module_param_string(func, func_name, NAME_MAX, S_IRUGO); | ||
29 | MODULE_PARM_DESC(func, "Function to kretprobe; this module will report the" | ||
30 | " function's execution time"); | ||
31 | |||
32 | /* per-instance private data */ | ||
33 | struct my_data { | ||
34 | ktime_t entry_stamp; | ||
35 | }; | ||
36 | |||
37 | /* Here we use the entry_hanlder to timestamp function entry */ | ||
38 | static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | ||
39 | { | ||
40 | struct my_data *data; | ||
41 | |||
42 | if (!current->mm) | ||
43 | return 1; /* Skip kernel threads */ | ||
44 | |||
45 | data = (struct my_data *)ri->data; | ||
46 | data->entry_stamp = ktime_get(); | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | /* | ||
51 | * Return-probe handler: Log the return value and duration. Duration may turn | ||
52 | * out to be zero consistently, depending upon the granularity of time | ||
53 | * accounting on the platform. | ||
54 | */ | ||
55 | static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | ||
56 | { | ||
57 | int retval = regs_return_value(regs); | ||
58 | struct my_data *data = (struct my_data *)ri->data; | ||
59 | s64 delta; | ||
60 | ktime_t now; | ||
61 | |||
62 | now = ktime_get(); | ||
63 | delta = ktime_to_ns(ktime_sub(now, data->entry_stamp)); | ||
64 | printk(KERN_INFO "%s returned %d and took %lld ns to execute\n", | ||
65 | func_name, retval, (long long)delta); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static struct kretprobe my_kretprobe = { | ||
70 | .handler = ret_handler, | ||
71 | .entry_handler = entry_handler, | ||
72 | .data_size = sizeof(struct my_data), | ||
73 | /* Probe up to 20 instances concurrently. */ | ||
74 | .maxactive = 20, | ||
75 | }; | ||
76 | |||
77 | static int __init kretprobe_init(void) | ||
78 | { | ||
79 | int ret; | ||
80 | |||
81 | my_kretprobe.kp.symbol_name = func_name; | ||
82 | ret = register_kretprobe(&my_kretprobe); | ||
83 | if (ret < 0) { | ||
84 | printk(KERN_INFO "register_kretprobe failed, returned %d\n", | ||
85 | ret); | ||
86 | return -1; | ||
87 | } | ||
88 | printk(KERN_INFO "Planted return probe at %s: %p\n", | ||
89 | my_kretprobe.kp.symbol_name, my_kretprobe.kp.addr); | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static void __exit kretprobe_exit(void) | ||
94 | { | ||
95 | unregister_kretprobe(&my_kretprobe); | ||
96 | printk(KERN_INFO "kretprobe at %p unregistered\n", | ||
97 | my_kretprobe.kp.addr); | ||
98 | |||
99 | /* nmissed > 0 suggests that maxactive was set too low. */ | ||
100 | printk(KERN_INFO "Missed probing %d instances of %s\n", | ||
101 | my_kretprobe.nmissed, my_kretprobe.kp.symbol_name); | ||
102 | } | ||
103 | |||
104 | module_init(kretprobe_init) | ||
105 | module_exit(kretprobe_exit) | ||
106 | MODULE_LICENSE("GPL"); | ||