aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/parse-events.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r--tools/perf/util/parse-events.c237
1 files changed, 185 insertions, 52 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index a587d41ae3c9..89172fd0038b 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -6,6 +6,7 @@
6#include "exec_cmd.h" 6#include "exec_cmd.h"
7#include "string.h" 7#include "string.h"
8#include "cache.h" 8#include "cache.h"
9#include "header.h"
9 10
10int nr_counters; 11int nr_counters;
11 12
@@ -18,6 +19,12 @@ struct event_symbol {
18 const char *alias; 19 const char *alias;
19}; 20};
20 21
22enum event_result {
23 EVT_FAILED,
24 EVT_HANDLED,
25 EVT_HANDLED_ALL
26};
27
21char debugfs_path[MAXPATHLEN]; 28char debugfs_path[MAXPATHLEN];
22 29
23#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 30#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
@@ -139,7 +146,7 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
139 (strcmp(evt_dirent.d_name, "..")) && \ 146 (strcmp(evt_dirent.d_name, "..")) && \
140 (!tp_event_has_id(&sys_dirent, &evt_dirent))) 147 (!tp_event_has_id(&sys_dirent, &evt_dirent)))
141 148
142#define MAX_EVENT_LENGTH 30 149#define MAX_EVENT_LENGTH 512
143 150
144int valid_debugfs_mount(const char *debugfs) 151int valid_debugfs_mount(const char *debugfs)
145{ 152{
@@ -344,7 +351,7 @@ static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int
344 return -1; 351 return -1;
345} 352}
346 353
347static int 354static enum event_result
348parse_generic_hw_event(const char **str, struct perf_counter_attr *attr) 355parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
349{ 356{
350 const char *s = *str; 357 const char *s = *str;
@@ -356,7 +363,7 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
356 * then bail out: 363 * then bail out:
357 */ 364 */
358 if (cache_type == -1) 365 if (cache_type == -1)
359 return 0; 366 return EVT_FAILED;
360 367
361 while ((cache_op == -1 || cache_result == -1) && *s == '-') { 368 while ((cache_op == -1 || cache_result == -1) && *s == '-') {
362 ++s; 369 ++s;
@@ -402,27 +409,115 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
402 attr->type = PERF_TYPE_HW_CACHE; 409 attr->type = PERF_TYPE_HW_CACHE;
403 410
404 *str = s; 411 *str = s;
405 return 1; 412 return EVT_HANDLED;
413}
414
415static enum event_result
416parse_single_tracepoint_event(char *sys_name,
417 const char *evt_name,
418 unsigned int evt_length,
419 char *flags,
420 struct perf_counter_attr *attr,
421 const char **strp)
422{
423 char evt_path[MAXPATHLEN];
424 char id_buf[4];
425 u64 id;
426 int fd;
427
428 if (flags) {
429 if (!strncmp(flags, "record", strlen(flags))) {
430 attr->sample_type |= PERF_SAMPLE_RAW;
431 attr->sample_type |= PERF_SAMPLE_TIME;
432 attr->sample_type |= PERF_SAMPLE_CPU;
433 }
434 }
435
436 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
437 sys_name, evt_name);
438
439 fd = open(evt_path, O_RDONLY);
440 if (fd < 0)
441 return EVT_FAILED;
442
443 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
444 close(fd);
445 return EVT_FAILED;
446 }
447
448 close(fd);
449 id = atoll(id_buf);
450 attr->config = id;
451 attr->type = PERF_TYPE_TRACEPOINT;
452 *strp = evt_name + evt_length;
453
454 return EVT_HANDLED;
455}
456
457/* sys + ':' + event + ':' + flags*/
458#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128)
459static enum event_result
460parse_subsystem_tracepoint_event(char *sys_name, char *flags)
461{
462 char evt_path[MAXPATHLEN];
463 struct dirent *evt_ent;
464 DIR *evt_dir;
465
466 snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
467 evt_dir = opendir(evt_path);
468
469 if (!evt_dir) {
470 perror("Can't open event dir");
471 return EVT_FAILED;
472 }
473
474 while ((evt_ent = readdir(evt_dir))) {
475 char event_opt[MAX_EVOPT_LEN + 1];
476 int len;
477 unsigned int rem = MAX_EVOPT_LEN;
478
479 if (!strcmp(evt_ent->d_name, ".")
480 || !strcmp(evt_ent->d_name, "..")
481 || !strcmp(evt_ent->d_name, "enable")
482 || !strcmp(evt_ent->d_name, "filter"))
483 continue;
484
485 len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name,
486 evt_ent->d_name);
487 if (len < 0)
488 return EVT_FAILED;
489
490 rem -= len;
491 if (flags) {
492 if (rem < strlen(flags) + 1)
493 return EVT_FAILED;
494
495 strcat(event_opt, ":");
496 strcat(event_opt, flags);
497 }
498
499 if (parse_events(NULL, event_opt, 0))
500 return EVT_FAILED;
501 }
502
503 return EVT_HANDLED_ALL;
406} 504}
407 505
408static int parse_tracepoint_event(const char **strp, 506
507static enum event_result parse_tracepoint_event(const char **strp,
409 struct perf_counter_attr *attr) 508 struct perf_counter_attr *attr)
410{ 509{
411 const char *evt_name; 510 const char *evt_name;
412 char *flags; 511 char *flags;
413 char sys_name[MAX_EVENT_LENGTH]; 512 char sys_name[MAX_EVENT_LENGTH];
414 char id_buf[4];
415 int fd;
416 unsigned int sys_length, evt_length; 513 unsigned int sys_length, evt_length;
417 u64 id;
418 char evt_path[MAXPATHLEN];
419 514
420 if (valid_debugfs_mount(debugfs_path)) 515 if (valid_debugfs_mount(debugfs_path))
421 return 0; 516 return 0;
422 517
423 evt_name = strchr(*strp, ':'); 518 evt_name = strchr(*strp, ':');
424 if (!evt_name) 519 if (!evt_name)
425 return 0; 520 return EVT_FAILED;
426 521
427 sys_length = evt_name - *strp; 522 sys_length = evt_name - *strp;
428 if (sys_length >= MAX_EVENT_LENGTH) 523 if (sys_length >= MAX_EVENT_LENGTH)
@@ -434,32 +529,22 @@ static int parse_tracepoint_event(const char **strp,
434 529
435 flags = strchr(evt_name, ':'); 530 flags = strchr(evt_name, ':');
436 if (flags) { 531 if (flags) {
437 *flags = '\0'; 532 /* split it out: */
533 evt_name = strndup(evt_name, flags - evt_name);
438 flags++; 534 flags++;
439 if (!strncmp(flags, "record", strlen(flags)))
440 attr->sample_type |= PERF_SAMPLE_RAW;
441 } 535 }
442 536
443 evt_length = strlen(evt_name); 537 evt_length = strlen(evt_name);
444 if (evt_length >= MAX_EVENT_LENGTH) 538 if (evt_length >= MAX_EVENT_LENGTH)
445 return 0; 539 return EVT_FAILED;
446
447 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
448 sys_name, evt_name);
449 fd = open(evt_path, O_RDONLY);
450 if (fd < 0)
451 return 0;
452 540
453 if (read(fd, id_buf, sizeof(id_buf)) < 0) { 541 if (!strcmp(evt_name, "*")) {
454 close(fd); 542 *strp = evt_name + evt_length;
455 return 0; 543 return parse_subsystem_tracepoint_event(sys_name, flags);
456 } 544 } else
457 close(fd); 545 return parse_single_tracepoint_event(sys_name, evt_name,
458 id = atoll(id_buf); 546 evt_length, flags,
459 attr->config = id; 547 attr, strp);
460 attr->type = PERF_TYPE_TRACEPOINT;
461 *strp = evt_name + evt_length;
462 return 1;
463} 548}
464 549
465static int check_events(const char *str, unsigned int i) 550static int check_events(const char *str, unsigned int i)
@@ -477,7 +562,7 @@ static int check_events(const char *str, unsigned int i)
477 return 0; 562 return 0;
478} 563}
479 564
480static int 565static enum event_result
481parse_symbolic_event(const char **strp, struct perf_counter_attr *attr) 566parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
482{ 567{
483 const char *str = *strp; 568 const char *str = *strp;
@@ -490,31 +575,32 @@ parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
490 attr->type = event_symbols[i].type; 575 attr->type = event_symbols[i].type;
491 attr->config = event_symbols[i].config; 576 attr->config = event_symbols[i].config;
492 *strp = str + n; 577 *strp = str + n;
493 return 1; 578 return EVT_HANDLED;
494 } 579 }
495 } 580 }
496 return 0; 581 return EVT_FAILED;
497} 582}
498 583
499static int parse_raw_event(const char **strp, struct perf_counter_attr *attr) 584static enum event_result
585parse_raw_event(const char **strp, struct perf_counter_attr *attr)
500{ 586{
501 const char *str = *strp; 587 const char *str = *strp;
502 u64 config; 588 u64 config;
503 int n; 589 int n;
504 590
505 if (*str != 'r') 591 if (*str != 'r')
506 return 0; 592 return EVT_FAILED;
507 n = hex2u64(str + 1, &config); 593 n = hex2u64(str + 1, &config);
508 if (n > 0) { 594 if (n > 0) {
509 *strp = str + n + 1; 595 *strp = str + n + 1;
510 attr->type = PERF_TYPE_RAW; 596 attr->type = PERF_TYPE_RAW;
511 attr->config = config; 597 attr->config = config;
512 return 1; 598 return EVT_HANDLED;
513 } 599 }
514 return 0; 600 return EVT_FAILED;
515} 601}
516 602
517static int 603static enum event_result
518parse_numeric_event(const char **strp, struct perf_counter_attr *attr) 604parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
519{ 605{
520 const char *str = *strp; 606 const char *str = *strp;
@@ -530,13 +616,13 @@ parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
530 attr->type = type; 616 attr->type = type;
531 attr->config = config; 617 attr->config = config;
532 *strp = endp; 618 *strp = endp;
533 return 1; 619 return EVT_HANDLED;
534 } 620 }
535 } 621 }
536 return 0; 622 return EVT_FAILED;
537} 623}
538 624
539static int 625static enum event_result
540parse_event_modifier(const char **strp, struct perf_counter_attr *attr) 626parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
541{ 627{
542 const char *str = *strp; 628 const char *str = *strp;
@@ -569,37 +655,84 @@ parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
569 * Each event can have multiple symbolic names. 655 * Each event can have multiple symbolic names.
570 * Symbolic names are (almost) exactly matched. 656 * Symbolic names are (almost) exactly matched.
571 */ 657 */
572static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) 658static enum event_result
659parse_event_symbols(const char **str, struct perf_counter_attr *attr)
573{ 660{
574 if (!(parse_tracepoint_event(str, attr) || 661 enum event_result ret;
575 parse_raw_event(str, attr) || 662
576 parse_numeric_event(str, attr) || 663 ret = parse_tracepoint_event(str, attr);
577 parse_symbolic_event(str, attr) || 664 if (ret != EVT_FAILED)
578 parse_generic_hw_event(str, attr))) 665 goto modifier;
579 return 0; 666
667 ret = parse_raw_event(str, attr);
668 if (ret != EVT_FAILED)
669 goto modifier;
670
671 ret = parse_numeric_event(str, attr);
672 if (ret != EVT_FAILED)
673 goto modifier;
674
675 ret = parse_symbolic_event(str, attr);
676 if (ret != EVT_FAILED)
677 goto modifier;
580 678
679 ret = parse_generic_hw_event(str, attr);
680 if (ret != EVT_FAILED)
681 goto modifier;
682
683 return EVT_FAILED;
684
685modifier:
581 parse_event_modifier(str, attr); 686 parse_event_modifier(str, attr);
582 687
583 return 1; 688 return ret;
584} 689}
585 690
691static void store_event_type(const char *orgname)
692{
693 char filename[PATH_MAX], *c;
694 FILE *file;
695 int id;
696
697 sprintf(filename, "/sys/kernel/debug/tracing/events/%s/id", orgname);
698 c = strchr(filename, ':');
699 if (c)
700 *c = '/';
701
702 file = fopen(filename, "r");
703 if (!file)
704 return;
705 if (fscanf(file, "%i", &id) < 1)
706 die("cannot store event ID");
707 fclose(file);
708 perf_header__push_event(id, orgname);
709}
710
711
586int parse_events(const struct option *opt __used, const char *str, int unset __used) 712int parse_events(const struct option *opt __used, const char *str, int unset __used)
587{ 713{
588 struct perf_counter_attr attr; 714 struct perf_counter_attr attr;
715 enum event_result ret;
716
717 if (strchr(str, ':'))
718 store_event_type(str);
589 719
590 for (;;) { 720 for (;;) {
591 if (nr_counters == MAX_COUNTERS) 721 if (nr_counters == MAX_COUNTERS)
592 return -1; 722 return -1;
593 723
594 memset(&attr, 0, sizeof(attr)); 724 memset(&attr, 0, sizeof(attr));
595 if (!parse_event_symbols(&str, &attr)) 725 ret = parse_event_symbols(&str, &attr);
726 if (ret == EVT_FAILED)
596 return -1; 727 return -1;
597 728
598 if (!(*str == 0 || *str == ',' || isspace(*str))) 729 if (!(*str == 0 || *str == ',' || isspace(*str)))
599 return -1; 730 return -1;
600 731
601 attrs[nr_counters] = attr; 732 if (ret != EVT_HANDLED_ALL) {
602 nr_counters++; 733 attrs[nr_counters] = attr;
734 nr_counters++;
735 }
603 736
604 if (*str == 0) 737 if (*str == 0)
605 break; 738 break;