diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2009-12-15 10:32:18 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-12-15 14:22:03 -0500 |
commit | af663d75a64d2cc3f18bdb8a29ff4650b9417c16 (patch) | |
tree | fbbad1152eb42f561cc8b186b8bb38aabc1e1d94 /tools | |
parent | bbbb521bc61008b280c72ad6e29a8a7558d3acfa (diff) |
perf probe: Support event name for --add option
Support event name syntax for --add option. This allows
users to specify event name for each new event.
The --add syntax is:
perf probe --add '[EVENT=]SRC:LINE ARGS'
or
perf probe --add '[EVENT=]FUNC[+OFFS|%return|:RLN][@SRC] ARGS'
e.g.
./perf probe --add myprobe1=schedule
Note: currently group name is not supported yet, because it
can cause name-space confliction with other tracepoint/
hw-breakpoint events.
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Jason Baron <jbaron@redhat.com>
Cc: K.Prasad <prasad@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: systemtap <systemtap@sources.redhat.com>
Cc: DLE <dle-develop@lists.sourceforge.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20091215153218.17436.84675.stgit@dhcp-100-2-132.bos.redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Documentation/perf-probe.txt | 3 | ||||
-rw-r--r-- | tools/perf/builtin-probe.c | 8 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 74 | ||||
-rw-r--r-- | tools/perf/util/probe-event.h | 3 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.h | 3 |
5 files changed, 55 insertions, 36 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 8fa6bf99fcb5..250e391b4bc8 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt | |||
@@ -49,8 +49,9 @@ PROBE SYNTAX | |||
49 | ------------ | 49 | ------------ |
50 | Probe points are defined by following syntax. | 50 | Probe points are defined by following syntax. |
51 | 51 | ||
52 | "FUNC[+OFFS|:RLN|%return][@SRC]|SRC:ALN [ARG ...]" | 52 | "[EVENT=]FUNC[+OFFS|:RLN|%return][@SRC]|SRC:ALN [ARG ...]" |
53 | 53 | ||
54 | 'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'. | ||
54 | 'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, 'RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. In addition, 'SRC' specifies a source file which has that function. | 55 | 'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, 'RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. In addition, 'SRC' specifies a source file which has that function. |
55 | It is also possible to specify a probe point by the source line number by using 'SRC:ALN' syntax, where 'SRC' is the source file path and 'ALN' is the line number. | 56 | It is also possible to specify a probe point by the source line number by using 'SRC:ALN' syntax, where 'SRC' is the source file path and 'ALN' is the line number. |
56 | 'ARG' specifies the arguments of this probe point. You can use the name of local variable, or kprobe-tracer argument format (e.g. $retval, %ax, etc). | 57 | 'ARG' specifies the arguments of this probe point. You can use the name of local variable, or kprobe-tracer argument format (e.g. $retval, %ax, etc). |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 438a7bb101d3..adc0a55acd95 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -172,13 +172,13 @@ static const struct option options[] = { | |||
172 | opt_del_probe_event), | 172 | opt_del_probe_event), |
173 | OPT_CALLBACK('a', "add", NULL, | 173 | OPT_CALLBACK('a', "add", NULL, |
174 | #ifdef NO_LIBDWARF | 174 | #ifdef NO_LIBDWARF |
175 | "FUNC[+OFFS|%return] [ARG ...]", | 175 | "[EVENT=]FUNC[+OFFS|%return] [ARG ...]", |
176 | #else | 176 | #else |
177 | "FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]", | 177 | "[EVENT=]FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]", |
178 | #endif | 178 | #endif |
179 | "probe point definition, where\n" | 179 | "probe point definition, where\n" |
180 | "\t\tGRP:\tGroup name (optional)\n" | 180 | "\t\tGROUP:\tGroup name (optional)\n" |
181 | "\t\tNAME:\tEvent name\n" | 181 | "\t\tEVENT:\tEvent name\n" |
182 | "\t\tFUNC:\tFunction name\n" | 182 | "\t\tFUNC:\tFunction name\n" |
183 | "\t\tOFFS:\tOffset from function entry (in byte)\n" | 183 | "\t\tOFFS:\tOffset from function entry (in byte)\n" |
184 | "\t\t%return:\tPut the probe at function return\n" | 184 | "\t\t%return:\tPut the probe at function return\n" |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 5e99e52b0179..3b4cf456165c 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -69,10 +69,23 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) | |||
69 | char c, nc = 0; | 69 | char c, nc = 0; |
70 | /* | 70 | /* |
71 | * <Syntax> | 71 | * <Syntax> |
72 | * perf probe SRC:LN | 72 | * perf probe [EVENT=]SRC:LN |
73 | * perf probe FUNC[+OFFS|%return][@SRC] | 73 | * perf probe [EVENT=]FUNC[+OFFS|%return][@SRC] |
74 | * | ||
75 | * TODO:Group name support | ||
74 | */ | 76 | */ |
75 | 77 | ||
78 | ptr = strchr(arg, '='); | ||
79 | if (ptr) { /* Event name */ | ||
80 | *ptr = '\0'; | ||
81 | tmp = ptr + 1; | ||
82 | ptr = strchr(arg, ':'); | ||
83 | if (ptr) /* Group name is not supported yet. */ | ||
84 | semantic_error("Group name is not supported yet."); | ||
85 | pp->event = strdup(arg); | ||
86 | arg = tmp; | ||
87 | } | ||
88 | |||
76 | ptr = strpbrk(arg, ":+@%"); | 89 | ptr = strpbrk(arg, ":+@%"); |
77 | if (ptr) { | 90 | if (ptr) { |
78 | nc = *ptr; | 91 | nc = *ptr; |
@@ -188,8 +201,7 @@ void parse_perf_probe_event(const char *str, struct probe_point *pp, | |||
188 | } | 201 | } |
189 | 202 | ||
190 | /* Parse kprobe_events event into struct probe_point */ | 203 | /* Parse kprobe_events event into struct probe_point */ |
191 | void parse_trace_kprobe_event(const char *str, char **group, char **event, | 204 | void parse_trace_kprobe_event(const char *str, struct probe_point *pp) |
192 | struct probe_point *pp) | ||
193 | { | 205 | { |
194 | char pr; | 206 | char pr; |
195 | char *p; | 207 | char *p; |
@@ -205,18 +217,17 @@ void parse_trace_kprobe_event(const char *str, char **group, char **event, | |||
205 | 217 | ||
206 | /* Scan event and group name. */ | 218 | /* Scan event and group name. */ |
207 | ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", | 219 | ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", |
208 | &pr, (float *)(void *)group, (float *)(void *)event); | 220 | &pr, (float *)(void *)&pp->group, |
221 | (float *)(void *)&pp->event); | ||
209 | if (ret != 3) | 222 | if (ret != 3) |
210 | semantic_error("Failed to parse event name: %s", argv[0]); | 223 | semantic_error("Failed to parse event name: %s", argv[0]); |
211 | pr_debug("Group:%s Event:%s probe:%c\n", *group, *event, pr); | 224 | pr_debug("Group:%s Event:%s probe:%c\n", pp->group, pp->event, pr); |
212 | |||
213 | if (!pp) | ||
214 | goto end; | ||
215 | 225 | ||
216 | pp->retprobe = (pr == 'r'); | 226 | pp->retprobe = (pr == 'r'); |
217 | 227 | ||
218 | /* Scan function name and offset */ | 228 | /* Scan function name and offset */ |
219 | ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function, &pp->offset); | 229 | ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function, |
230 | &pp->offset); | ||
220 | if (ret == 1) | 231 | if (ret == 1) |
221 | pp->offset = 0; | 232 | pp->offset = 0; |
222 | 233 | ||
@@ -235,7 +246,6 @@ void parse_trace_kprobe_event(const char *str, char **group, char **event, | |||
235 | die("Failed to copy argument."); | 246 | die("Failed to copy argument."); |
236 | } | 247 | } |
237 | 248 | ||
238 | end: | ||
239 | argv_free(argv); | 249 | argv_free(argv); |
240 | } | 250 | } |
241 | 251 | ||
@@ -368,6 +378,10 @@ static void clear_probe_point(struct probe_point *pp) | |||
368 | { | 378 | { |
369 | int i; | 379 | int i; |
370 | 380 | ||
381 | if (pp->event) | ||
382 | free(pp->event); | ||
383 | if (pp->group) | ||
384 | free(pp->group); | ||
371 | if (pp->function) | 385 | if (pp->function) |
372 | free(pp->function); | 386 | free(pp->function); |
373 | if (pp->file) | 387 | if (pp->file) |
@@ -382,13 +396,13 @@ static void clear_probe_point(struct probe_point *pp) | |||
382 | } | 396 | } |
383 | 397 | ||
384 | /* Show an event */ | 398 | /* Show an event */ |
385 | static void show_perf_probe_event(const char *group, const char *event, | 399 | static void show_perf_probe_event(const char *event, const char *place, |
386 | const char *place, struct probe_point *pp) | 400 | struct probe_point *pp) |
387 | { | 401 | { |
388 | int i, ret; | 402 | int i, ret; |
389 | char buf[128]; | 403 | char buf[128]; |
390 | 404 | ||
391 | ret = e_snprintf(buf, 128, "%s:%s", group, event); | 405 | ret = e_snprintf(buf, 128, "%s:%s", pp->group, event); |
392 | if (ret < 0) | 406 | if (ret < 0) |
393 | die("Failed to copy event: %s", strerror(-ret)); | 407 | die("Failed to copy event: %s", strerror(-ret)); |
394 | printf(" %-40s (on %s", buf, place); | 408 | printf(" %-40s (on %s", buf, place); |
@@ -405,7 +419,6 @@ static void show_perf_probe_event(const char *group, const char *event, | |||
405 | void show_perf_probe_events(void) | 419 | void show_perf_probe_events(void) |
406 | { | 420 | { |
407 | int fd, nr; | 421 | int fd, nr; |
408 | char *group, *event; | ||
409 | struct probe_point pp; | 422 | struct probe_point pp; |
410 | struct strlist *rawlist; | 423 | struct strlist *rawlist; |
411 | struct str_node *ent; | 424 | struct str_node *ent; |
@@ -415,16 +428,14 @@ void show_perf_probe_events(void) | |||
415 | close(fd); | 428 | close(fd); |
416 | 429 | ||
417 | strlist__for_each(ent, rawlist) { | 430 | strlist__for_each(ent, rawlist) { |
418 | parse_trace_kprobe_event(ent->s, &group, &event, &pp); | 431 | parse_trace_kprobe_event(ent->s, &pp); |
419 | /* Synthesize only event probe point */ | 432 | /* Synthesize only event probe point */ |
420 | nr = pp.nr_args; | 433 | nr = pp.nr_args; |
421 | pp.nr_args = 0; | 434 | pp.nr_args = 0; |
422 | synthesize_perf_probe_event(&pp); | 435 | synthesize_perf_probe_event(&pp); |
423 | pp.nr_args = nr; | 436 | pp.nr_args = nr; |
424 | /* Show an event */ | 437 | /* Show an event */ |
425 | show_perf_probe_event(group, event, pp.probes[0], &pp); | 438 | show_perf_probe_event(pp.event, pp.probes[0], &pp); |
426 | free(group); | ||
427 | free(event); | ||
428 | clear_probe_point(&pp); | 439 | clear_probe_point(&pp); |
429 | } | 440 | } |
430 | 441 | ||
@@ -434,24 +445,25 @@ void show_perf_probe_events(void) | |||
434 | /* Get current perf-probe event names */ | 445 | /* Get current perf-probe event names */ |
435 | static struct strlist *get_perf_event_names(int fd, bool include_group) | 446 | static struct strlist *get_perf_event_names(int fd, bool include_group) |
436 | { | 447 | { |
437 | char *group, *event; | ||
438 | char buf[128]; | 448 | char buf[128]; |
439 | struct strlist *sl, *rawlist; | 449 | struct strlist *sl, *rawlist; |
440 | struct str_node *ent; | 450 | struct str_node *ent; |
451 | struct probe_point pp; | ||
441 | 452 | ||
453 | memset(&pp, 0, sizeof(pp)); | ||
442 | rawlist = get_trace_kprobe_event_rawlist(fd); | 454 | rawlist = get_trace_kprobe_event_rawlist(fd); |
443 | 455 | ||
444 | sl = strlist__new(true, NULL); | 456 | sl = strlist__new(true, NULL); |
445 | strlist__for_each(ent, rawlist) { | 457 | strlist__for_each(ent, rawlist) { |
446 | parse_trace_kprobe_event(ent->s, &group, &event, NULL); | 458 | parse_trace_kprobe_event(ent->s, &pp); |
447 | if (include_group) { | 459 | if (include_group) { |
448 | if (e_snprintf(buf, 128, "%s:%s", group, event) < 0) | 460 | if (e_snprintf(buf, 128, "%s:%s", pp.group, |
461 | pp.event) < 0) | ||
449 | die("Failed to copy group:event name."); | 462 | die("Failed to copy group:event name."); |
450 | strlist__add(sl, buf); | 463 | strlist__add(sl, buf); |
451 | } else | 464 | } else |
452 | strlist__add(sl, event); | 465 | strlist__add(sl, pp.event); |
453 | free(group); | 466 | clear_probe_point(&pp); |
454 | free(event); | ||
455 | } | 467 | } |
456 | 468 | ||
457 | strlist__delete(rawlist); | 469 | strlist__delete(rawlist); |
@@ -507,19 +519,23 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes) | |||
507 | 519 | ||
508 | for (j = 0; j < nr_probes; j++) { | 520 | for (j = 0; j < nr_probes; j++) { |
509 | pp = probes + j; | 521 | pp = probes + j; |
522 | if (!pp->event) | ||
523 | pp->event = strdup(pp->function); | ||
524 | if (!pp->group) | ||
525 | pp->group = strdup(PERFPROBE_GROUP); | ||
526 | DIE_IF(!pp->event || !pp->group); | ||
510 | for (i = 0; i < pp->found; i++) { | 527 | for (i = 0; i < pp->found; i++) { |
511 | /* Get an unused new event name */ | 528 | /* Get an unused new event name */ |
512 | get_new_event_name(event, 64, pp->function, namelist); | 529 | get_new_event_name(event, 64, pp->event, namelist); |
513 | snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n", | 530 | snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n", |
514 | pp->retprobe ? 'r' : 'p', | 531 | pp->retprobe ? 'r' : 'p', |
515 | PERFPROBE_GROUP, event, | 532 | pp->group, event, |
516 | pp->probes[i]); | 533 | pp->probes[i]); |
517 | write_trace_kprobe_event(fd, buf); | 534 | write_trace_kprobe_event(fd, buf); |
518 | printf("Added new event:\n"); | 535 | printf("Added new event:\n"); |
519 | /* Get the first parameter (probe-point) */ | 536 | /* Get the first parameter (probe-point) */ |
520 | sscanf(pp->probes[i], "%s", buf); | 537 | sscanf(pp->probes[i], "%s", buf); |
521 | show_perf_probe_event(PERFPROBE_GROUP, event, | 538 | show_perf_probe_event(event, buf, pp); |
522 | buf, pp); | ||
523 | /* Add added event name to namelist */ | 539 | /* Add added event name to namelist */ |
524 | strlist__add(namelist, event); | 540 | strlist__add(namelist, event); |
525 | } | 541 | } |
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 028575b5fc3b..8bb22f5246cc 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
@@ -8,8 +8,7 @@ | |||
8 | extern void parse_perf_probe_event(const char *str, struct probe_point *pp, | 8 | extern void parse_perf_probe_event(const char *str, struct probe_point *pp, |
9 | bool *need_dwarf); | 9 | bool *need_dwarf); |
10 | extern int synthesize_perf_probe_event(struct probe_point *pp); | 10 | extern int synthesize_perf_probe_event(struct probe_point *pp); |
11 | extern void parse_trace_kprobe_event(const char *str, char **group, | 11 | extern void parse_trace_kprobe_event(const char *str, struct probe_point *pp); |
12 | char **event, struct probe_point *pp); | ||
13 | extern int synthesize_trace_kprobe_event(struct probe_point *pp); | 12 | extern int synthesize_trace_kprobe_event(struct probe_point *pp); |
14 | extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes); | 13 | extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes); |
15 | extern void del_trace_kprobe_events(struct strlist *dellist); | 14 | extern void del_trace_kprobe_events(struct strlist *dellist); |
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index bdebca6697d2..5e4050ce2963 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h | |||
@@ -12,6 +12,9 @@ static inline int is_c_varname(const char *name) | |||
12 | } | 12 | } |
13 | 13 | ||
14 | struct probe_point { | 14 | struct probe_point { |
15 | char *event; /* Event name */ | ||
16 | char *group; /* Event group */ | ||
17 | |||
15 | /* Inputs */ | 18 | /* Inputs */ |
16 | char *file; /* File name */ | 19 | char *file; /* File name */ |
17 | int line; /* Line number */ | 20 | int line; /* Line number */ |