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 | |
| 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>
| -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 */ |
