diff options
Diffstat (limited to 'Documentation/kprobes.txt')
| -rw-r--r-- | Documentation/kprobes.txt | 243 |
1 files changed, 5 insertions, 238 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 |
