diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2009-09-10 19:53:38 -0400 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-09-11 00:08:00 -0400 |
commit | eca0d916f6429785bbc88db3ff66631cde62b432 (patch) | |
tree | ba4ddf9900d128e7c8c24b6ee931eace0aad6a36 | |
parent | e08d1c657f70bcaca11401cd6ac5c8fe59bd2bb7 (diff) |
tracing/kprobes: Add argument name support
Add argument name assignment support and remove "alias" lines from format.
This allows user to assign unique name to each argument. For example,
$ echo p do_sys_open dfd=a0 filename=a1 flags=a2 mode=a3 > kprobe_events
This assigns dfd, filename, flags, and mode to 1st - 4th arguments
respectively. Trace buffer shows those names too.
<...>-1439 [000] 1200885.933147: do_sys_open+0x0/0xdf: dfd=ffffff9c filename=bfa898ac flags=8000 mode=0
This helps users to know what each value means.
Users can filter each events by these names too. Note that you can not
filter by argN anymore.
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jason Baron <jbaron@redhat.com>
Cc: K.Prasad <prasad@linux.vnet.ibm.com>
Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <20090910235337.22412.77383.stgit@dhcp-100-2-132.bos.redhat.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
-rw-r--r-- | Documentation/trace/kprobetrace.txt | 46 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 128 |
2 files changed, 84 insertions, 90 deletions
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt index 8f882ebd1368..aaa6c1067c78 100644 --- a/Documentation/trace/kprobetrace.txt +++ b/Documentation/trace/kprobetrace.txt | |||
@@ -42,7 +42,8 @@ Synopsis of kprobe_events | |||
42 | aN : Fetch function argument. (N >= 0)(*) | 42 | aN : Fetch function argument. (N >= 0)(*) |
43 | rv : Fetch return value.(**) | 43 | rv : Fetch return value.(**) |
44 | ra : Fetch return address.(**) | 44 | ra : Fetch return address.(**) |
45 | +|-offs(FETCHARG) : fetch memory at FETCHARG +|- offs address.(***) | 45 | +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(***) |
46 | NAME=FETCHARG: Set NAME as the argument name of FETCHARG. | ||
46 | 47 | ||
47 | (*) aN may not correct on asmlinkaged functions and at the middle of | 48 | (*) aN may not correct on asmlinkaged functions and at the middle of |
48 | function body. | 49 | function body. |
@@ -62,12 +63,10 @@ enabled: | |||
62 | You can enable/disable the probe by writing 1 or 0 on it. | 63 | You can enable/disable the probe by writing 1 or 0 on it. |
63 | 64 | ||
64 | format: | 65 | format: |
65 | This shows the format of this probe event. It also shows aliases of arguments | 66 | This shows the format of this probe event. |
66 | which you specified to kprobe_events. | ||
67 | 67 | ||
68 | filter: | 68 | filter: |
69 | You can write filtering rules of this event. And you can use both of aliase | 69 | You can write filtering rules of this event. |
70 | names and field names for describing filters. | ||
71 | 70 | ||
72 | id: | 71 | id: |
73 | This shows the id of this probe event. | 72 | This shows the id of this probe event. |
@@ -85,10 +84,11 @@ Usage examples | |||
85 | To add a probe as a new event, write a new definition to kprobe_events | 84 | To add a probe as a new event, write a new definition to kprobe_events |
86 | as below. | 85 | as below. |
87 | 86 | ||
88 | echo p:myprobe do_sys_open a0 a1 a2 a3 > /sys/kernel/debug/tracing/kprobe_events | 87 | echo p:myprobe do_sys_open dfd=a0 filename=a1 flags=a2 mode=a3 > /sys/kernel/debug/tracing/kprobe_events |
89 | 88 | ||
90 | This sets a kprobe on the top of do_sys_open() function with recording | 89 | This sets a kprobe on the top of do_sys_open() function with recording |
91 | 1st to 4th arguments as "myprobe" event. | 90 | 1st to 4th arguments as "myprobe" event. As this example shows, users can |
91 | choose more familiar names for each arguments. | ||
92 | 92 | ||
93 | echo r:myretprobe do_sys_open rv ra >> /sys/kernel/debug/tracing/kprobe_events | 93 | echo r:myretprobe do_sys_open rv ra >> /sys/kernel/debug/tracing/kprobe_events |
94 | 94 | ||
@@ -99,7 +99,7 @@ recording return value and return address as "myretprobe" event. | |||
99 | 99 | ||
100 | cat /sys/kernel/debug/tracing/events/kprobes/myprobe/format | 100 | cat /sys/kernel/debug/tracing/events/kprobes/myprobe/format |
101 | name: myprobe | 101 | name: myprobe |
102 | ID: 23 | 102 | ID: 75 |
103 | format: | 103 | format: |
104 | field:unsigned short common_type; offset:0; size:2; | 104 | field:unsigned short common_type; offset:0; size:2; |
105 | field:unsigned char common_flags; offset:2; size:1; | 105 | field:unsigned char common_flags; offset:2; size:1; |
@@ -109,21 +109,15 @@ format: | |||
109 | 109 | ||
110 | field: unsigned long ip; offset:16;tsize:8; | 110 | field: unsigned long ip; offset:16;tsize:8; |
111 | field: int nargs; offset:24;tsize:4; | 111 | field: int nargs; offset:24;tsize:4; |
112 | field: unsigned long arg0; offset:32;tsize:8; | 112 | field: unsigned long dfd; offset:32;tsize:8; |
113 | field: unsigned long arg1; offset:40;tsize:8; | 113 | field: unsigned long filename; offset:40;tsize:8; |
114 | field: unsigned long arg2; offset:48;tsize:8; | 114 | field: unsigned long flags; offset:48;tsize:8; |
115 | field: unsigned long arg3; offset:56;tsize:8; | 115 | field: unsigned long mode; offset:56;tsize:8; |
116 | 116 | ||
117 | alias: a0; original: arg0; | 117 | print fmt: "%lx: dfd=%lx filename=%lx flags=%lx mode=%lx", ip, REC->dfd, REC->filename, REC->flags, REC->mode |
118 | alias: a1; original: arg1; | ||
119 | alias: a2; original: arg2; | ||
120 | alias: a3; original: arg3; | ||
121 | 118 | ||
122 | print fmt: "%lx: 0x%lx 0x%lx 0x%lx 0x%lx", ip, arg0, arg1, arg2, arg3 | ||
123 | 119 | ||
124 | 120 | You can see that the event has 4 arguments as in the expressions you specified. | |
125 | You can see that the event has 4 arguments and alias expressions | ||
126 | corresponding to it. | ||
127 | 121 | ||
128 | echo > /sys/kernel/debug/tracing/kprobe_events | 122 | echo > /sys/kernel/debug/tracing/kprobe_events |
129 | 123 | ||
@@ -135,12 +129,12 @@ corresponding to it. | |||
135 | # | 129 | # |
136 | # TASK-PID CPU# TIMESTAMP FUNCTION | 130 | # TASK-PID CPU# TIMESTAMP FUNCTION |
137 | # | | | | | | 131 | # | | | | | |
138 | <...>-1447 [001] 1038282.286875: do_sys_open+0x0/0xd6: 0x3 0x7fffd1ec4440 0x8000 0x0 | 132 | <...>-1447 [001] 1038282.286875: do_sys_open+0x0/0xd6: dfd=3 filename=7fffd1ec4440 flags=8000 mode=0 |
139 | <...>-1447 [001] 1038282.286878: sys_openat+0xc/0xe <- do_sys_open: 0xfffffffffffffffe 0xffffffff81367a3a | 133 | <...>-1447 [001] 1038282.286878: sys_openat+0xc/0xe <- do_sys_open: rv=fffffffffffffffe ra=ffffffff81367a3a |
140 | <...>-1447 [001] 1038282.286885: do_sys_open+0x0/0xd6: 0xffffff9c 0x40413c 0x8000 0x1b6 | 134 | <...>-1447 [001] 1038282.286885: do_sys_open+0x0/0xd6: dfd=ffffff9c filename=40413c flags=8000 mode=1b6 |
141 | <...>-1447 [001] 1038282.286915: sys_open+0x1b/0x1d <- do_sys_open: 0x3 0xffffffff81367a3a | 135 | <...>-1447 [001] 1038282.286915: sys_open+0x1b/0x1d <- do_sys_open: rv=3 ra=ffffffff81367a3a |
142 | <...>-1447 [001] 1038282.286969: do_sys_open+0x0/0xd6: 0xffffff9c 0x4041c6 0x98800 0x10 | 136 | <...>-1447 [001] 1038282.286969: do_sys_open+0x0/0xd6: dfd=ffffff9c filename=4041c6 flags=98800 mode=10 |
143 | <...>-1447 [001] 1038282.286976: sys_open+0x1b/0x1d <- do_sys_open: 0x3 0xffffffff81367a3a | 137 | <...>-1447 [001] 1038282.286976: sys_open+0x1b/0x1d <- do_sys_open: rv=3 ra=ffffffff81367a3a |
144 | 138 | ||
145 | 139 | ||
146 | Each line shows when the kernel hits a probe, and <- SYMBOL means kernel | 140 | Each line shows when the kernel hits a probe, and <- SYMBOL means kernel |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 730e992d28da..44dad1aa95d3 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -176,9 +176,14 @@ static __kprobes void free_indirect_fetch_data(struct indirect_fetch_data *data) | |||
176 | } | 176 | } |
177 | 177 | ||
178 | /** | 178 | /** |
179 | * kprobe_trace_core | 179 | * Kprobe tracer core functions |
180 | */ | 180 | */ |
181 | 181 | ||
182 | struct probe_arg { | ||
183 | struct fetch_func fetch; | ||
184 | const char *name; | ||
185 | }; | ||
186 | |||
182 | struct trace_probe { | 187 | struct trace_probe { |
183 | struct list_head list; | 188 | struct list_head list; |
184 | struct kretprobe rp; /* Use rp.kp for kprobe use */ | 189 | struct kretprobe rp; /* Use rp.kp for kprobe use */ |
@@ -187,12 +192,12 @@ struct trace_probe { | |||
187 | struct ftrace_event_call call; | 192 | struct ftrace_event_call call; |
188 | struct trace_event event; | 193 | struct trace_event event; |
189 | unsigned int nr_args; | 194 | unsigned int nr_args; |
190 | struct fetch_func args[]; | 195 | struct probe_arg args[]; |
191 | }; | 196 | }; |
192 | 197 | ||
193 | #define SIZEOF_TRACE_PROBE(n) \ | 198 | #define SIZEOF_TRACE_PROBE(n) \ |
194 | (offsetof(struct trace_probe, args) + \ | 199 | (offsetof(struct trace_probe, args) + \ |
195 | (sizeof(struct fetch_func) * (n))) | 200 | (sizeof(struct probe_arg) * (n))) |
196 | 201 | ||
197 | static int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs); | 202 | static int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs); |
198 | static int kretprobe_trace_func(struct kretprobe_instance *ri, | 203 | static int kretprobe_trace_func(struct kretprobe_instance *ri, |
@@ -301,15 +306,21 @@ error: | |||
301 | return ERR_PTR(-ENOMEM); | 306 | return ERR_PTR(-ENOMEM); |
302 | } | 307 | } |
303 | 308 | ||
309 | static void free_probe_arg(struct probe_arg *arg) | ||
310 | { | ||
311 | if (arg->fetch.func == fetch_symbol) | ||
312 | free_symbol_cache(arg->fetch.data); | ||
313 | else if (arg->fetch.func == fetch_indirect) | ||
314 | free_indirect_fetch_data(arg->fetch.data); | ||
315 | kfree(arg->name); | ||
316 | } | ||
317 | |||
304 | static void free_trace_probe(struct trace_probe *tp) | 318 | static void free_trace_probe(struct trace_probe *tp) |
305 | { | 319 | { |
306 | int i; | 320 | int i; |
307 | 321 | ||
308 | for (i = 0; i < tp->nr_args; i++) | 322 | for (i = 0; i < tp->nr_args; i++) |
309 | if (tp->args[i].func == fetch_symbol) | 323 | free_probe_arg(&tp->args[i]); |
310 | free_symbol_cache(tp->args[i].data); | ||
311 | else if (tp->args[i].func == fetch_indirect) | ||
312 | free_indirect_fetch_data(tp->args[i].data); | ||
313 | 324 | ||
314 | kfree(tp->call.name); | 325 | kfree(tp->call.name); |
315 | kfree(tp->symbol); | 326 | kfree(tp->symbol); |
@@ -532,11 +543,13 @@ static int create_trace_probe(int argc, char **argv) | |||
532 | * %REG : fetch register REG | 543 | * %REG : fetch register REG |
533 | * Indirect memory fetch: | 544 | * Indirect memory fetch: |
534 | * +|-offs(ARG) : fetch memory at ARG +|- offs address. | 545 | * +|-offs(ARG) : fetch memory at ARG +|- offs address. |
546 | * Alias name of args: | ||
547 | * NAME=FETCHARG : set NAME as alias of FETCHARG. | ||
535 | */ | 548 | */ |
536 | struct trace_probe *tp; | 549 | struct trace_probe *tp; |
537 | int i, ret = 0; | 550 | int i, ret = 0; |
538 | int is_return = 0; | 551 | int is_return = 0; |
539 | char *symbol = NULL, *event = NULL; | 552 | char *symbol = NULL, *event = NULL, *arg = NULL; |
540 | unsigned long offset = 0; | 553 | unsigned long offset = 0; |
541 | void *addr = NULL; | 554 | void *addr = NULL; |
542 | char buf[MAX_EVENT_NAME_LEN]; | 555 | char buf[MAX_EVENT_NAME_LEN]; |
@@ -596,12 +609,21 @@ static int create_trace_probe(int argc, char **argv) | |||
596 | /* parse arguments */ | 609 | /* parse arguments */ |
597 | ret = 0; | 610 | ret = 0; |
598 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { | 611 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { |
599 | if (strlen(argv[i]) > MAX_ARGSTR_LEN) { | 612 | /* Parse argument name */ |
600 | pr_info("Argument%d(%s) is too long.\n", i, argv[i]); | 613 | arg = strchr(argv[i], '='); |
614 | if (arg) | ||
615 | *arg++ = '\0'; | ||
616 | else | ||
617 | arg = argv[i]; | ||
618 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); | ||
619 | |||
620 | /* Parse fetch argument */ | ||
621 | if (strlen(arg) > MAX_ARGSTR_LEN) { | ||
622 | pr_info("Argument%d(%s) is too long.\n", i, arg); | ||
601 | ret = -ENOSPC; | 623 | ret = -ENOSPC; |
602 | goto error; | 624 | goto error; |
603 | } | 625 | } |
604 | ret = parse_probe_arg(argv[i], &tp->args[i], is_return); | 626 | ret = parse_probe_arg(arg, &tp->args[i].fetch, is_return); |
605 | if (ret) | 627 | if (ret) |
606 | goto error; | 628 | goto error; |
607 | } | 629 | } |
@@ -664,12 +686,12 @@ static int probes_seq_show(struct seq_file *m, void *v) | |||
664 | seq_printf(m, " 0x%p", tp->rp.kp.addr); | 686 | seq_printf(m, " 0x%p", tp->rp.kp.addr); |
665 | 687 | ||
666 | for (i = 0; i < tp->nr_args; i++) { | 688 | for (i = 0; i < tp->nr_args; i++) { |
667 | ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i]); | 689 | ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i].fetch); |
668 | if (ret < 0) { | 690 | if (ret < 0) { |
669 | pr_warning("Argument%d decoding error(%d).\n", i, ret); | 691 | pr_warning("Argument%d decoding error(%d).\n", i, ret); |
670 | return ret; | 692 | return ret; |
671 | } | 693 | } |
672 | seq_printf(m, " %s", buf); | 694 | seq_printf(m, " %s=%s", tp->args[i].name, buf); |
673 | } | 695 | } |
674 | seq_printf(m, "\n"); | 696 | seq_printf(m, "\n"); |
675 | return 0; | 697 | return 0; |
@@ -824,7 +846,7 @@ static __kprobes int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
824 | entry->nargs = tp->nr_args; | 846 | entry->nargs = tp->nr_args; |
825 | entry->ip = (unsigned long)kp->addr; | 847 | entry->ip = (unsigned long)kp->addr; |
826 | for (i = 0; i < tp->nr_args; i++) | 848 | for (i = 0; i < tp->nr_args; i++) |
827 | entry->args[i] = call_fetch(&tp->args[i], regs); | 849 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); |
828 | 850 | ||
829 | if (!filter_current_check_discard(buffer, call, entry, event)) | 851 | if (!filter_current_check_discard(buffer, call, entry, event)) |
830 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 852 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); |
@@ -858,7 +880,7 @@ static __kprobes int kretprobe_trace_func(struct kretprobe_instance *ri, | |||
858 | entry->func = (unsigned long)tp->rp.kp.addr; | 880 | entry->func = (unsigned long)tp->rp.kp.addr; |
859 | entry->ret_ip = (unsigned long)ri->ret_addr; | 881 | entry->ret_ip = (unsigned long)ri->ret_addr; |
860 | for (i = 0; i < tp->nr_args; i++) | 882 | for (i = 0; i < tp->nr_args; i++) |
861 | entry->args[i] = call_fetch(&tp->args[i], regs); | 883 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); |
862 | 884 | ||
863 | if (!filter_current_check_discard(buffer, call, entry, event)) | 885 | if (!filter_current_check_discard(buffer, call, entry, event)) |
864 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); | 886 | trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); |
@@ -872,9 +894,13 @@ print_kprobe_event(struct trace_iterator *iter, int flags) | |||
872 | { | 894 | { |
873 | struct kprobe_trace_entry *field; | 895 | struct kprobe_trace_entry *field; |
874 | struct trace_seq *s = &iter->seq; | 896 | struct trace_seq *s = &iter->seq; |
897 | struct trace_event *event; | ||
898 | struct trace_probe *tp; | ||
875 | int i; | 899 | int i; |
876 | 900 | ||
877 | field = (struct kprobe_trace_entry *)iter->ent; | 901 | field = (struct kprobe_trace_entry *)iter->ent; |
902 | event = ftrace_find_event(field->ent.type); | ||
903 | tp = container_of(event, struct trace_probe, event); | ||
878 | 904 | ||
879 | if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET)) | 905 | if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET)) |
880 | goto partial; | 906 | goto partial; |
@@ -883,7 +909,8 @@ print_kprobe_event(struct trace_iterator *iter, int flags) | |||
883 | goto partial; | 909 | goto partial; |
884 | 910 | ||
885 | for (i = 0; i < field->nargs; i++) | 911 | for (i = 0; i < field->nargs; i++) |
886 | if (!trace_seq_printf(s, " 0x%lx", field->args[i])) | 912 | if (!trace_seq_printf(s, " %s=%lx", |
913 | tp->args[i].name, field->args[i])) | ||
887 | goto partial; | 914 | goto partial; |
888 | 915 | ||
889 | if (!trace_seq_puts(s, "\n")) | 916 | if (!trace_seq_puts(s, "\n")) |
@@ -899,9 +926,13 @@ print_kretprobe_event(struct trace_iterator *iter, int flags) | |||
899 | { | 926 | { |
900 | struct kretprobe_trace_entry *field; | 927 | struct kretprobe_trace_entry *field; |
901 | struct trace_seq *s = &iter->seq; | 928 | struct trace_seq *s = &iter->seq; |
929 | struct trace_event *event; | ||
930 | struct trace_probe *tp; | ||
902 | int i; | 931 | int i; |
903 | 932 | ||
904 | field = (struct kretprobe_trace_entry *)iter->ent; | 933 | field = (struct kretprobe_trace_entry *)iter->ent; |
934 | event = ftrace_find_event(field->ent.type); | ||
935 | tp = container_of(event, struct trace_probe, event); | ||
905 | 936 | ||
906 | if (!seq_print_ip_sym(s, field->ret_ip, flags | TRACE_ITER_SYM_OFFSET)) | 937 | if (!seq_print_ip_sym(s, field->ret_ip, flags | TRACE_ITER_SYM_OFFSET)) |
907 | goto partial; | 938 | goto partial; |
@@ -916,7 +947,8 @@ print_kretprobe_event(struct trace_iterator *iter, int flags) | |||
916 | goto partial; | 947 | goto partial; |
917 | 948 | ||
918 | for (i = 0; i < field->nargs; i++) | 949 | for (i = 0; i < field->nargs; i++) |
919 | if (!trace_seq_printf(s, " 0x%lx", field->args[i])) | 950 | if (!trace_seq_printf(s, " %s=%lx", |
951 | tp->args[i].name, field->args[i])) | ||
920 | goto partial; | 952 | goto partial; |
921 | 953 | ||
922 | if (!trace_seq_puts(s, "\n")) | 954 | if (!trace_seq_puts(s, "\n")) |
@@ -972,7 +1004,6 @@ static int kprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
972 | { | 1004 | { |
973 | int ret, i; | 1005 | int ret, i; |
974 | struct kprobe_trace_entry field; | 1006 | struct kprobe_trace_entry field; |
975 | char buf[MAX_ARGSTR_LEN + 1]; | ||
976 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1007 | struct trace_probe *tp = (struct trace_probe *)event_call->data; |
977 | 1008 | ||
978 | ret = trace_define_common_fields(event_call); | 1009 | ret = trace_define_common_fields(event_call); |
@@ -981,16 +1012,9 @@ static int kprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
981 | 1012 | ||
982 | DEFINE_FIELD(unsigned long, ip, "ip", 0); | 1013 | DEFINE_FIELD(unsigned long, ip, "ip", 0); |
983 | DEFINE_FIELD(int, nargs, "nargs", 1); | 1014 | DEFINE_FIELD(int, nargs, "nargs", 1); |
984 | for (i = 0; i < tp->nr_args; i++) { | 1015 | /* Set argument names as fields */ |
985 | /* Set argN as a field */ | 1016 | for (i = 0; i < tp->nr_args; i++) |
986 | sprintf(buf, "arg%d", i); | 1017 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); |
987 | DEFINE_FIELD(unsigned long, args[i], buf, 0); | ||
988 | /* Set argument string as an alias field */ | ||
989 | ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i]); | ||
990 | if (ret < 0) | ||
991 | return ret; | ||
992 | DEFINE_FIELD(unsigned long, args[i], buf, 0); | ||
993 | } | ||
994 | return 0; | 1018 | return 0; |
995 | } | 1019 | } |
996 | 1020 | ||
@@ -998,7 +1022,6 @@ static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
998 | { | 1022 | { |
999 | int ret, i; | 1023 | int ret, i; |
1000 | struct kretprobe_trace_entry field; | 1024 | struct kretprobe_trace_entry field; |
1001 | char buf[MAX_ARGSTR_LEN + 1]; | ||
1002 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1025 | struct trace_probe *tp = (struct trace_probe *)event_call->data; |
1003 | 1026 | ||
1004 | ret = trace_define_common_fields(event_call); | 1027 | ret = trace_define_common_fields(event_call); |
@@ -1008,16 +1031,9 @@ static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
1008 | DEFINE_FIELD(unsigned long, func, "func", 0); | 1031 | DEFINE_FIELD(unsigned long, func, "func", 0); |
1009 | DEFINE_FIELD(unsigned long, ret_ip, "ret_ip", 0); | 1032 | DEFINE_FIELD(unsigned long, ret_ip, "ret_ip", 0); |
1010 | DEFINE_FIELD(int, nargs, "nargs", 1); | 1033 | DEFINE_FIELD(int, nargs, "nargs", 1); |
1011 | for (i = 0; i < tp->nr_args; i++) { | 1034 | /* Set argument names as fields */ |
1012 | /* Set argN as a field */ | 1035 | for (i = 0; i < tp->nr_args; i++) |
1013 | sprintf(buf, "arg%d", i); | 1036 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); |
1014 | DEFINE_FIELD(unsigned long, args[i], buf, 0); | ||
1015 | /* Set argument string as an alias field */ | ||
1016 | ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i]); | ||
1017 | if (ret < 0) | ||
1018 | return ret; | ||
1019 | DEFINE_FIELD(unsigned long, args[i], buf, 0); | ||
1020 | } | ||
1021 | return 0; | 1037 | return 0; |
1022 | } | 1038 | } |
1023 | 1039 | ||
@@ -1025,31 +1041,21 @@ static int __probe_event_show_format(struct trace_seq *s, | |||
1025 | struct trace_probe *tp, const char *fmt, | 1041 | struct trace_probe *tp, const char *fmt, |
1026 | const char *arg) | 1042 | const char *arg) |
1027 | { | 1043 | { |
1028 | int i, ret; | 1044 | int i; |
1029 | char buf[MAX_ARGSTR_LEN + 1]; | ||
1030 | 1045 | ||
1031 | /* Show aliases */ | ||
1032 | for (i = 0; i < tp->nr_args; i++) { | ||
1033 | ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i]); | ||
1034 | if (ret < 0) | ||
1035 | return ret; | ||
1036 | if (!trace_seq_printf(s, "\talias: %s;\toriginal: arg%d;\n", | ||
1037 | buf, i)) | ||
1038 | return 0; | ||
1039 | } | ||
1040 | /* Show format */ | 1046 | /* Show format */ |
1041 | if (!trace_seq_printf(s, "\nprint fmt: \"%s", fmt)) | 1047 | if (!trace_seq_printf(s, "\nprint fmt: \"%s", fmt)) |
1042 | return 0; | 1048 | return 0; |
1043 | 1049 | ||
1044 | for (i = 0; i < tp->nr_args; i++) | 1050 | for (i = 0; i < tp->nr_args; i++) |
1045 | if (!trace_seq_puts(s, " 0x%lx")) | 1051 | if (!trace_seq_printf(s, " %s=%%lx", tp->args[i].name)) |
1046 | return 0; | 1052 | return 0; |
1047 | 1053 | ||
1048 | if (!trace_seq_printf(s, "\", %s", arg)) | 1054 | if (!trace_seq_printf(s, "\", %s", arg)) |
1049 | return 0; | 1055 | return 0; |
1050 | 1056 | ||
1051 | for (i = 0; i < tp->nr_args; i++) | 1057 | for (i = 0; i < tp->nr_args; i++) |
1052 | if (!trace_seq_printf(s, ", arg%d", i)) | 1058 | if (!trace_seq_printf(s, ", REC->%s", tp->args[i].name)) |
1053 | return 0; | 1059 | return 0; |
1054 | 1060 | ||
1055 | return trace_seq_puts(s, "\n"); | 1061 | return trace_seq_puts(s, "\n"); |
@@ -1071,17 +1077,14 @@ static int kprobe_event_show_format(struct ftrace_event_call *call, | |||
1071 | { | 1077 | { |
1072 | struct kprobe_trace_entry field __attribute__((unused)); | 1078 | struct kprobe_trace_entry field __attribute__((unused)); |
1073 | int ret, i; | 1079 | int ret, i; |
1074 | char buf[8]; | ||
1075 | struct trace_probe *tp = (struct trace_probe *)call->data; | 1080 | struct trace_probe *tp = (struct trace_probe *)call->data; |
1076 | 1081 | ||
1077 | SHOW_FIELD(unsigned long, ip, "ip"); | 1082 | SHOW_FIELD(unsigned long, ip, "ip"); |
1078 | SHOW_FIELD(int, nargs, "nargs"); | 1083 | SHOW_FIELD(int, nargs, "nargs"); |
1079 | 1084 | ||
1080 | /* Show fields */ | 1085 | /* Show fields */ |
1081 | for (i = 0; i < tp->nr_args; i++) { | 1086 | for (i = 0; i < tp->nr_args; i++) |
1082 | sprintf(buf, "arg%d", i); | 1087 | SHOW_FIELD(unsigned long, args[i], tp->args[i].name); |
1083 | SHOW_FIELD(unsigned long, args[i], buf); | ||
1084 | } | ||
1085 | trace_seq_puts(s, "\n"); | 1088 | trace_seq_puts(s, "\n"); |
1086 | 1089 | ||
1087 | return __probe_event_show_format(s, tp, "%lx:", "ip"); | 1090 | return __probe_event_show_format(s, tp, "%lx:", "ip"); |
@@ -1092,7 +1095,6 @@ static int kretprobe_event_show_format(struct ftrace_event_call *call, | |||
1092 | { | 1095 | { |
1093 | struct kretprobe_trace_entry field __attribute__((unused)); | 1096 | struct kretprobe_trace_entry field __attribute__((unused)); |
1094 | int ret, i; | 1097 | int ret, i; |
1095 | char buf[8]; | ||
1096 | struct trace_probe *tp = (struct trace_probe *)call->data; | 1098 | struct trace_probe *tp = (struct trace_probe *)call->data; |
1097 | 1099 | ||
1098 | SHOW_FIELD(unsigned long, func, "func"); | 1100 | SHOW_FIELD(unsigned long, func, "func"); |
@@ -1100,10 +1102,8 @@ static int kretprobe_event_show_format(struct ftrace_event_call *call, | |||
1100 | SHOW_FIELD(int, nargs, "nargs"); | 1102 | SHOW_FIELD(int, nargs, "nargs"); |
1101 | 1103 | ||
1102 | /* Show fields */ | 1104 | /* Show fields */ |
1103 | for (i = 0; i < tp->nr_args; i++) { | 1105 | for (i = 0; i < tp->nr_args; i++) |
1104 | sprintf(buf, "arg%d", i); | 1106 | SHOW_FIELD(unsigned long, args[i], tp->args[i].name); |
1105 | SHOW_FIELD(unsigned long, args[i], buf); | ||
1106 | } | ||
1107 | trace_seq_puts(s, "\n"); | 1107 | trace_seq_puts(s, "\n"); |
1108 | 1108 | ||
1109 | return __probe_event_show_format(s, tp, "%lx <- %lx:", | 1109 | return __probe_event_show_format(s, tp, "%lx <- %lx:", |
@@ -1140,7 +1140,7 @@ static __kprobes int kprobe_profile_func(struct kprobe *kp, | |||
1140 | entry->nargs = tp->nr_args; | 1140 | entry->nargs = tp->nr_args; |
1141 | entry->ip = (unsigned long)kp->addr; | 1141 | entry->ip = (unsigned long)kp->addr; |
1142 | for (i = 0; i < tp->nr_args; i++) | 1142 | for (i = 0; i < tp->nr_args; i++) |
1143 | entry->args[i] = call_fetch(&tp->args[i], regs); | 1143 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); |
1144 | perf_tpcounter_event(call->id, entry->ip, 1, entry, size); | 1144 | perf_tpcounter_event(call->id, entry->ip, 1, entry, size); |
1145 | } while (0); | 1145 | } while (0); |
1146 | return 0; | 1146 | return 0; |
@@ -1175,7 +1175,7 @@ static __kprobes int kretprobe_profile_func(struct kretprobe_instance *ri, | |||
1175 | entry->func = (unsigned long)tp->rp.kp.addr; | 1175 | entry->func = (unsigned long)tp->rp.kp.addr; |
1176 | entry->ret_ip = (unsigned long)ri->ret_addr; | 1176 | entry->ret_ip = (unsigned long)ri->ret_addr; |
1177 | for (i = 0; i < tp->nr_args; i++) | 1177 | for (i = 0; i < tp->nr_args; i++) |
1178 | entry->args[i] = call_fetch(&tp->args[i], regs); | 1178 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); |
1179 | perf_tpcounter_event(call->id, entry->ret_ip, 1, entry, size); | 1179 | perf_tpcounter_event(call->id, entry->ret_ip, 1, entry, size); |
1180 | } while (0); | 1180 | } while (0); |
1181 | return 0; | 1181 | return 0; |