diff options
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r-- | tools/perf/util/parse-events.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 6b6d03e93c3d..2d8d53bec17e 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -722,6 +722,27 @@ static int get_event_modifier(struct event_modifier *mod, char *str, | |||
722 | return 0; | 722 | return 0; |
723 | } | 723 | } |
724 | 724 | ||
725 | /* | ||
726 | * Basic modifier sanity check to validate it contains only one | ||
727 | * instance of any modifier (apart from 'p') present. | ||
728 | */ | ||
729 | static int check_modifier(char *str) | ||
730 | { | ||
731 | char *p = str; | ||
732 | |||
733 | /* The sizeof includes 0 byte as well. */ | ||
734 | if (strlen(str) > (sizeof("ukhGHppp") - 1)) | ||
735 | return -1; | ||
736 | |||
737 | while (*p) { | ||
738 | if (*p != 'p' && strchr(p + 1, *p)) | ||
739 | return -1; | ||
740 | p++; | ||
741 | } | ||
742 | |||
743 | return 0; | ||
744 | } | ||
745 | |||
725 | int parse_events__modifier_event(struct list_head *list, char *str, bool add) | 746 | int parse_events__modifier_event(struct list_head *list, char *str, bool add) |
726 | { | 747 | { |
727 | struct perf_evsel *evsel; | 748 | struct perf_evsel *evsel; |
@@ -730,6 +751,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) | |||
730 | if (str == NULL) | 751 | if (str == NULL) |
731 | return 0; | 752 | return 0; |
732 | 753 | ||
754 | if (check_modifier(str)) | ||
755 | return -EINVAL; | ||
756 | |||
733 | if (!add && get_event_modifier(&mod, str, NULL)) | 757 | if (!add && get_event_modifier(&mod, str, NULL)) |
734 | return -EINVAL; | 758 | return -EINVAL; |
735 | 759 | ||
@@ -827,8 +851,6 @@ int parse_events(struct perf_evlist *evlist, const char *str, | |||
827 | * Both call perf_evlist__delete in case of error, so we dont | 851 | * Both call perf_evlist__delete in case of error, so we dont |
828 | * need to bother. | 852 | * need to bother. |
829 | */ | 853 | */ |
830 | fprintf(stderr, "invalid or unsupported event: '%s'\n", str); | ||
831 | fprintf(stderr, "Run 'perf list' for a list of valid events\n"); | ||
832 | return ret; | 854 | return ret; |
833 | } | 855 | } |
834 | 856 | ||
@@ -836,7 +858,13 @@ int parse_events_option(const struct option *opt, const char *str, | |||
836 | int unset __maybe_unused) | 858 | int unset __maybe_unused) |
837 | { | 859 | { |
838 | struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; | 860 | struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; |
839 | return parse_events(evlist, str, unset); | 861 | int ret = parse_events(evlist, str, unset); |
862 | |||
863 | if (ret) { | ||
864 | fprintf(stderr, "invalid or unsupported event: '%s'\n", str); | ||
865 | fprintf(stderr, "Run 'perf list' for a list of valid events\n"); | ||
866 | } | ||
867 | return ret; | ||
840 | } | 868 | } |
841 | 869 | ||
842 | int parse_filter(const struct option *opt, const char *str, | 870 | int parse_filter(const struct option *opt, const char *str, |
@@ -1081,7 +1109,7 @@ void print_events(const char *event_glob, bool name_only) | |||
1081 | printf(" %-50s [%s]\n", | 1109 | printf(" %-50s [%s]\n", |
1082 | "cpu/t1=v1[,t2=v2,t3 ...]/modifier", | 1110 | "cpu/t1=v1[,t2=v2,t3 ...]/modifier", |
1083 | event_type_descriptors[PERF_TYPE_RAW]); | 1111 | event_type_descriptors[PERF_TYPE_RAW]); |
1084 | printf(" (see 'perf list --help' on how to encode it)\n"); | 1112 | printf(" (see 'man perf-list' on how to encode it)\n"); |
1085 | printf("\n"); | 1113 | printf("\n"); |
1086 | 1114 | ||
1087 | printf(" %-50s [%s]\n", | 1115 | printf(" %-50s [%s]\n", |
@@ -1142,6 +1170,24 @@ int parse_events__term_str(struct parse_events__term **term, | |||
1142 | config, str, 0); | 1170 | config, str, 0); |
1143 | } | 1171 | } |
1144 | 1172 | ||
1173 | int parse_events__term_sym_hw(struct parse_events__term **term, | ||
1174 | char *config, unsigned idx) | ||
1175 | { | ||
1176 | struct event_symbol *sym; | ||
1177 | |||
1178 | BUG_ON(idx >= PERF_COUNT_HW_MAX); | ||
1179 | sym = &event_symbols_hw[idx]; | ||
1180 | |||
1181 | if (config) | ||
1182 | return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, | ||
1183 | PARSE_EVENTS__TERM_TYPE_USER, config, | ||
1184 | (char *) sym->symbol, 0); | ||
1185 | else | ||
1186 | return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, | ||
1187 | PARSE_EVENTS__TERM_TYPE_USER, | ||
1188 | (char *) "event", (char *) sym->symbol, 0); | ||
1189 | } | ||
1190 | |||
1145 | int parse_events__term_clone(struct parse_events__term **new, | 1191 | int parse_events__term_clone(struct parse_events__term **new, |
1146 | struct parse_events__term *term) | 1192 | struct parse_events__term *term) |
1147 | { | 1193 | { |