Commit 09b18203 authored by Ananth N Mavinakayanahalli's avatar Ananth N Mavinakayanahalli Committed by Linus Torvalds

[PATCH] Update Documentation/kprobes.txt

Documentation/kprobes.txt updated to reflect:

o In-kernel symbol resolution
o CONFIG_KALLSYMS dependency
o Usage of JPROBE_ENTRY
o Addition of regs_return_value()

Also update the references list and usage examples to use correct module
interfaces.
Signed-off-by: default avatarAnanth N Mavinakayanahalli <ananth@in.ibm.com>
Acked-by: default avatarJim Keniston <jkenisto@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b3f827cb
...@@ -151,9 +151,9 @@ So that you can load and unload Kprobes-based instrumentation modules, ...@@ -151,9 +151,9 @@ So that you can load and unload Kprobes-based instrumentation modules,
make sure "Loadable module support" (CONFIG_MODULES) and "Module make sure "Loadable module support" (CONFIG_MODULES) and "Module
unloading" (CONFIG_MODULE_UNLOAD) are set to "y". unloading" (CONFIG_MODULE_UNLOAD) are set to "y".
You may also want to ensure that CONFIG_KALLSYMS and perhaps even Also make sure that CONFIG_KALLSYMS and perhaps even CONFIG_KALLSYMS_ALL
CONFIG_KALLSYMS_ALL are set to "y", since kallsyms_lookup_name() are set to "y", since kallsyms_lookup_name() is used by the in-kernel
is a handy, version-independent way to find a function's address. kprobe address resolution code.
If you need to insert a probe in the middle of a function, you may find If you need to insert a probe in the middle of a function, you may find
it useful to "Compile the kernel with debug info" (CONFIG_DEBUG_INFO), it useful to "Compile the kernel with debug info" (CONFIG_DEBUG_INFO),
...@@ -179,6 +179,27 @@ occurs during execution of kp->pre_handler or kp->post_handler, ...@@ -179,6 +179,27 @@ occurs during execution of kp->pre_handler or kp->post_handler,
or during single-stepping of the probed instruction, Kprobes calls or during single-stepping of the probed instruction, Kprobes calls
kp->fault_handler. Any or all handlers can be NULL. kp->fault_handler. Any or all handlers can be NULL.
NOTE:
1. With the introduction of the "symbol_name" field to struct kprobe,
the probepoint address resolution will now be taken care of by the kernel.
The following will now work:
kp.symbol_name = "symbol_name";
(64-bit powerpc intricacies such as function descriptors are handled
transparently)
2. Use the "offset" field of struct kprobe if the offset into the symbol
to install a probepoint is known. This field is used to calculate the
probepoint.
3. Specify either the kprobe "symbol_name" OR the "addr". If both are
specified, kprobe registration will fail with -EINVAL.
4. With CISC architectures (such as i386 and x86_64), the kprobes code
does not validate if the kprobe.addr is at an instruction boundary.
Use "offset" with caution.
register_kprobe() returns 0 on success, or a negative errno otherwise. register_kprobe() returns 0 on success, or a negative errno otherwise.
User's pre-handler (kp->pre_handler): User's pre-handler (kp->pre_handler):
...@@ -225,6 +246,12 @@ control to Kprobes.) If the probed function is declared asmlinkage, ...@@ -225,6 +246,12 @@ control to Kprobes.) If the probed function is declared asmlinkage,
fastcall, or anything else that affects how args are passed, the fastcall, or anything else that affects how args are passed, the
handler's declaration must match. handler's declaration must match.
NOTE: A macro JPROBE_ENTRY is provided to handle architecture-specific
aliasing of jp->entry. In the interest of portability, it is advised
to use:
jp->entry = JPROBE_ENTRY(handler);
register_jprobe() returns 0 on success, or a negative errno otherwise. register_jprobe() returns 0 on success, or a negative errno otherwise.
4.3 register_kretprobe 4.3 register_kretprobe
...@@ -251,6 +278,11 @@ of interest: ...@@ -251,6 +278,11 @@ of interest:
- ret_addr: the return address - ret_addr: the return address
- rp: points to the corresponding kretprobe object - rp: points to the corresponding kretprobe object
- task: points to the corresponding task struct - task: points to the corresponding task struct
The regs_return_value(regs) macro provides a simple abstraction to
extract the return value from the appropriate register as defined by
the architecture's ABI.
The handler's return value is currently ignored. The handler's return value is currently ignored.
4.4 unregister_*probe 4.4 unregister_*probe
...@@ -369,7 +401,6 @@ stack trace and selected i386 registers when do_fork() is called. ...@@ -369,7 +401,6 @@ stack trace and selected i386 registers when do_fork() is called.
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/kallsyms.h>
#include <linux/sched.h> #include <linux/sched.h>
/*For each probe you need to allocate a kprobe structure*/ /*For each probe you need to allocate a kprobe structure*/
...@@ -403,18 +434,14 @@ int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr) ...@@ -403,18 +434,14 @@ int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
return 0; return 0;
} }
int init_module(void) static int __init kprobe_init(void)
{ {
int ret; int ret;
kp.pre_handler = handler_pre; kp.pre_handler = handler_pre;
kp.post_handler = handler_post; kp.post_handler = handler_post;
kp.fault_handler = handler_fault; kp.fault_handler = handler_fault;
kp.addr = (kprobe_opcode_t*) kallsyms_lookup_name("do_fork"); kp.symbol_name = "do_fork";
/* register the kprobe now */
if (!kp.addr) {
printk("Couldn't find %s to plant kprobe\n", "do_fork");
return -1;
}
if ((ret = register_kprobe(&kp) < 0)) { if ((ret = register_kprobe(&kp) < 0)) {
printk("register_kprobe failed, returned %d\n", ret); printk("register_kprobe failed, returned %d\n", ret);
return -1; return -1;
...@@ -423,12 +450,14 @@ int init_module(void) ...@@ -423,12 +450,14 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void __exit kprobe_exit(void)
{ {
unregister_kprobe(&kp); unregister_kprobe(&kp);
printk("kprobe unregistered\n"); printk("kprobe unregistered\n");
} }
module_init(kprobe_init)
module_exit(kprobe_exit)
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
----- cut here ----- ----- cut here -----
...@@ -463,7 +492,6 @@ the arguments of do_fork(). ...@@ -463,7 +492,6 @@ the arguments of do_fork().
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/kallsyms.h>
/* /*
* Jumper probe for do_fork. * Jumper probe for do_fork.
...@@ -485,17 +513,13 @@ long jdo_fork(unsigned long clone_flags, unsigned long stack_start, ...@@ -485,17 +513,13 @@ long jdo_fork(unsigned long clone_flags, unsigned long stack_start,
} }
static struct jprobe my_jprobe = { static struct jprobe my_jprobe = {
.entry = (kprobe_opcode_t *) jdo_fork .entry = JPROBE_ENTRY(jdo_fork)
}; };
int init_module(void) static int __init jprobe_init(void)
{ {
int ret; int ret;
my_jprobe.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork"); my_jprobe.kp.symbol_name = "do_fork";
if (!my_jprobe.kp.addr) {
printk("Couldn't find %s to plant jprobe\n", "do_fork");
return -1;
}
if ((ret = register_jprobe(&my_jprobe)) <0) { if ((ret = register_jprobe(&my_jprobe)) <0) {
printk("register_jprobe failed, returned %d\n", ret); printk("register_jprobe failed, returned %d\n", ret);
...@@ -506,12 +530,14 @@ int init_module(void) ...@@ -506,12 +530,14 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void __exit jprobe_exit(void)
{ {
unregister_jprobe(&my_jprobe); unregister_jprobe(&my_jprobe);
printk("jprobe unregistered\n"); printk("jprobe unregistered\n");
} }
module_init(jprobe_init)
module_exit(jprobe_exit)
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
----- cut here ----- ----- cut here -----
...@@ -530,16 +556,13 @@ report failed calls to sys_open(). ...@@ -530,16 +556,13 @@ report failed calls to sys_open().
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/kallsyms.h>
static const char *probed_func = "sys_open"; static const char *probed_func = "sys_open";
/* Return-probe handler: If the probed function fails, log the return value. */ /* Return-probe handler: If the probed function fails, log the return value. */
static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs) static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{ {
// Substitute the appropriate register name for your architecture -- int retval = regs_return_value(regs);
// e.g., regs->rax for x86_64, regs->gpr[3] for ppc64.
int retval = (int) regs->eax;
if (retval < 0) { if (retval < 0) {
printk("%s returns %d\n", probed_func, retval); printk("%s returns %d\n", probed_func, retval);
} }
...@@ -552,15 +575,11 @@ static struct kretprobe my_kretprobe = { ...@@ -552,15 +575,11 @@ static struct kretprobe my_kretprobe = {
.maxactive = 20 .maxactive = 20
}; };
int init_module(void) static int __init kretprobe_init(void)
{ {
int ret; int ret;
my_kretprobe.kp.addr = my_kretprobe.kp.symbol_name = (char *)probed_func;
(kprobe_opcode_t *) kallsyms_lookup_name(probed_func);
if (!my_kretprobe.kp.addr) {
printk("Couldn't find %s to plant return probe\n", probed_func);
return -1;
}
if ((ret = register_kretprobe(&my_kretprobe)) < 0) { if ((ret = register_kretprobe(&my_kretprobe)) < 0) {
printk("register_kretprobe failed, returned %d\n", ret); printk("register_kretprobe failed, returned %d\n", ret);
return -1; return -1;
...@@ -569,7 +588,7 @@ int init_module(void) ...@@ -569,7 +588,7 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void __exit kretprobe_exit(void)
{ {
unregister_kretprobe(&my_kretprobe); unregister_kretprobe(&my_kretprobe);
printk("kretprobe unregistered\n"); printk("kretprobe unregistered\n");
...@@ -578,6 +597,8 @@ void cleanup_module(void) ...@@ -578,6 +597,8 @@ void cleanup_module(void)
my_kretprobe.nmissed, probed_func); my_kretprobe.nmissed, probed_func);
} }
module_init(kretprobe_init)
module_exit(kretprobe_exit)
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
----- cut here ----- ----- cut here -----
...@@ -590,3 +611,5 @@ messages.) ...@@ -590,3 +611,5 @@ messages.)
For additional information on Kprobes, refer to the following URLs: For additional information on Kprobes, refer to the following URLs:
http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe
http://www.redhat.com/magazine/005mar05/features/kprobes/ http://www.redhat.com/magazine/005mar05/features/kprobes/
http://www-users.cs.umn.edu/~boutcher/kprobes/
http://www.linuxsymposium.org/2006/linuxsymposium_procv2.pdf (pages 101-115)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment