diff options
-rw-r--r-- | Documentation/trace/kprobetrace.txt | 3 | ||||
-rw-r--r-- | kernel/trace/trace_event_types.h | 18 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 64 |
3 files changed, 35 insertions, 50 deletions
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt index c9c09b45038d..5e59e854e71b 100644 --- a/Documentation/trace/kprobetrace.txt +++ b/Documentation/trace/kprobetrace.txt | |||
@@ -28,7 +28,8 @@ Synopsis of kprobe_events | |||
28 | p[:EVENT] SYMBOL[+offs|-offs]|MEMADDR [FETCHARGS] : Set a probe | 28 | p[:EVENT] SYMBOL[+offs|-offs]|MEMADDR [FETCHARGS] : Set a probe |
29 | r[:EVENT] SYMBOL[+0] [FETCHARGS] : Set a return probe | 29 | r[:EVENT] SYMBOL[+0] [FETCHARGS] : Set a return probe |
30 | 30 | ||
31 | EVENT : Event name. | 31 | EVENT : Event name. If omitted, the event name is generated |
32 | based on SYMBOL+offs or MEMADDR. | ||
32 | SYMBOL[+offs|-offs] : Symbol+offset where the probe is inserted. | 33 | SYMBOL[+offs|-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 | ||
diff --git a/kernel/trace/trace_event_types.h b/kernel/trace/trace_event_types.h index 186b598a1f11..e74f0906ab1a 100644 --- a/kernel/trace/trace_event_types.h +++ b/kernel/trace/trace_event_types.h | |||
@@ -175,22 +175,4 @@ TRACE_EVENT_FORMAT(kmem_free, TRACE_KMEM_FREE, kmemtrace_free_entry, ignore, | |||
175 | TP_RAW_FMT("type:%u call_site:%lx ptr:%p") | 175 | TP_RAW_FMT("type:%u call_site:%lx ptr:%p") |
176 | ); | 176 | ); |
177 | 177 | ||
178 | TRACE_EVENT_FORMAT(kprobe, TRACE_KPROBE, kprobe_trace_entry, ignore, | ||
179 | TRACE_STRUCT( | ||
180 | TRACE_FIELD(unsigned long, ip, ip) | ||
181 | TRACE_FIELD(int, nargs, nargs) | ||
182 | TRACE_FIELD_ZERO(unsigned long, args) | ||
183 | ), | ||
184 | TP_RAW_FMT("%08lx: args:0x%lx ...") | ||
185 | ); | ||
186 | |||
187 | TRACE_EVENT_FORMAT(kretprobe, TRACE_KRETPROBE, kretprobe_trace_entry, ignore, | ||
188 | TRACE_STRUCT( | ||
189 | TRACE_FIELD(unsigned long, func, func) | ||
190 | TRACE_FIELD(unsigned long, ret_ip, ret_ip) | ||
191 | TRACE_FIELD(int, nargs, nargs) | ||
192 | TRACE_FIELD_ZERO(unsigned long, args) | ||
193 | ), | ||
194 | TP_RAW_FMT("%08lx <- %08lx: args:0x%lx ...") | ||
195 | ); | ||
196 | #undef TRACE_SYSTEM | 178 | #undef TRACE_SYSTEM |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 6d488efd16b2..8aeb24cc295f 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #define MAX_TRACE_ARGS 128 | 35 | #define MAX_TRACE_ARGS 128 |
36 | #define MAX_ARGSTR_LEN 63 | 36 | #define MAX_ARGSTR_LEN 63 |
37 | #define MAX_EVENT_NAME_LEN 64 | ||
37 | 38 | ||
38 | /* currently, trace_kprobe only supports X86. */ | 39 | /* currently, trace_kprobe only supports X86. */ |
39 | 40 | ||
@@ -280,11 +281,11 @@ static struct trace_probe *alloc_trace_probe(const char *symbol, | |||
280 | if (!tp->symbol) | 281 | if (!tp->symbol) |
281 | goto error; | 282 | goto error; |
282 | } | 283 | } |
283 | if (event) { | 284 | if (!event) |
284 | tp->call.name = kstrdup(event, GFP_KERNEL); | 285 | goto error; |
285 | if (!tp->call.name) | 286 | tp->call.name = kstrdup(event, GFP_KERNEL); |
286 | goto error; | 287 | if (!tp->call.name) |
287 | } | 288 | goto error; |
288 | 289 | ||
289 | INIT_LIST_HEAD(&tp->list); | 290 | INIT_LIST_HEAD(&tp->list); |
290 | return tp; | 291 | return tp; |
@@ -314,7 +315,7 @@ static struct trace_probe *find_probe_event(const char *event) | |||
314 | struct trace_probe *tp; | 315 | struct trace_probe *tp; |
315 | 316 | ||
316 | list_for_each_entry(tp, &probe_list, list) | 317 | list_for_each_entry(tp, &probe_list, list) |
317 | if (tp->call.name && !strcmp(tp->call.name, event)) | 318 | if (!strcmp(tp->call.name, event)) |
318 | return tp; | 319 | return tp; |
319 | return NULL; | 320 | return NULL; |
320 | } | 321 | } |
@@ -330,8 +331,7 @@ static void __unregister_trace_probe(struct trace_probe *tp) | |||
330 | /* Unregister a trace_probe and probe_event: call with locking probe_lock */ | 331 | /* Unregister a trace_probe and probe_event: call with locking probe_lock */ |
331 | static void unregister_trace_probe(struct trace_probe *tp) | 332 | static void unregister_trace_probe(struct trace_probe *tp) |
332 | { | 333 | { |
333 | if (tp->call.name) | 334 | unregister_probe_event(tp); |
334 | unregister_probe_event(tp); | ||
335 | __unregister_trace_probe(tp); | 335 | __unregister_trace_probe(tp); |
336 | list_del(&tp->list); | 336 | list_del(&tp->list); |
337 | } | 337 | } |
@@ -360,18 +360,16 @@ static int register_trace_probe(struct trace_probe *tp) | |||
360 | goto end; | 360 | goto end; |
361 | } | 361 | } |
362 | /* register as an event */ | 362 | /* register as an event */ |
363 | if (tp->call.name) { | 363 | old_tp = find_probe_event(tp->call.name); |
364 | old_tp = find_probe_event(tp->call.name); | 364 | if (old_tp) { |
365 | if (old_tp) { | 365 | /* delete old event */ |
366 | /* delete old event */ | 366 | unregister_trace_probe(old_tp); |
367 | unregister_trace_probe(old_tp); | 367 | free_trace_probe(old_tp); |
368 | free_trace_probe(old_tp); | 368 | } |
369 | } | 369 | ret = register_probe_event(tp); |
370 | ret = register_probe_event(tp); | 370 | if (ret) { |
371 | if (ret) { | 371 | pr_warning("Faild to register probe event(%d)\n", ret); |
372 | pr_warning("Faild to register probe event(%d)\n", ret); | 372 | __unregister_trace_probe(tp); |
373 | __unregister_trace_probe(tp); | ||
374 | } | ||
375 | } | 373 | } |
376 | list_add_tail(&tp->list, &probe_list); | 374 | list_add_tail(&tp->list, &probe_list); |
377 | end: | 375 | end: |
@@ -580,7 +578,18 @@ static int create_trace_probe(int argc, char **argv) | |||
580 | argc -= 2; argv += 2; | 578 | argc -= 2; argv += 2; |
581 | 579 | ||
582 | /* setup a probe */ | 580 | /* setup a probe */ |
583 | tp = alloc_trace_probe(symbol, event, argc); | 581 | if (!event) { |
582 | /* Make a new event name */ | ||
583 | char buf[MAX_EVENT_NAME_LEN]; | ||
584 | if (symbol) | ||
585 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@%s%+ld", | ||
586 | is_return ? 'r' : 'p', symbol, offset); | ||
587 | else | ||
588 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@0x%p", | ||
589 | is_return ? 'r' : 'p', addr); | ||
590 | tp = alloc_trace_probe(symbol, buf, argc); | ||
591 | } else | ||
592 | tp = alloc_trace_probe(symbol, event, argc); | ||
584 | if (IS_ERR(tp)) | 593 | if (IS_ERR(tp)) |
585 | return PTR_ERR(tp); | 594 | return PTR_ERR(tp); |
586 | 595 | ||
@@ -661,8 +670,7 @@ static int probes_seq_show(struct seq_file *m, void *v) | |||
661 | char buf[MAX_ARGSTR_LEN + 1]; | 670 | char buf[MAX_ARGSTR_LEN + 1]; |
662 | 671 | ||
663 | seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p'); | 672 | seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p'); |
664 | if (tp->call.name) | 673 | seq_printf(m, ":%s", tp->call.name); |
665 | seq_printf(m, ":%s", tp->call.name); | ||
666 | 674 | ||
667 | if (tp->symbol) | 675 | if (tp->symbol) |
668 | seq_printf(m, " %s%+ld", probe_symbol(tp), probe_offset(tp)); | 676 | seq_printf(m, " %s%+ld", probe_symbol(tp), probe_offset(tp)); |
@@ -780,10 +788,7 @@ static __kprobes int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
780 | struct ring_buffer_event *event; | 788 | struct ring_buffer_event *event; |
781 | int size, i, pc; | 789 | int size, i, pc; |
782 | unsigned long irq_flags; | 790 | unsigned long irq_flags; |
783 | struct ftrace_event_call *call = &event_kprobe; | 791 | struct ftrace_event_call *call = &tp->call; |
784 | |||
785 | if (&tp->call.name) | ||
786 | call = &tp->call; | ||
787 | 792 | ||
788 | local_save_flags(irq_flags); | 793 | local_save_flags(irq_flags); |
789 | pc = preempt_count(); | 794 | pc = preempt_count(); |
@@ -815,10 +820,7 @@ static __kprobes int kretprobe_trace_func(struct kretprobe_instance *ri, | |||
815 | struct ring_buffer_event *event; | 820 | struct ring_buffer_event *event; |
816 | int size, i, pc; | 821 | int size, i, pc; |
817 | unsigned long irq_flags; | 822 | unsigned long irq_flags; |
818 | struct ftrace_event_call *call = &event_kretprobe; | 823 | struct ftrace_event_call *call = &tp->call; |
819 | |||
820 | if (&tp->call.name) | ||
821 | call = &tp->call; | ||
822 | 824 | ||
823 | local_save_flags(irq_flags); | 825 | local_save_flags(irq_flags); |
824 | pc = preempt_count(); | 826 | pc = preempt_count(); |