diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2009-09-10 19:53:53 -0400 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-09-16 22:03:24 -0400 |
commit | f52487e9c0041842eeb77c6c48774414b1cede08 (patch) | |
tree | 30dc710a8a9823d41dbf83e8bb0acd264917fc96 /kernel/trace/trace_kprobe.c | |
parent | 6e9f23d1619f7badaf9090dac09e86a22d6061d8 (diff) |
tracing/kprobes: Support custom subsystem for each kprobe event
Support specifying a custom subsystem(group) for each kprobe event.
This allows users to create new group to control several probes
at once, or add events to existing groups as additional tracepoints.
New synopsis:
p[:[subsys/]event-name] KADDR|KSYM[+offs] [ARGS]
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: <20090910235353.22412.15149.stgit@dhcp-100-2-132.bos.redhat.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
-rw-r--r-- | kernel/trace/trace_kprobe.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 1746afeaabf9..cbc0870dcf5d 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #define MAX_TRACE_ARGS 128 | 36 | #define MAX_TRACE_ARGS 128 |
37 | #define MAX_ARGSTR_LEN 63 | 37 | #define MAX_ARGSTR_LEN 63 |
38 | #define MAX_EVENT_NAME_LEN 64 | 38 | #define MAX_EVENT_NAME_LEN 64 |
39 | #define KPROBE_EVENT_SYSTEM "kprobes" | ||
39 | 40 | ||
40 | /* currently, trace_kprobe only supports X86. */ | 41 | /* currently, trace_kprobe only supports X86. */ |
41 | 42 | ||
@@ -265,7 +266,8 @@ static LIST_HEAD(probe_list); | |||
265 | /* | 266 | /* |
266 | * Allocate new trace_probe and initialize it (including kprobes). | 267 | * Allocate new trace_probe and initialize it (including kprobes). |
267 | */ | 268 | */ |
268 | static struct trace_probe *alloc_trace_probe(const char *event, | 269 | static struct trace_probe *alloc_trace_probe(const char *group, |
270 | const char *event, | ||
269 | void *addr, | 271 | void *addr, |
270 | const char *symbol, | 272 | const char *symbol, |
271 | unsigned long offs, | 273 | unsigned long offs, |
@@ -298,9 +300,16 @@ static struct trace_probe *alloc_trace_probe(const char *event, | |||
298 | if (!tp->call.name) | 300 | if (!tp->call.name) |
299 | goto error; | 301 | goto error; |
300 | 302 | ||
303 | if (!group) | ||
304 | goto error; | ||
305 | tp->call.system = kstrdup(group, GFP_KERNEL); | ||
306 | if (!tp->call.system) | ||
307 | goto error; | ||
308 | |||
301 | INIT_LIST_HEAD(&tp->list); | 309 | INIT_LIST_HEAD(&tp->list); |
302 | return tp; | 310 | return tp; |
303 | error: | 311 | error: |
312 | kfree(tp->call.name); | ||
304 | kfree(tp->symbol); | 313 | kfree(tp->symbol); |
305 | kfree(tp); | 314 | kfree(tp); |
306 | return ERR_PTR(-ENOMEM); | 315 | return ERR_PTR(-ENOMEM); |
@@ -322,6 +331,7 @@ static void free_trace_probe(struct trace_probe *tp) | |||
322 | for (i = 0; i < tp->nr_args; i++) | 331 | for (i = 0; i < tp->nr_args; i++) |
323 | free_probe_arg(&tp->args[i]); | 332 | free_probe_arg(&tp->args[i]); |
324 | 333 | ||
334 | kfree(tp->call.system); | ||
325 | kfree(tp->call.name); | 335 | kfree(tp->call.name); |
326 | kfree(tp->symbol); | 336 | kfree(tp->symbol); |
327 | kfree(tp); | 337 | kfree(tp); |
@@ -530,8 +540,8 @@ static int create_trace_probe(int argc, char **argv) | |||
530 | { | 540 | { |
531 | /* | 541 | /* |
532 | * Argument syntax: | 542 | * Argument syntax: |
533 | * - Add kprobe: p[:EVENT] SYMBOL[+OFFS]|ADDRESS [FETCHARGS] | 543 | * - Add kprobe: p[:[GRP/]EVENT] KSYM[+OFFS]|KADDR [FETCHARGS] |
534 | * - Add kretprobe: r[:EVENT] SYMBOL[+0] [FETCHARGS] | 544 | * - Add kretprobe: r[:[GRP/]EVENT] KSYM[+0] [FETCHARGS] |
535 | * Fetch args: | 545 | * Fetch args: |
536 | * aN : fetch Nth of function argument. (N:0-) | 546 | * aN : fetch Nth of function argument. (N:0-) |
537 | * rv : fetch return value | 547 | * rv : fetch return value |
@@ -549,7 +559,7 @@ static int create_trace_probe(int argc, char **argv) | |||
549 | struct trace_probe *tp; | 559 | struct trace_probe *tp; |
550 | int i, ret = 0; | 560 | int i, ret = 0; |
551 | int is_return = 0; | 561 | int is_return = 0; |
552 | char *symbol = NULL, *event = NULL, *arg = NULL; | 562 | char *symbol = NULL, *event = NULL, *arg = NULL, *group = NULL; |
553 | unsigned long offset = 0; | 563 | unsigned long offset = 0; |
554 | void *addr = NULL; | 564 | void *addr = NULL; |
555 | char buf[MAX_EVENT_NAME_LEN]; | 565 | char buf[MAX_EVENT_NAME_LEN]; |
@@ -566,6 +576,15 @@ static int create_trace_probe(int argc, char **argv) | |||
566 | 576 | ||
567 | if (argv[0][1] == ':') { | 577 | if (argv[0][1] == ':') { |
568 | event = &argv[0][2]; | 578 | event = &argv[0][2]; |
579 | if (strchr(event, '/')) { | ||
580 | group = event; | ||
581 | event = strchr(group, '/') + 1; | ||
582 | event[-1] = '\0'; | ||
583 | if (strlen(group) == 0) { | ||
584 | pr_info("Group name is not specifiled\n"); | ||
585 | return -EINVAL; | ||
586 | } | ||
587 | } | ||
569 | if (strlen(event) == 0) { | 588 | if (strlen(event) == 0) { |
570 | pr_info("Event name is not specifiled\n"); | 589 | pr_info("Event name is not specifiled\n"); |
571 | return -EINVAL; | 590 | return -EINVAL; |
@@ -592,6 +611,8 @@ static int create_trace_probe(int argc, char **argv) | |||
592 | argc -= 2; argv += 2; | 611 | argc -= 2; argv += 2; |
593 | 612 | ||
594 | /* setup a probe */ | 613 | /* setup a probe */ |
614 | if (!group) | ||
615 | group = KPROBE_EVENT_SYSTEM; | ||
595 | if (!event) { | 616 | if (!event) { |
596 | /* Make a new event name */ | 617 | /* Make a new event name */ |
597 | if (symbol) | 618 | if (symbol) |
@@ -602,7 +623,8 @@ static int create_trace_probe(int argc, char **argv) | |||
602 | is_return ? 'r' : 'p', addr); | 623 | is_return ? 'r' : 'p', addr); |
603 | event = buf; | 624 | event = buf; |
604 | } | 625 | } |
605 | tp = alloc_trace_probe(event, addr, symbol, offset, argc, is_return); | 626 | tp = alloc_trace_probe(group, event, addr, symbol, offset, argc, |
627 | is_return); | ||
606 | if (IS_ERR(tp)) | 628 | if (IS_ERR(tp)) |
607 | return PTR_ERR(tp); | 629 | return PTR_ERR(tp); |
608 | 630 | ||
@@ -1217,7 +1239,6 @@ static int register_probe_event(struct trace_probe *tp) | |||
1217 | int ret; | 1239 | int ret; |
1218 | 1240 | ||
1219 | /* Initialize ftrace_event_call */ | 1241 | /* Initialize ftrace_event_call */ |
1220 | call->system = "kprobes"; | ||
1221 | if (probe_is_return(tp)) { | 1242 | if (probe_is_return(tp)) { |
1222 | tp->event.trace = print_kretprobe_event; | 1243 | tp->event.trace = print_kretprobe_event; |
1223 | call->raw_init = probe_event_raw_init; | 1244 | call->raw_init = probe_event_raw_init; |