diff options
author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2011-06-27 03:26:56 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2011-07-15 15:17:14 -0400 |
commit | 614243181050436785f5a621749a7da2336a7916 (patch) | |
tree | d64445cc0bc14420b993e82bd4bb4723ea8e34fa | |
parent | bc81d48d13d8839fae6833c95794c403b2133f36 (diff) |
tracing/kprobes: Support module init function probing
To support probing module init functions, kprobe-tracer allows
user to define a probe on non-existed function when it is given
with a module name. This also enables user to set a probe on
a function on a specific module, even if a same name (but different)
function is locally defined in another module.
The module name must be in the front of function name and separated
by a ':'. e.g. btrfs:btrfs_init_sysfs
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lkml.kernel.org/r/20110627072656.6528.89970.stgit@fedora15
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | Documentation/trace/kprobetrace.txt | 9 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 164 |
2 files changed, 143 insertions, 30 deletions
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt index c83bd6b4e6e8..d0d0bb9e3e25 100644 --- a/Documentation/trace/kprobetrace.txt +++ b/Documentation/trace/kprobetrace.txt | |||
@@ -22,14 +22,15 @@ current_tracer. Instead of that, add probe points via | |||
22 | 22 | ||
23 | Synopsis of kprobe_events | 23 | Synopsis of kprobe_events |
24 | ------------------------- | 24 | ------------------------- |
25 | p[:[GRP/]EVENT] SYMBOL[+offs]|MEMADDR [FETCHARGS] : Set a probe | 25 | p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : Set a probe |
26 | r[:[GRP/]EVENT] SYMBOL[+0] [FETCHARGS] : Set a return probe | 26 | r[:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : Set a return probe |
27 | -:[GRP/]EVENT : Clear a probe | 27 | -:[GRP/]EVENT : Clear a probe |
28 | 28 | ||
29 | GRP : Group name. If omitted, use "kprobes" for it. | 29 | GRP : Group name. If omitted, use "kprobes" for it. |
30 | EVENT : Event name. If omitted, the event name is generated | 30 | EVENT : Event name. If omitted, the event name is generated |
31 | based on SYMBOL+offs or MEMADDR. | 31 | based on SYM+offs or MEMADDR. |
32 | SYMBOL[+offs] : Symbol+offset where the probe is inserted. | 32 | MOD : Module name which has given SYM. |
33 | SYM[+offs] : Symbol+offset where the probe is inserted. | ||
33 | MEMADDR : Address where the probe is inserted. | 34 | MEMADDR : Address where the probe is inserted. |
34 | 35 | ||
35 | FETCHARGS : Arguments. Each probe can have up to 128 args. | 36 | FETCHARGS : Arguments. Each probe can have up to 128 args. |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 3be50c52d080..acc6664a6b22 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -536,6 +536,7 @@ struct probe_arg { | |||
536 | /* Flags for trace_probe */ | 536 | /* Flags for trace_probe */ |
537 | #define TP_FLAG_TRACE 1 | 537 | #define TP_FLAG_TRACE 1 |
538 | #define TP_FLAG_PROFILE 2 | 538 | #define TP_FLAG_PROFILE 2 |
539 | #define TP_FLAG_REGISTERED 4 | ||
539 | 540 | ||
540 | struct trace_probe { | 541 | struct trace_probe { |
541 | struct list_head list; | 542 | struct list_head list; |
@@ -565,6 +566,39 @@ static __kprobes const char *trace_probe_symbol(struct trace_probe *tp) | |||
565 | return tp->symbol ? tp->symbol : "unknown"; | 566 | return tp->symbol ? tp->symbol : "unknown"; |
566 | } | 567 | } |
567 | 568 | ||
569 | static __kprobes unsigned long trace_probe_offset(struct trace_probe *tp) | ||
570 | { | ||
571 | return tp->rp.kp.offset; | ||
572 | } | ||
573 | |||
574 | static __kprobes bool trace_probe_is_enabled(struct trace_probe *tp) | ||
575 | { | ||
576 | return !!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE)); | ||
577 | } | ||
578 | |||
579 | static __kprobes bool trace_probe_is_registered(struct trace_probe *tp) | ||
580 | { | ||
581 | return !!(tp->flags & TP_FLAG_REGISTERED); | ||
582 | } | ||
583 | |||
584 | static __kprobes bool trace_probe_has_gone(struct trace_probe *tp) | ||
585 | { | ||
586 | return !!(kprobe_gone(&tp->rp.kp)); | ||
587 | } | ||
588 | |||
589 | static __kprobes bool trace_probe_within_module(struct trace_probe *tp, | ||
590 | struct module *mod) | ||
591 | { | ||
592 | int len = strlen(mod->name); | ||
593 | const char *name = trace_probe_symbol(tp); | ||
594 | return strncmp(mod->name, name, len) == 0 && name[len] == ':'; | ||
595 | } | ||
596 | |||
597 | static __kprobes bool trace_probe_is_on_module(struct trace_probe *tp) | ||
598 | { | ||
599 | return !!strchr(trace_probe_symbol(tp), ':'); | ||
600 | } | ||
601 | |||
568 | static int register_probe_event(struct trace_probe *tp); | 602 | static int register_probe_event(struct trace_probe *tp); |
569 | static void unregister_probe_event(struct trace_probe *tp); | 603 | static void unregister_probe_event(struct trace_probe *tp); |
570 | 604 | ||
@@ -689,7 +723,8 @@ static int enable_trace_probe(struct trace_probe *tp, int flag) | |||
689 | int ret = 0; | 723 | int ret = 0; |
690 | 724 | ||
691 | tp->flags |= flag; | 725 | tp->flags |= flag; |
692 | if (tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE)) { | 726 | if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) && |
727 | !trace_probe_has_gone(tp)) { | ||
693 | if (trace_probe_is_return(tp)) | 728 | if (trace_probe_is_return(tp)) |
694 | ret = enable_kretprobe(&tp->rp); | 729 | ret = enable_kretprobe(&tp->rp); |
695 | else | 730 | else |
@@ -703,7 +738,7 @@ static int enable_trace_probe(struct trace_probe *tp, int flag) | |||
703 | static void disable_trace_probe(struct trace_probe *tp, int flag) | 738 | static void disable_trace_probe(struct trace_probe *tp, int flag) |
704 | { | 739 | { |
705 | tp->flags &= ~flag; | 740 | tp->flags &= ~flag; |
706 | if (!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE))) { | 741 | if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) { |
707 | if (trace_probe_is_return(tp)) | 742 | if (trace_probe_is_return(tp)) |
708 | disable_kretprobe(&tp->rp); | 743 | disable_kretprobe(&tp->rp); |
709 | else | 744 | else |
@@ -711,13 +746,64 @@ static void disable_trace_probe(struct trace_probe *tp, int flag) | |||
711 | } | 746 | } |
712 | } | 747 | } |
713 | 748 | ||
714 | /* Unregister a trace_probe and probe_event: call with locking probe_lock */ | 749 | /* Internal register function - just handle k*probes and flags */ |
715 | static void unregister_trace_probe(struct trace_probe *tp) | 750 | static int __register_trace_probe(struct trace_probe *tp) |
716 | { | 751 | { |
752 | int ret; | ||
753 | |||
754 | if (trace_probe_is_registered(tp)) | ||
755 | return -EINVAL; | ||
756 | |||
757 | /* Set/clear disabled flag according to tp->flag */ | ||
758 | if (trace_probe_is_enabled(tp)) | ||
759 | tp->rp.kp.flags &= ~KPROBE_FLAG_DISABLED; | ||
760 | else | ||
761 | tp->rp.kp.flags |= KPROBE_FLAG_DISABLED; | ||
762 | |||
717 | if (trace_probe_is_return(tp)) | 763 | if (trace_probe_is_return(tp)) |
718 | unregister_kretprobe(&tp->rp); | 764 | ret = register_kretprobe(&tp->rp); |
719 | else | 765 | else |
720 | unregister_kprobe(&tp->rp.kp); | 766 | ret = register_kprobe(&tp->rp.kp); |
767 | |||
768 | if (ret == 0) | ||
769 | tp->flags |= TP_FLAG_REGISTERED; | ||
770 | else { | ||
771 | pr_warning("Could not insert probe at %s+%lu: %d\n", | ||
772 | trace_probe_symbol(tp), trace_probe_offset(tp), ret); | ||
773 | if (ret == -ENOENT && trace_probe_is_on_module(tp)) { | ||
774 | pr_warning("This probe might be able to register after" | ||
775 | "target module is loaded. Continue.\n"); | ||
776 | ret = 0; | ||
777 | } else if (ret == -EILSEQ) { | ||
778 | pr_warning("Probing address(0x%p) is not an " | ||
779 | "instruction boundary.\n", | ||
780 | tp->rp.kp.addr); | ||
781 | ret = -EINVAL; | ||
782 | } | ||
783 | } | ||
784 | |||
785 | return ret; | ||
786 | } | ||
787 | |||
788 | /* Internal unregister function - just handle k*probes and flags */ | ||
789 | static void __unregister_trace_probe(struct trace_probe *tp) | ||
790 | { | ||
791 | if (trace_probe_is_registered(tp)) { | ||
792 | if (trace_probe_is_return(tp)) | ||
793 | unregister_kretprobe(&tp->rp); | ||
794 | else | ||
795 | unregister_kprobe(&tp->rp.kp); | ||
796 | tp->flags &= ~TP_FLAG_REGISTERED; | ||
797 | /* Cleanup kprobe for reuse */ | ||
798 | if (tp->rp.kp.symbol_name) | ||
799 | tp->rp.kp.addr = NULL; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | /* Unregister a trace_probe and probe_event: call with locking probe_lock */ | ||
804 | static void unregister_trace_probe(struct trace_probe *tp) | ||
805 | { | ||
806 | __unregister_trace_probe(tp); | ||
721 | list_del(&tp->list); | 807 | list_del(&tp->list); |
722 | unregister_probe_event(tp); | 808 | unregister_probe_event(tp); |
723 | } | 809 | } |
@@ -730,41 +816,65 @@ static int register_trace_probe(struct trace_probe *tp) | |||
730 | 816 | ||
731 | mutex_lock(&probe_lock); | 817 | mutex_lock(&probe_lock); |
732 | 818 | ||
733 | /* register as an event */ | 819 | /* Delete old (same name) event if exist */ |
734 | old_tp = find_trace_probe(tp->call.name, tp->call.class->system); | 820 | old_tp = find_trace_probe(tp->call.name, tp->call.class->system); |
735 | if (old_tp) { | 821 | if (old_tp) { |
736 | /* delete old event */ | ||
737 | unregister_trace_probe(old_tp); | 822 | unregister_trace_probe(old_tp); |
738 | free_trace_probe(old_tp); | 823 | free_trace_probe(old_tp); |
739 | } | 824 | } |
825 | |||
826 | /* Register new event */ | ||
740 | ret = register_probe_event(tp); | 827 | ret = register_probe_event(tp); |
741 | if (ret) { | 828 | if (ret) { |
742 | pr_warning("Failed to register probe event(%d)\n", ret); | 829 | pr_warning("Failed to register probe event(%d)\n", ret); |
743 | goto end; | 830 | goto end; |
744 | } | 831 | } |
745 | 832 | ||
746 | tp->rp.kp.flags |= KPROBE_FLAG_DISABLED; | 833 | /* Register k*probe */ |
747 | if (trace_probe_is_return(tp)) | 834 | ret = __register_trace_probe(tp); |
748 | ret = register_kretprobe(&tp->rp); | 835 | if (ret < 0) |
749 | else | ||
750 | ret = register_kprobe(&tp->rp.kp); | ||
751 | |||
752 | if (ret) { | ||
753 | pr_warning("Could not insert probe(%d)\n", ret); | ||
754 | if (ret == -EILSEQ) { | ||
755 | pr_warning("Probing address(0x%p) is not an " | ||
756 | "instruction boundary.\n", | ||
757 | tp->rp.kp.addr); | ||
758 | ret = -EINVAL; | ||
759 | } | ||
760 | unregister_probe_event(tp); | 836 | unregister_probe_event(tp); |
761 | } else | 837 | else |
762 | list_add_tail(&tp->list, &probe_list); | 838 | list_add_tail(&tp->list, &probe_list); |
839 | |||
763 | end: | 840 | end: |
764 | mutex_unlock(&probe_lock); | 841 | mutex_unlock(&probe_lock); |
765 | return ret; | 842 | return ret; |
766 | } | 843 | } |
767 | 844 | ||
845 | /* Module notifier call back, checking event on the module */ | ||
846 | static int trace_probe_module_callback(struct notifier_block *nb, | ||
847 | unsigned long val, void *data) | ||
848 | { | ||
849 | struct module *mod = data; | ||
850 | struct trace_probe *tp; | ||
851 | int ret; | ||
852 | |||
853 | if (val != MODULE_STATE_COMING) | ||
854 | return NOTIFY_DONE; | ||
855 | |||
856 | /* Update probes on coming module */ | ||
857 | mutex_lock(&probe_lock); | ||
858 | list_for_each_entry(tp, &probe_list, list) { | ||
859 | if (trace_probe_within_module(tp, mod)) { | ||
860 | __unregister_trace_probe(tp); | ||
861 | ret = __register_trace_probe(tp); | ||
862 | if (ret) | ||
863 | pr_warning("Failed to re-register probe %s on" | ||
864 | "%s: %d\n", | ||
865 | tp->call.name, mod->name, ret); | ||
866 | } | ||
867 | } | ||
868 | mutex_unlock(&probe_lock); | ||
869 | |||
870 | return NOTIFY_DONE; | ||
871 | } | ||
872 | |||
873 | static struct notifier_block trace_probe_module_nb = { | ||
874 | .notifier_call = trace_probe_module_callback, | ||
875 | .priority = 1 /* Invoked after kprobe module callback */ | ||
876 | }; | ||
877 | |||
768 | /* Split symbol and offset. */ | 878 | /* Split symbol and offset. */ |
769 | static int split_symbol_offset(char *symbol, unsigned long *offset) | 879 | static int split_symbol_offset(char *symbol, unsigned long *offset) |
770 | { | 880 | { |
@@ -990,8 +1100,8 @@ static int create_trace_probe(int argc, char **argv) | |||
990 | { | 1100 | { |
991 | /* | 1101 | /* |
992 | * Argument syntax: | 1102 | * Argument syntax: |
993 | * - Add kprobe: p[:[GRP/]EVENT] KSYM[+OFFS]|KADDR [FETCHARGS] | 1103 | * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS] |
994 | * - Add kretprobe: r[:[GRP/]EVENT] KSYM[+0] [FETCHARGS] | 1104 | * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS] |
995 | * Fetch args: | 1105 | * Fetch args: |
996 | * $retval : fetch return value | 1106 | * $retval : fetch return value |
997 | * $stack : fetch stack address | 1107 | * $stack : fetch stack address |
@@ -1186,7 +1296,6 @@ static void release_all_trace_probes(void) | |||
1186 | mutex_unlock(&probe_lock); | 1296 | mutex_unlock(&probe_lock); |
1187 | } | 1297 | } |
1188 | 1298 | ||
1189 | |||
1190 | /* Probes listing interfaces */ | 1299 | /* Probes listing interfaces */ |
1191 | static void *probes_seq_start(struct seq_file *m, loff_t *pos) | 1300 | static void *probes_seq_start(struct seq_file *m, loff_t *pos) |
1192 | { | 1301 | { |
@@ -1827,6 +1936,9 @@ static __init int init_kprobe_trace(void) | |||
1827 | struct dentry *d_tracer; | 1936 | struct dentry *d_tracer; |
1828 | struct dentry *entry; | 1937 | struct dentry *entry; |
1829 | 1938 | ||
1939 | if (register_module_notifier(&trace_probe_module_nb)) | ||
1940 | return -EINVAL; | ||
1941 | |||
1830 | d_tracer = tracing_init_dentry(); | 1942 | d_tracer = tracing_init_dentry(); |
1831 | if (!d_tracer) | 1943 | if (!d_tracer) |
1832 | return 0; | 1944 | return 0; |