diff options
-rw-r--r-- | Documentation/kprobes.txt | 89 |
1 files changed, 56 insertions, 33 deletions
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index 2c3b1eae4280..ba26201d5023 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt | |||
@@ -151,9 +151,9 @@ So that you can load and unload Kprobes-based instrumentation modules, | |||
151 | make sure "Loadable module support" (CONFIG_MODULES) and "Module | 151 | make sure "Loadable module support" (CONFIG_MODULES) and "Module |
152 | unloading" (CONFIG_MODULE_UNLOAD) are set to "y". | 152 | unloading" (CONFIG_MODULE_UNLOAD) are set to "y". |
153 | 153 | ||
154 | You may also want to ensure that CONFIG_KALLSYMS and perhaps even | 154 | Also make sure that CONFIG_KALLSYMS and perhaps even CONFIG_KALLSYMS_ALL |
155 | CONFIG_KALLSYMS_ALL are set to "y", since kallsyms_lookup_name() | 155 | are set to "y", since kallsyms_lookup_name() is used by the in-kernel |
156 | is a handy, version-independent way to find a function's address. | 156 | kprobe address resolution code. |
157 | 157 | ||
158 | If you need to insert a probe in the middle of a function, you may find | 158 | If you need to insert a probe in the middle of a function, you may find |
159 | it useful to "Compile the kernel with debug info" (CONFIG_DEBUG_INFO), | 159 | 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 | or during single-stepping of the probed instruction, Kprobes calls | 179 | or during single-stepping of the probed instruction, Kprobes calls |
180 | kp->fault_handler. Any or all handlers can be NULL. | 180 | kp->fault_handler. Any or all handlers can be NULL. |
181 | 181 | ||
182 | NOTE: | ||
183 | 1. With the introduction of the "symbol_name" field to struct kprobe, | ||
184 | the probepoint address resolution will now be taken care of by the kernel. | ||
185 | The following will now work: | ||
186 | |||
187 | kp.symbol_name = "symbol_name"; | ||
188 | |||
189 | (64-bit powerpc intricacies such as function descriptors are handled | ||
190 | transparently) | ||
191 | |||
192 | 2. Use the "offset" field of struct kprobe if the offset into the symbol | ||
193 | to install a probepoint is known. This field is used to calculate the | ||
194 | probepoint. | ||
195 | |||
196 | 3. Specify either the kprobe "symbol_name" OR the "addr". If both are | ||
197 | specified, kprobe registration will fail with -EINVAL. | ||
198 | |||
199 | 4. With CISC architectures (such as i386 and x86_64), the kprobes code | ||
200 | does not validate if the kprobe.addr is at an instruction boundary. | ||
201 | Use "offset" with caution. | ||
202 | |||
182 | register_kprobe() returns 0 on success, or a negative errno otherwise. | 203 | register_kprobe() returns 0 on success, or a negative errno otherwise. |
183 | 204 | ||
184 | User's pre-handler (kp->pre_handler): | 205 | User's pre-handler (kp->pre_handler): |
@@ -225,6 +246,12 @@ control to Kprobes.) If the probed function is declared asmlinkage, | |||
225 | fastcall, or anything else that affects how args are passed, the | 246 | fastcall, or anything else that affects how args are passed, the |
226 | handler's declaration must match. | 247 | handler's declaration must match. |
227 | 248 | ||
249 | NOTE: A macro JPROBE_ENTRY is provided to handle architecture-specific | ||
250 | aliasing of jp->entry. In the interest of portability, it is advised | ||
251 | to use: | ||
252 | |||
253 | jp->entry = JPROBE_ENTRY(handler); | ||
254 | |||
228 | register_jprobe() returns 0 on success, or a negative errno otherwise. | 255 | register_jprobe() returns 0 on success, or a negative errno otherwise. |
229 | 256 | ||
230 | 4.3 register_kretprobe | 257 | 4.3 register_kretprobe |
@@ -251,6 +278,11 @@ of interest: | |||
251 | - ret_addr: the return address | 278 | - ret_addr: the return address |
252 | - rp: points to the corresponding kretprobe object | 279 | - rp: points to the corresponding kretprobe object |
253 | - task: points to the corresponding task struct | 280 | - task: points to the corresponding task struct |
281 | |||
282 | The regs_return_value(regs) macro provides a simple abstraction to | ||
283 | extract the return value from the appropriate register as defined by | ||
284 | the architecture's ABI. | ||
285 | |||
254 | The handler's return value is currently ignored. | 286 | The handler's return value is currently ignored. |
255 | 287 | ||
256 | 4.4 unregister_*probe | 288 | 4.4 unregister_*probe |
@@ -369,7 +401,6 @@ stack trace and selected i386 registers when do_fork() is called. | |||
369 | #include <linux/kernel.h> | 401 | #include <linux/kernel.h> |
370 | #include <linux/module.h> | 402 | #include <linux/module.h> |
371 | #include <linux/kprobes.h> | 403 | #include <linux/kprobes.h> |
372 | #include <linux/kallsyms.h> | ||
373 | #include <linux/sched.h> | 404 | #include <linux/sched.h> |
374 | 405 | ||
375 | /*For each probe you need to allocate a kprobe structure*/ | 406 | /*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 | return 0; | 434 | return 0; |
404 | } | 435 | } |
405 | 436 | ||
406 | int init_module(void) | 437 | static int __init kprobe_init(void) |
407 | { | 438 | { |
408 | int ret; | 439 | int ret; |
409 | kp.pre_handler = handler_pre; | 440 | kp.pre_handler = handler_pre; |
410 | kp.post_handler = handler_post; | 441 | kp.post_handler = handler_post; |
411 | kp.fault_handler = handler_fault; | 442 | kp.fault_handler = handler_fault; |
412 | kp.addr = (kprobe_opcode_t*) kallsyms_lookup_name("do_fork"); | 443 | kp.symbol_name = "do_fork"; |
413 | /* register the kprobe now */ | 444 | |
414 | if (!kp.addr) { | ||
415 | printk("Couldn't find %s to plant kprobe\n", "do_fork"); | ||
416 | return -1; | ||
417 | } | ||
418 | if ((ret = register_kprobe(&kp) < 0)) { | 445 | if ((ret = register_kprobe(&kp) < 0)) { |
419 | printk("register_kprobe failed, returned %d\n", ret); | 446 | printk("register_kprobe failed, returned %d\n", ret); |
420 | return -1; | 447 | return -1; |
@@ -423,12 +450,14 @@ int init_module(void) | |||
423 | return 0; | 450 | return 0; |
424 | } | 451 | } |
425 | 452 | ||
426 | void cleanup_module(void) | 453 | static void __exit kprobe_exit(void) |
427 | { | 454 | { |
428 | unregister_kprobe(&kp); | 455 | unregister_kprobe(&kp); |
429 | printk("kprobe unregistered\n"); | 456 | printk("kprobe unregistered\n"); |
430 | } | 457 | } |
431 | 458 | ||
459 | module_init(kprobe_init) | ||
460 | module_exit(kprobe_exit) | ||
432 | MODULE_LICENSE("GPL"); | 461 | MODULE_LICENSE("GPL"); |
433 | ----- cut here ----- | 462 | ----- cut here ----- |
434 | 463 | ||
@@ -463,7 +492,6 @@ the arguments of do_fork(). | |||
463 | #include <linux/fs.h> | 492 | #include <linux/fs.h> |
464 | #include <linux/uio.h> | 493 | #include <linux/uio.h> |
465 | #include <linux/kprobes.h> | 494 | #include <linux/kprobes.h> |
466 | #include <linux/kallsyms.h> | ||
467 | 495 | ||
468 | /* | 496 | /* |
469 | * Jumper probe for do_fork. | 497 | * Jumper probe for do_fork. |
@@ -485,17 +513,13 @@ long jdo_fork(unsigned long clone_flags, unsigned long stack_start, | |||
485 | } | 513 | } |
486 | 514 | ||
487 | static struct jprobe my_jprobe = { | 515 | static struct jprobe my_jprobe = { |
488 | .entry = (kprobe_opcode_t *) jdo_fork | 516 | .entry = JPROBE_ENTRY(jdo_fork) |
489 | }; | 517 | }; |
490 | 518 | ||
491 | int init_module(void) | 519 | static int __init jprobe_init(void) |
492 | { | 520 | { |
493 | int ret; | 521 | int ret; |
494 | my_jprobe.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork"); | 522 | my_jprobe.kp.symbol_name = "do_fork"; |
495 | if (!my_jprobe.kp.addr) { | ||
496 | printk("Couldn't find %s to plant jprobe\n", "do_fork"); | ||
497 | return -1; | ||
498 | } | ||
499 | 523 | ||
500 | if ((ret = register_jprobe(&my_jprobe)) <0) { | 524 | if ((ret = register_jprobe(&my_jprobe)) <0) { |
501 | printk("register_jprobe failed, returned %d\n", ret); | 525 | printk("register_jprobe failed, returned %d\n", ret); |
@@ -506,12 +530,14 @@ int init_module(void) | |||
506 | return 0; | 530 | return 0; |
507 | } | 531 | } |
508 | 532 | ||
509 | void cleanup_module(void) | 533 | static void __exit jprobe_exit(void) |
510 | { | 534 | { |
511 | unregister_jprobe(&my_jprobe); | 535 | unregister_jprobe(&my_jprobe); |
512 | printk("jprobe unregistered\n"); | 536 | printk("jprobe unregistered\n"); |
513 | } | 537 | } |
514 | 538 | ||
539 | module_init(jprobe_init) | ||
540 | module_exit(jprobe_exit) | ||
515 | MODULE_LICENSE("GPL"); | 541 | MODULE_LICENSE("GPL"); |
516 | ----- cut here ----- | 542 | ----- cut here ----- |
517 | 543 | ||
@@ -530,16 +556,13 @@ report failed calls to sys_open(). | |||
530 | #include <linux/kernel.h> | 556 | #include <linux/kernel.h> |
531 | #include <linux/module.h> | 557 | #include <linux/module.h> |
532 | #include <linux/kprobes.h> | 558 | #include <linux/kprobes.h> |
533 | #include <linux/kallsyms.h> | ||
534 | 559 | ||
535 | static const char *probed_func = "sys_open"; | 560 | static const char *probed_func = "sys_open"; |
536 | 561 | ||
537 | /* Return-probe handler: If the probed function fails, log the return value. */ | 562 | /* Return-probe handler: If the probed function fails, log the return value. */ |
538 | static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs) | 563 | static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs) |
539 | { | 564 | { |
540 | // Substitute the appropriate register name for your architecture -- | 565 | int retval = regs_return_value(regs); |
541 | // e.g., regs->rax for x86_64, regs->gpr[3] for ppc64. | ||
542 | int retval = (int) regs->eax; | ||
543 | if (retval < 0) { | 566 | if (retval < 0) { |
544 | printk("%s returns %d\n", probed_func, retval); | 567 | printk("%s returns %d\n", probed_func, retval); |
545 | } | 568 | } |
@@ -552,15 +575,11 @@ static struct kretprobe my_kretprobe = { | |||
552 | .maxactive = 20 | 575 | .maxactive = 20 |
553 | }; | 576 | }; |
554 | 577 | ||
555 | int init_module(void) | 578 | static int __init kretprobe_init(void) |
556 | { | 579 | { |
557 | int ret; | 580 | int ret; |
558 | my_kretprobe.kp.addr = | 581 | my_kretprobe.kp.symbol_name = (char *)probed_func; |
559 | (kprobe_opcode_t *) kallsyms_lookup_name(probed_func); | 582 | |
560 | if (!my_kretprobe.kp.addr) { | ||
561 | printk("Couldn't find %s to plant return probe\n", probed_func); | ||
562 | return -1; | ||
563 | } | ||
564 | if ((ret = register_kretprobe(&my_kretprobe)) < 0) { | 583 | if ((ret = register_kretprobe(&my_kretprobe)) < 0) { |
565 | printk("register_kretprobe failed, returned %d\n", ret); | 584 | printk("register_kretprobe failed, returned %d\n", ret); |
566 | return -1; | 585 | return -1; |
@@ -569,7 +588,7 @@ int init_module(void) | |||
569 | return 0; | 588 | return 0; |
570 | } | 589 | } |
571 | 590 | ||
572 | void cleanup_module(void) | 591 | static void __exit kretprobe_exit(void) |
573 | { | 592 | { |
574 | unregister_kretprobe(&my_kretprobe); | 593 | unregister_kretprobe(&my_kretprobe); |
575 | printk("kretprobe unregistered\n"); | 594 | printk("kretprobe unregistered\n"); |
@@ -578,6 +597,8 @@ void cleanup_module(void) | |||
578 | my_kretprobe.nmissed, probed_func); | 597 | my_kretprobe.nmissed, probed_func); |
579 | } | 598 | } |
580 | 599 | ||
600 | module_init(kretprobe_init) | ||
601 | module_exit(kretprobe_exit) | ||
581 | MODULE_LICENSE("GPL"); | 602 | MODULE_LICENSE("GPL"); |
582 | ----- cut here ----- | 603 | ----- cut here ----- |
583 | 604 | ||
@@ -590,3 +611,5 @@ messages.) | |||
590 | For additional information on Kprobes, refer to the following URLs: | 611 | For additional information on Kprobes, refer to the following URLs: |
591 | http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe | 612 | http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe |
592 | http://www.redhat.com/magazine/005mar05/features/kprobes/ | 613 | http://www.redhat.com/magazine/005mar05/features/kprobes/ |
614 | http://www-users.cs.umn.edu/~boutcher/kprobes/ | ||
615 | http://www.linuxsymposium.org/2006/linuxsymposium_procv2.pdf (pages 101-115) | ||