aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-probe.txt3
-rw-r--r--tools/perf/builtin-probe.c8
-rw-r--r--tools/perf/util/probe-event.c74
-rw-r--r--tools/perf/util/probe-event.h3
-rw-r--r--tools/perf/util/probe-finder.h3
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------------
50Probe points are defined by following syntax. 50Probe 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.
55It 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. 56It 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 */
191void parse_trace_kprobe_event(const char *str, char **group, char **event, 204void 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
238end:
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 */
385static void show_perf_probe_event(const char *group, const char *event, 399static 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,
405void show_perf_probe_events(void) 419void 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 */
435static struct strlist *get_perf_event_names(int fd, bool include_group) 446static 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 @@
8extern void parse_perf_probe_event(const char *str, struct probe_point *pp, 8extern void parse_perf_probe_event(const char *str, struct probe_point *pp,
9 bool *need_dwarf); 9 bool *need_dwarf);
10extern int synthesize_perf_probe_event(struct probe_point *pp); 10extern int synthesize_perf_probe_event(struct probe_point *pp);
11extern void parse_trace_kprobe_event(const char *str, char **group, 11extern void parse_trace_kprobe_event(const char *str, struct probe_point *pp);
12 char **event, struct probe_point *pp);
13extern int synthesize_trace_kprobe_event(struct probe_point *pp); 12extern int synthesize_trace_kprobe_event(struct probe_point *pp);
14extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes); 13extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes);
15extern void del_trace_kprobe_events(struct strlist *dellist); 14extern 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
14struct probe_point { 14struct 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 */