aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-event.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r--tools/perf/util/probe-event.c133
1 files changed, 118 insertions, 15 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index cd7fbda5e2a5..d14a4585bcaf 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -48,6 +48,9 @@
48 48
49/* If there is no space to write, returns -E2BIG. */ 49/* If there is no space to write, returns -E2BIG. */
50static int e_snprintf(char *str, size_t size, const char *format, ...) 50static int e_snprintf(char *str, size_t size, const char *format, ...)
51 __attribute__((format(printf, 3, 4)));
52
53static int e_snprintf(char *str, size_t size, const char *format, ...)
51{ 54{
52 int ret; 55 int ret;
53 va_list ap; 56 va_list ap;
@@ -258,7 +261,7 @@ int synthesize_perf_probe_event(struct probe_point *pp)
258 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function, 261 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function,
259 offs, pp->retprobe ? "%return" : "", line); 262 offs, pp->retprobe ? "%return" : "", line);
260 else 263 else
261 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->file, line); 264 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line);
262 if (ret <= 0) 265 if (ret <= 0)
263 goto error; 266 goto error;
264 len = ret; 267 len = ret;
@@ -373,14 +376,32 @@ static void clear_probe_point(struct probe_point *pp)
373 free(pp->args); 376 free(pp->args);
374 for (i = 0; i < pp->found; i++) 377 for (i = 0; i < pp->found; i++)
375 free(pp->probes[i]); 378 free(pp->probes[i]);
376 memset(pp, 0, sizeof(pp)); 379 memset(pp, 0, sizeof(*pp));
380}
381
382/* Show an event */
383static void show_perf_probe_event(const char *group, const char *event,
384 const char *place, struct probe_point *pp)
385{
386 int i;
387 char buf[128];
388
389 e_snprintf(buf, 128, "%s:%s", group, event);
390 printf(" %-40s (on %s", buf, place);
391
392 if (pp->nr_args > 0) {
393 printf(" with");
394 for (i = 0; i < pp->nr_args; i++)
395 printf(" %s", pp->args[i]);
396 }
397 printf(")\n");
377} 398}
378 399
379/* List up current perf-probe events */ 400/* List up current perf-probe events */
380void show_perf_probe_events(void) 401void show_perf_probe_events(void)
381{ 402{
382 unsigned int i; 403 unsigned int i;
383 int fd; 404 int fd, nr;
384 char *group, *event; 405 char *group, *event;
385 struct probe_point pp; 406 struct probe_point pp;
386 struct strlist *rawlist; 407 struct strlist *rawlist;
@@ -393,8 +414,13 @@ void show_perf_probe_events(void)
393 for (i = 0; i < strlist__nr_entries(rawlist); i++) { 414 for (i = 0; i < strlist__nr_entries(rawlist); i++) {
394 ent = strlist__entry(rawlist, i); 415 ent = strlist__entry(rawlist, i);
395 parse_trace_kprobe_event(ent->s, &group, &event, &pp); 416 parse_trace_kprobe_event(ent->s, &group, &event, &pp);
417 /* Synthesize only event probe point */
418 nr = pp.nr_args;
419 pp.nr_args = 0;
396 synthesize_perf_probe_event(&pp); 420 synthesize_perf_probe_event(&pp);
397 printf("[%s:%s]\t%s\n", group, event, pp.probes[0]); 421 pp.nr_args = nr;
422 /* Show an event */
423 show_perf_probe_event(group, event, pp.probes[0], &pp);
398 free(group); 424 free(group);
399 free(event); 425 free(event);
400 clear_probe_point(&pp); 426 clear_probe_point(&pp);
@@ -404,21 +430,28 @@ void show_perf_probe_events(void)
404} 430}
405 431
406/* Get current perf-probe event names */ 432/* Get current perf-probe event names */
407static struct strlist *get_perf_event_names(int fd) 433static struct strlist *get_perf_event_names(int fd, bool include_group)
408{ 434{
409 unsigned int i; 435 unsigned int i;
410 char *group, *event; 436 char *group, *event;
437 char buf[128];
411 struct strlist *sl, *rawlist; 438 struct strlist *sl, *rawlist;
412 struct str_node *ent; 439 struct str_node *ent;
413 440
414 rawlist = get_trace_kprobe_event_rawlist(fd); 441 rawlist = get_trace_kprobe_event_rawlist(fd);
415 442
416 sl = strlist__new(false, NULL); 443 sl = strlist__new(true, NULL);
417 for (i = 0; i < strlist__nr_entries(rawlist); i++) { 444 for (i = 0; i < strlist__nr_entries(rawlist); i++) {
418 ent = strlist__entry(rawlist, i); 445 ent = strlist__entry(rawlist, i);
419 parse_trace_kprobe_event(ent->s, &group, &event, NULL); 446 parse_trace_kprobe_event(ent->s, &group, &event, NULL);
420 strlist__add(sl, event); 447 if (include_group) {
448 if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
449 die("Failed to copy group:event name.");
450 strlist__add(sl, buf);
451 } else
452 strlist__add(sl, event);
421 free(group); 453 free(group);
454 free(event);
422 } 455 }
423 456
424 strlist__delete(rawlist); 457 strlist__delete(rawlist);
@@ -426,24 +459,30 @@ static struct strlist *get_perf_event_names(int fd)
426 return sl; 459 return sl;
427} 460}
428 461
429static int write_trace_kprobe_event(int fd, const char *buf) 462static void write_trace_kprobe_event(int fd, const char *buf)
430{ 463{
431 int ret; 464 int ret;
432 465
466 pr_debug("Writing event: %s\n", buf);
433 ret = write(fd, buf, strlen(buf)); 467 ret = write(fd, buf, strlen(buf));
434 if (ret <= 0) 468 if (ret <= 0)
435 die("Failed to create event."); 469 die("Failed to write event: %s", strerror(errno));
436 else
437 printf("Added new event: %s\n", buf);
438
439 return ret;
440} 470}
441 471
442static void get_new_event_name(char *buf, size_t len, const char *base, 472static void get_new_event_name(char *buf, size_t len, const char *base,
443 struct strlist *namelist) 473 struct strlist *namelist)
444{ 474{
445 int i, ret; 475 int i, ret;
446 for (i = 0; i < MAX_EVENT_INDEX; i++) { 476
477 /* Try no suffix */
478 ret = e_snprintf(buf, len, "%s", base);
479 if (ret < 0)
480 die("snprintf() failed: %s", strerror(-ret));
481 if (!strlist__has_entry(namelist, buf))
482 return;
483
484 /* Try to add suffix */
485 for (i = 1; i < MAX_EVENT_INDEX; i++) {
447 ret = e_snprintf(buf, len, "%s_%d", base, i); 486 ret = e_snprintf(buf, len, "%s_%d", base, i);
448 if (ret < 0) 487 if (ret < 0)
449 die("snprintf() failed: %s", strerror(-ret)); 488 die("snprintf() failed: %s", strerror(-ret));
@@ -464,7 +503,7 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes)
464 503
465 fd = open_kprobe_events(O_RDWR, O_APPEND); 504 fd = open_kprobe_events(O_RDWR, O_APPEND);
466 /* Get current event names */ 505 /* Get current event names */
467 namelist = get_perf_event_names(fd); 506 namelist = get_perf_event_names(fd, false);
468 507
469 for (j = 0; j < nr_probes; j++) { 508 for (j = 0; j < nr_probes; j++) {
470 pp = probes + j; 509 pp = probes + j;
@@ -476,9 +515,73 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes)
476 PERFPROBE_GROUP, event, 515 PERFPROBE_GROUP, event,
477 pp->probes[i]); 516 pp->probes[i]);
478 write_trace_kprobe_event(fd, buf); 517 write_trace_kprobe_event(fd, buf);
518 printf("Added new event:\n");
519 /* Get the first parameter (probe-point) */
520 sscanf(pp->probes[i], "%s", buf);
521 show_perf_probe_event(PERFPROBE_GROUP, event,
522 buf, pp);
479 /* Add added event name to namelist */ 523 /* Add added event name to namelist */
480 strlist__add(namelist, event); 524 strlist__add(namelist, event);
481 } 525 }
482 } 526 }
527 /* Show how to use the event. */
528 printf("\nYou can now use it on all perf tools, such as:\n\n");
529 printf("\tperf record -e %s:%s -a sleep 1\n\n", PERFPROBE_GROUP, event);
530
531 strlist__delete(namelist);
532 close(fd);
533}
534
535static void del_trace_kprobe_event(int fd, const char *group,
536 const char *event, struct strlist *namelist)
537{
538 char buf[128];
539
540 if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
541 die("Failed to copy event.");
542 if (!strlist__has_entry(namelist, buf)) {
543 pr_warning("Warning: event \"%s\" is not found.\n", buf);
544 return;
545 }
546 /* Convert from perf-probe event to trace-kprobe event */
547 if (e_snprintf(buf, 128, "-:%s/%s", group, event) < 0)
548 die("Failed to copy event.");
549
550 write_trace_kprobe_event(fd, buf);
551 printf("Remove event: %s:%s\n", group, event);
552}
553
554void del_trace_kprobe_events(struct strlist *dellist)
555{
556 int fd;
557 unsigned int i;
558 const char *group, *event;
559 char *p, *str;
560 struct str_node *ent;
561 struct strlist *namelist;
562
563 fd = open_kprobe_events(O_RDWR, O_APPEND);
564 /* Get current event names */
565 namelist = get_perf_event_names(fd, true);
566
567 for (i = 0; i < strlist__nr_entries(dellist); i++) {
568 ent = strlist__entry(dellist, i);
569 str = strdup(ent->s);
570 if (!str)
571 die("Failed to copy event.");
572 p = strchr(str, ':');
573 if (p) {
574 group = str;
575 *p = '\0';
576 event = p + 1;
577 } else {
578 group = PERFPROBE_GROUP;
579 event = str;
580 }
581 del_trace_kprobe_event(fd, group, event, namelist);
582 free(str);
583 }
584 strlist__delete(namelist);
483 close(fd); 585 close(fd);
484} 586}
587