diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2009-09-10 23:31:21 -0400 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-09-10 23:31:21 -0400 |
commit | 4a846b443b4e8633057946a2234e23559a67ce42 (patch) | |
tree | eb69e76e8480bf593634a395f0093b6133f3b6c1 | |
parent | 2fba0c8867af47f6455490e7b59e512dd180c027 (diff) |
tracing/kprobes: Cleanup kprobe tracer code.
Simplify trace_probe to remove a union, and remove some redundant
wrappers.
And also, cleanup create_trace_probe() function.
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: <20090910235322.22412.52525.stgit@dhcp-100-2-132.bos.redhat.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
-rw-r--r-- | kernel/trace/trace_kprobe.c | 81 |
1 files changed, 34 insertions, 47 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index c24b7e9d97c4..4ce728ca1b18 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -180,10 +180,7 @@ static __kprobes void free_indirect_fetch_data(struct indirect_fetch_data *data) | |||
180 | 180 | ||
181 | struct trace_probe { | 181 | struct trace_probe { |
182 | struct list_head list; | 182 | struct list_head list; |
183 | union { | 183 | struct kretprobe rp; /* Use rp.kp for kprobe use */ |
184 | struct kprobe kp; | ||
185 | struct kretprobe rp; | ||
186 | }; | ||
187 | unsigned long nhit; | 184 | unsigned long nhit; |
188 | const char *symbol; /* symbol name */ | 185 | const char *symbol; /* symbol name */ |
189 | struct ftrace_event_call call; | 186 | struct ftrace_event_call call; |
@@ -202,7 +199,7 @@ static int kretprobe_trace_func(struct kretprobe_instance *ri, | |||
202 | 199 | ||
203 | static __kprobes int probe_is_return(struct trace_probe *tp) | 200 | static __kprobes int probe_is_return(struct trace_probe *tp) |
204 | { | 201 | { |
205 | return (tp->rp.handler == kretprobe_trace_func); | 202 | return tp->rp.handler != NULL; |
206 | } | 203 | } |
207 | 204 | ||
208 | static __kprobes const char *probe_symbol(struct trace_probe *tp) | 205 | static __kprobes const char *probe_symbol(struct trace_probe *tp) |
@@ -210,16 +207,6 @@ static __kprobes const char *probe_symbol(struct trace_probe *tp) | |||
210 | return tp->symbol ? tp->symbol : "unknown"; | 207 | return tp->symbol ? tp->symbol : "unknown"; |
211 | } | 208 | } |
212 | 209 | ||
213 | static __kprobes unsigned int probe_offset(struct trace_probe *tp) | ||
214 | { | ||
215 | return (probe_is_return(tp)) ? tp->rp.kp.offset : tp->kp.offset; | ||
216 | } | ||
217 | |||
218 | static __kprobes void *probe_address(struct trace_probe *tp) | ||
219 | { | ||
220 | return (probe_is_return(tp)) ? tp->rp.kp.addr : tp->kp.addr; | ||
221 | } | ||
222 | |||
223 | static int probe_arg_string(char *buf, size_t n, struct fetch_func *ff) | 210 | static int probe_arg_string(char *buf, size_t n, struct fetch_func *ff) |
224 | { | 211 | { |
225 | int ret = -EINVAL; | 212 | int ret = -EINVAL; |
@@ -269,8 +256,14 @@ static void unregister_probe_event(struct trace_probe *tp); | |||
269 | static DEFINE_MUTEX(probe_lock); | 256 | static DEFINE_MUTEX(probe_lock); |
270 | static LIST_HEAD(probe_list); | 257 | static LIST_HEAD(probe_list); |
271 | 258 | ||
272 | static struct trace_probe *alloc_trace_probe(const char *symbol, | 259 | /* |
273 | const char *event, int nargs) | 260 | * Allocate new trace_probe and initialize it (including kprobes). |
261 | */ | ||
262 | static struct trace_probe *alloc_trace_probe(const char *event, | ||
263 | void *addr, | ||
264 | const char *symbol, | ||
265 | unsigned long offs, | ||
266 | int nargs, int is_return) | ||
274 | { | 267 | { |
275 | struct trace_probe *tp; | 268 | struct trace_probe *tp; |
276 | 269 | ||
@@ -282,7 +275,16 @@ static struct trace_probe *alloc_trace_probe(const char *symbol, | |||
282 | tp->symbol = kstrdup(symbol, GFP_KERNEL); | 275 | tp->symbol = kstrdup(symbol, GFP_KERNEL); |
283 | if (!tp->symbol) | 276 | if (!tp->symbol) |
284 | goto error; | 277 | goto error; |
285 | } | 278 | tp->rp.kp.symbol_name = tp->symbol; |
279 | tp->rp.kp.offset = offs; | ||
280 | } else | ||
281 | tp->rp.kp.addr = addr; | ||
282 | |||
283 | if (is_return) | ||
284 | tp->rp.handler = kretprobe_trace_func; | ||
285 | else | ||
286 | tp->rp.kp.pre_handler = kprobe_trace_func; | ||
287 | |||
286 | if (!event) | 288 | if (!event) |
287 | goto error; | 289 | goto error; |
288 | tp->call.name = kstrdup(event, GFP_KERNEL); | 290 | tp->call.name = kstrdup(event, GFP_KERNEL); |
@@ -327,7 +329,7 @@ static void __unregister_trace_probe(struct trace_probe *tp) | |||
327 | if (probe_is_return(tp)) | 329 | if (probe_is_return(tp)) |
328 | unregister_kretprobe(&tp->rp); | 330 | unregister_kretprobe(&tp->rp); |
329 | else | 331 | else |
330 | unregister_kprobe(&tp->kp); | 332 | unregister_kprobe(&tp->rp.kp); |
331 | } | 333 | } |
332 | 334 | ||
333 | /* Unregister a trace_probe and probe_event: call with locking probe_lock */ | 335 | /* Unregister a trace_probe and probe_event: call with locking probe_lock */ |
@@ -349,14 +351,14 @@ static int register_trace_probe(struct trace_probe *tp) | |||
349 | if (probe_is_return(tp)) | 351 | if (probe_is_return(tp)) |
350 | ret = register_kretprobe(&tp->rp); | 352 | ret = register_kretprobe(&tp->rp); |
351 | else | 353 | else |
352 | ret = register_kprobe(&tp->kp); | 354 | ret = register_kprobe(&tp->rp.kp); |
353 | 355 | ||
354 | if (ret) { | 356 | if (ret) { |
355 | pr_warning("Could not insert probe(%d)\n", ret); | 357 | pr_warning("Could not insert probe(%d)\n", ret); |
356 | if (ret == -EILSEQ) { | 358 | if (ret == -EILSEQ) { |
357 | pr_warning("Probing address(0x%p) is not an " | 359 | pr_warning("Probing address(0x%p) is not an " |
358 | "instruction boundary.\n", | 360 | "instruction boundary.\n", |
359 | probe_address(tp)); | 361 | tp->rp.kp.addr); |
360 | ret = -EINVAL; | 362 | ret = -EINVAL; |
361 | } | 363 | } |
362 | goto end; | 364 | goto end; |
@@ -530,12 +532,12 @@ static int create_trace_probe(int argc, char **argv) | |||
530 | * +|-offs(ARG) : fetch memory at ARG +|- offs address. | 532 | * +|-offs(ARG) : fetch memory at ARG +|- offs address. |
531 | */ | 533 | */ |
532 | struct trace_probe *tp; | 534 | struct trace_probe *tp; |
533 | struct kprobe *kp; | ||
534 | int i, ret = 0; | 535 | int i, ret = 0; |
535 | int is_return = 0; | 536 | int is_return = 0; |
536 | char *symbol = NULL, *event = NULL; | 537 | char *symbol = NULL, *event = NULL; |
537 | unsigned long offset = 0; | 538 | unsigned long offset = 0; |
538 | void *addr = NULL; | 539 | void *addr = NULL; |
540 | char buf[MAX_EVENT_NAME_LEN]; | ||
539 | 541 | ||
540 | if (argc < 2) | 542 | if (argc < 2) |
541 | return -EINVAL; | 543 | return -EINVAL; |
@@ -577,33 +579,18 @@ static int create_trace_probe(int argc, char **argv) | |||
577 | /* setup a probe */ | 579 | /* setup a probe */ |
578 | if (!event) { | 580 | if (!event) { |
579 | /* Make a new event name */ | 581 | /* Make a new event name */ |
580 | char buf[MAX_EVENT_NAME_LEN]; | ||
581 | if (symbol) | 582 | if (symbol) |
582 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@%s%+ld", | 583 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@%s%+ld", |
583 | is_return ? 'r' : 'p', symbol, offset); | 584 | is_return ? 'r' : 'p', symbol, offset); |
584 | else | 585 | else |
585 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@0x%p", | 586 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@0x%p", |
586 | is_return ? 'r' : 'p', addr); | 587 | is_return ? 'r' : 'p', addr); |
587 | tp = alloc_trace_probe(symbol, buf, argc); | 588 | event = buf; |
588 | } else | 589 | } |
589 | tp = alloc_trace_probe(symbol, event, argc); | 590 | tp = alloc_trace_probe(event, addr, symbol, offset, argc, is_return); |
590 | if (IS_ERR(tp)) | 591 | if (IS_ERR(tp)) |
591 | return PTR_ERR(tp); | 592 | return PTR_ERR(tp); |
592 | 593 | ||
593 | if (is_return) { | ||
594 | kp = &tp->rp.kp; | ||
595 | tp->rp.handler = kretprobe_trace_func; | ||
596 | } else { | ||
597 | kp = &tp->kp; | ||
598 | tp->kp.pre_handler = kprobe_trace_func; | ||
599 | } | ||
600 | |||
601 | if (tp->symbol) { | ||
602 | kp->symbol_name = tp->symbol; | ||
603 | kp->offset = (unsigned int)offset; | ||
604 | } else | ||
605 | kp->addr = addr; | ||
606 | |||
607 | /* parse arguments */ | 594 | /* parse arguments */ |
608 | ret = 0; | 595 | ret = 0; |
609 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { | 596 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { |
@@ -670,9 +657,9 @@ static int probes_seq_show(struct seq_file *m, void *v) | |||
670 | seq_printf(m, ":%s", tp->call.name); | 657 | seq_printf(m, ":%s", tp->call.name); |
671 | 658 | ||
672 | if (tp->symbol) | 659 | if (tp->symbol) |
673 | seq_printf(m, " %s+%u", probe_symbol(tp), probe_offset(tp)); | 660 | seq_printf(m, " %s+%u", probe_symbol(tp), tp->rp.kp.offset); |
674 | else | 661 | else |
675 | seq_printf(m, " 0x%p", probe_address(tp)); | 662 | seq_printf(m, " 0x%p", tp->rp.kp.addr); |
676 | 663 | ||
677 | for (i = 0; i < tp->nr_args; i++) { | 664 | for (i = 0; i < tp->nr_args; i++) { |
678 | ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i]); | 665 | ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i]); |
@@ -783,7 +770,7 @@ static int probes_profile_seq_show(struct seq_file *m, void *v) | |||
783 | struct trace_probe *tp = v; | 770 | struct trace_probe *tp = v; |
784 | 771 | ||
785 | seq_printf(m, " %-44s %15lu %15lu\n", tp->call.name, tp->nhit, | 772 | seq_printf(m, " %-44s %15lu %15lu\n", tp->call.name, tp->nhit, |
786 | probe_is_return(tp) ? tp->rp.kp.nmissed : tp->kp.nmissed); | 773 | tp->rp.kp.nmissed); |
787 | 774 | ||
788 | return 0; | 775 | return 0; |
789 | } | 776 | } |
@@ -811,7 +798,7 @@ static const struct file_operations kprobe_profile_ops = { | |||
811 | /* Kprobe handler */ | 798 | /* Kprobe handler */ |
812 | static __kprobes int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | 799 | static __kprobes int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) |
813 | { | 800 | { |
814 | struct trace_probe *tp = container_of(kp, struct trace_probe, kp); | 801 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); |
815 | struct kprobe_trace_entry *entry; | 802 | struct kprobe_trace_entry *entry; |
816 | struct ring_buffer_event *event; | 803 | struct ring_buffer_event *event; |
817 | struct ring_buffer *buffer; | 804 | struct ring_buffer *buffer; |
@@ -866,7 +853,7 @@ static __kprobes int kretprobe_trace_func(struct kretprobe_instance *ri, | |||
866 | 853 | ||
867 | entry = ring_buffer_event_data(event); | 854 | entry = ring_buffer_event_data(event); |
868 | entry->nargs = tp->nr_args; | 855 | entry->nargs = tp->nr_args; |
869 | entry->func = (unsigned long)probe_address(tp); | 856 | entry->func = (unsigned long)tp->rp.kp.addr; |
870 | entry->ret_ip = (unsigned long)ri->ret_addr; | 857 | entry->ret_ip = (unsigned long)ri->ret_addr; |
871 | for (i = 0; i < tp->nr_args; i++) | 858 | for (i = 0; i < tp->nr_args; i++) |
872 | entry->args[i] = call_fetch(&tp->args[i], regs); | 859 | entry->args[i] = call_fetch(&tp->args[i], regs); |
@@ -945,7 +932,7 @@ static int probe_event_enable(struct ftrace_event_call *call) | |||
945 | if (probe_is_return(tp)) | 932 | if (probe_is_return(tp)) |
946 | return enable_kretprobe(&tp->rp); | 933 | return enable_kretprobe(&tp->rp); |
947 | else | 934 | else |
948 | return enable_kprobe(&tp->kp); | 935 | return enable_kprobe(&tp->rp.kp); |
949 | } | 936 | } |
950 | 937 | ||
951 | static void probe_event_disable(struct ftrace_event_call *call) | 938 | static void probe_event_disable(struct ftrace_event_call *call) |
@@ -955,7 +942,7 @@ static void probe_event_disable(struct ftrace_event_call *call) | |||
955 | if (probe_is_return(tp)) | 942 | if (probe_is_return(tp)) |
956 | disable_kretprobe(&tp->rp); | 943 | disable_kretprobe(&tp->rp); |
957 | else | 944 | else |
958 | disable_kprobe(&tp->kp); | 945 | disable_kprobe(&tp->rp.kp); |
959 | } | 946 | } |
960 | 947 | ||
961 | static int probe_event_raw_init(struct ftrace_event_call *event_call) | 948 | static int probe_event_raw_init(struct ftrace_event_call *event_call) |