aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/trace/kprobetrace.txt3
-rw-r--r--kernel/trace/trace_event_types.h18
-rw-r--r--kernel/trace/trace_kprobe.c64
3 files changed, 35 insertions, 50 deletions
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
index c9c09b45038..5e59e854e71 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 186b598a1f1..e74f0906ab1 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
178TRACE_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
187TRACE_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 6d488efd16b..8aeb24cc295 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 */
331static void unregister_trace_probe(struct trace_probe *tp) 332static 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);
377end: 375end:
@@ -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();