diff options
author | Abhishek Sagar <sagar.abhishek@gmail.com> | 2008-02-06 04:38:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-06 13:41:11 -0500 |
commit | f47cd9b553aaada602449204513b5a5b29cba263 (patch) | |
tree | 079ddd399b1aa00a8c413ef51f3b8681a19a6e7e /Documentation | |
parent | 5beec4aa2ac261b0b4992fb41df40a7ab91e4fad (diff) |
kprobes: kretprobe user entry-handler
Provide support to add an optional user defined callback to be run at
function entry of a kretprobe'd function. Also modify the kprobe smoke
tests to include an entry-handler during the kretprobe sanity test.
Signed-off-by: Abhishek Sagar <sagar.abhishek@gmail.com>
Cc: Prasanna S Panchamukhi <prasanna@in.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Acked-by: Jim Keniston <jkenisto@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'Documentation')
-rw-r--r-- | Documentation/kprobes.txt | 81 |
1 files changed, 69 insertions, 12 deletions
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index 53a63890aea4..30c101761d0d 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt | |||
@@ -96,7 +96,9 @@ or in registers (e.g., for x86_64 or for an i386 fastcall function). | |||
96 | The jprobe will work in either case, so long as the handler's | 96 | The jprobe will work in either case, so long as the handler's |
97 | prototype matches that of the probed function. | 97 | prototype matches that of the probed function. |
98 | 98 | ||
99 | 1.3 How Does a Return Probe Work? | 99 | 1.3 Return Probes |
100 | |||
101 | 1.3.1 How Does a Return Probe Work? | ||
100 | 102 | ||
101 | When you call register_kretprobe(), Kprobes establishes a kprobe at | 103 | When you call register_kretprobe(), Kprobes establishes a kprobe at |
102 | the entry to the function. When the probed function is called and this | 104 | the entry to the function. When the probed function is called and this |
@@ -107,9 +109,9 @@ At boot time, Kprobes registers a kprobe at the trampoline. | |||
107 | 109 | ||
108 | When the probed function executes its return instruction, control | 110 | When the probed function executes its return instruction, control |
109 | passes to the trampoline and that probe is hit. Kprobes' trampoline | 111 | passes to the trampoline and that probe is hit. Kprobes' trampoline |
110 | handler calls the user-specified handler associated with the kretprobe, | 112 | handler calls the user-specified return handler associated with the |
111 | then sets the saved instruction pointer to the saved return address, | 113 | kretprobe, then sets the saved instruction pointer to the saved return |
112 | and that's where execution resumes upon return from the trap. | 114 | address, and that's where execution resumes upon return from the trap. |
113 | 115 | ||
114 | While the probed function is executing, its return address is | 116 | While the probed function is executing, its return address is |
115 | stored in an object of type kretprobe_instance. Before calling | 117 | stored in an object of type kretprobe_instance. Before calling |
@@ -131,6 +133,30 @@ zero when the return probe is registered, and is incremented every | |||
131 | time the probed function is entered but there is no kretprobe_instance | 133 | time the probed function is entered but there is no kretprobe_instance |
132 | object available for establishing the return probe. | 134 | object available for establishing the return probe. |
133 | 135 | ||
136 | 1.3.2 Kretprobe entry-handler | ||
137 | |||
138 | Kretprobes also provides an optional user-specified handler which runs | ||
139 | on function entry. This handler is specified by setting the entry_handler | ||
140 | field of the kretprobe struct. Whenever the kprobe placed by kretprobe at the | ||
141 | function entry is hit, the user-defined entry_handler, if any, is invoked. | ||
142 | If the entry_handler returns 0 (success) then a corresponding return handler | ||
143 | is guaranteed to be called upon function return. If the entry_handler | ||
144 | returns a non-zero error then Kprobes leaves the return address as is, and | ||
145 | the kretprobe has no further effect for that particular function instance. | ||
146 | |||
147 | Multiple entry and return handler invocations are matched using the unique | ||
148 | kretprobe_instance object associated with them. Additionally, a user | ||
149 | may also specify per return-instance private data to be part of each | ||
150 | kretprobe_instance object. This is especially useful when sharing private | ||
151 | data between corresponding user entry and return handlers. The size of each | ||
152 | private data object can be specified at kretprobe registration time by | ||
153 | setting the data_size field of the kretprobe struct. This data can be | ||
154 | accessed through the data field of each kretprobe_instance object. | ||
155 | |||
156 | In case probed function is entered but there is no kretprobe_instance | ||
157 | object available, then in addition to incrementing the nmissed count, | ||
158 | the user entry_handler invocation is also skipped. | ||
159 | |||
134 | 2. Architectures Supported | 160 | 2. Architectures Supported |
135 | 161 | ||
136 | Kprobes, jprobes, and return probes are implemented on the following | 162 | Kprobes, jprobes, and return probes are implemented on the following |
@@ -274,6 +300,8 @@ of interest: | |||
274 | - ret_addr: the return address | 300 | - ret_addr: the return address |
275 | - rp: points to the corresponding kretprobe object | 301 | - rp: points to the corresponding kretprobe object |
276 | - task: points to the corresponding task struct | 302 | - task: points to the corresponding task struct |
303 | - data: points to per return-instance private data; see "Kretprobe | ||
304 | entry-handler" for details. | ||
277 | 305 | ||
278 | The regs_return_value(regs) macro provides a simple abstraction to | 306 | The regs_return_value(regs) macro provides a simple abstraction to |
279 | extract the return value from the appropriate register as defined by | 307 | extract the return value from the appropriate register as defined by |
@@ -556,23 +584,52 @@ report failed calls to sys_open(). | |||
556 | #include <linux/kernel.h> | 584 | #include <linux/kernel.h> |
557 | #include <linux/module.h> | 585 | #include <linux/module.h> |
558 | #include <linux/kprobes.h> | 586 | #include <linux/kprobes.h> |
587 | #include <linux/ktime.h> | ||
588 | |||
589 | /* per-instance private data */ | ||
590 | struct my_data { | ||
591 | ktime_t entry_stamp; | ||
592 | }; | ||
559 | 593 | ||
560 | static const char *probed_func = "sys_open"; | 594 | static const char *probed_func = "sys_open"; |
561 | 595 | ||
562 | /* Return-probe handler: If the probed function fails, log the return value. */ | 596 | /* Timestamp function entry. */ |
563 | static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | 597 | static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) |
598 | { | ||
599 | struct my_data *data; | ||
600 | |||
601 | if(!current->mm) | ||
602 | return 1; /* skip kernel threads */ | ||
603 | |||
604 | data = (struct my_data *)ri->data; | ||
605 | data->entry_stamp = ktime_get(); | ||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | /* If the probed function failed, log the return value and duration. | ||
610 | * Duration may turn out to be zero consistently, depending upon the | ||
611 | * granularity of time accounting on the platform. */ | ||
612 | static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | ||
564 | { | 613 | { |
565 | int retval = regs_return_value(regs); | 614 | int retval = regs_return_value(regs); |
615 | struct my_data *data = (struct my_data *)ri->data; | ||
616 | s64 delta; | ||
617 | ktime_t now; | ||
618 | |||
566 | if (retval < 0) { | 619 | if (retval < 0) { |
567 | printk("%s returns %d\n", probed_func, retval); | 620 | now = ktime_get(); |
621 | delta = ktime_to_ns(ktime_sub(now, data->entry_stamp)); | ||
622 | printk("%s: return val = %d (duration = %lld ns)\n", | ||
623 | probed_func, retval, delta); | ||
568 | } | 624 | } |
569 | return 0; | 625 | return 0; |
570 | } | 626 | } |
571 | 627 | ||
572 | static struct kretprobe my_kretprobe = { | 628 | static struct kretprobe my_kretprobe = { |
573 | .handler = ret_handler, | 629 | .handler = return_handler, |
574 | /* Probe up to 20 instances concurrently. */ | 630 | .entry_handler = entry_handler, |
575 | .maxactive = 20 | 631 | .data_size = sizeof(struct my_data), |
632 | .maxactive = 20, /* probe up to 20 instances concurrently */ | ||
576 | }; | 633 | }; |
577 | 634 | ||
578 | static int __init kretprobe_init(void) | 635 | static int __init kretprobe_init(void) |
@@ -584,7 +641,7 @@ static int __init kretprobe_init(void) | |||
584 | printk("register_kretprobe failed, returned %d\n", ret); | 641 | printk("register_kretprobe failed, returned %d\n", ret); |
585 | return -1; | 642 | return -1; |
586 | } | 643 | } |
587 | printk("Planted return probe at %p\n", my_kretprobe.kp.addr); | 644 | printk("Kretprobe active on %s\n", my_kretprobe.kp.symbol_name); |
588 | return 0; | 645 | return 0; |
589 | } | 646 | } |
590 | 647 | ||
@@ -594,7 +651,7 @@ static void __exit kretprobe_exit(void) | |||
594 | printk("kretprobe unregistered\n"); | 651 | printk("kretprobe unregistered\n"); |
595 | /* nmissed > 0 suggests that maxactive was set too low. */ | 652 | /* nmissed > 0 suggests that maxactive was set too low. */ |
596 | printk("Missed probing %d instances of %s\n", | 653 | printk("Missed probing %d instances of %s\n", |
597 | my_kretprobe.nmissed, probed_func); | 654 | my_kretprobe.nmissed, probed_func); |
598 | } | 655 | } |
599 | 656 | ||
600 | module_init(kretprobe_init) | 657 | module_init(kretprobe_init) |