1 %define api.pure full
2 %parse-param {void *_parse_state}
3 %parse-param {void *scanner}
4 %lex-param {void* scanner}
5 %locations
6
7 %{
8
9 #define YYDEBUG 1
10
11 #include <errno.h>
12 #include <fnmatch.h>
13 #include <stdio.h>
14 #include <linux/compiler.h>
15 #include <linux/types.h>
16 #include <linux/zalloc.h>
17 #include "pmu.h"
18 #include "pmus.h"
19 #include "evsel.h"
20 #include "parse-events.h"
21 #include "parse-events-bison.h"
22
23 int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner);
24 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
25
26 #define PE_ABORT(val) \
27 do { \
28 if (val == -ENOMEM) \
29 YYNOMEM; \
30 YYABORT; \
31 } while (0)
32
alloc_list(void)33 static struct list_head* alloc_list(void)
34 {
35 struct list_head *list;
36
37 list = malloc(sizeof(*list));
38 if (!list)
39 return NULL;
40
41 INIT_LIST_HEAD(list);
42 return list;
43 }
44
free_list_evsel(struct list_head * list_evsel)45 static void free_list_evsel(struct list_head* list_evsel)
46 {
47 struct evsel *evsel, *tmp;
48
49 list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
50 list_del_init(&evsel->core.node);
51 evsel__delete(evsel);
52 }
53 free(list_evsel);
54 }
55
56 %}
57
58 %token PE_START_EVENTS PE_START_TERMS
59 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
60 %token PE_VALUE_SYM_TOOL
61 %token PE_EVENT_NAME
62 %token PE_RAW PE_NAME
63 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
64 %token PE_LEGACY_CACHE
65 %token PE_PREFIX_MEM
66 %token PE_ERROR
67 %token PE_DRV_CFG_TERM
68 %token PE_TERM_HW
69 %type <num> PE_VALUE
70 %type <num> PE_VALUE_SYM_HW
71 %type <num> PE_VALUE_SYM_SW
72 %type <num> PE_VALUE_SYM_TOOL
73 %type <num> PE_TERM
74 %type <num> value_sym
75 %type <str> PE_RAW
76 %type <str> PE_NAME
77 %type <str> PE_LEGACY_CACHE
78 %type <str> PE_MODIFIER_EVENT
79 %type <str> PE_MODIFIER_BP
80 %type <str> PE_EVENT_NAME
81 %type <str> PE_DRV_CFG_TERM
82 %type <str> name_or_raw name_or_legacy
83 %destructor { free ($$); } <str>
84 %type <term> event_term
85 %destructor { parse_events_term__delete ($$); } <term>
86 %type <list_terms> event_config
87 %type <list_terms> opt_event_config
88 %type <list_terms> opt_pmu_config
89 %destructor { parse_events_terms__delete ($$); } <list_terms>
90 %type <list_evsel> event_pmu
91 %type <list_evsel> event_legacy_symbol
92 %type <list_evsel> event_legacy_cache
93 %type <list_evsel> event_legacy_mem
94 %type <list_evsel> event_legacy_tracepoint
95 %type <list_evsel> event_legacy_numeric
96 %type <list_evsel> event_legacy_raw
97 %type <list_evsel> event_def
98 %type <list_evsel> event_mod
99 %type <list_evsel> event_name
100 %type <list_evsel> event
101 %type <list_evsel> events
102 %type <list_evsel> group_def
103 %type <list_evsel> group
104 %type <list_evsel> groups
105 %destructor { free_list_evsel ($$); } <list_evsel>
106 %type <tracepoint_name> tracepoint_name
107 %type <hardware_term> PE_TERM_HW
108 %destructor { free ($$.str); } <hardware_term>
109
110 %union
111 {
112 char *str;
113 u64 num;
114 struct list_head *list_evsel;
115 struct list_head *list_terms;
116 struct parse_events_term *term;
117 struct tracepoint_name {
118 char *sys;
119 char *event;
120 } tracepoint_name;
121 struct hardware_term {
122 char *str;
123 u64 num;
124 } hardware_term;
125 }
126 %%
127
128 start:
129 PE_START_EVENTS start_events
130 |
131 PE_START_TERMS start_terms
132
133 start_events: groups
134 {
135 struct parse_events_state *parse_state = _parse_state;
136
137 /* frees $1 */
138 parse_events_update_lists($1, &parse_state->list);
139 }
140
141 groups:
142 groups ',' group
143 {
144 struct list_head *list = $1;
145 struct list_head *group = $3;
146
147 /* frees $3 */
148 parse_events_update_lists(group, list);
149 $$ = list;
150 }
151 |
152 groups ',' event
153 {
154 struct list_head *list = $1;
155 struct list_head *event = $3;
156
157 /* frees $3 */
158 parse_events_update_lists(event, list);
159 $$ = list;
160 }
161 |
162 group
163 |
164 event
165
166 group:
167 group_def ':' PE_MODIFIER_EVENT
168 {
169 struct list_head *list = $1;
170 int err;
171
172 err = parse_events__modifier_group(list, $3);
173 free($3);
174 if (err) {
175 struct parse_events_state *parse_state = _parse_state;
176 struct parse_events_error *error = parse_state->error;
177
178 parse_events_error__handle(error, @3.first_column,
179 strdup("Bad modifier"), NULL);
180 free_list_evsel(list);
181 YYABORT;
182 }
183 $$ = list;
184 }
185 |
186 group_def
187
188 group_def:
189 PE_NAME '{' events '}'
190 {
191 struct list_head *list = $3;
192
193 /* Takes ownership of $1. */
194 parse_events__set_leader($1, list);
195 $$ = list;
196 }
197 |
198 '{' events '}'
199 {
200 struct list_head *list = $2;
201
202 parse_events__set_leader(NULL, list);
203 $$ = list;
204 }
205
206 events:
207 events ',' event
208 {
209 struct list_head *event = $3;
210 struct list_head *list = $1;
211
212 /* frees $3 */
213 parse_events_update_lists(event, list);
214 $$ = list;
215 }
216 |
217 event
218
219 event: event_mod
220
221 event_mod:
222 event_name PE_MODIFIER_EVENT
223 {
224 struct list_head *list = $1;
225 int err;
226
227 /*
228 * Apply modifier on all events added by single event definition
229 * (there could be more events added for multiple tracepoint
230 * definitions via '*?'.
231 */
232 err = parse_events__modifier_event(list, $2, false);
233 free($2);
234 if (err) {
235 struct parse_events_state *parse_state = _parse_state;
236 struct parse_events_error *error = parse_state->error;
237
238 parse_events_error__handle(error, @2.first_column,
239 strdup("Bad modifier"), NULL);
240 free_list_evsel(list);
241 YYABORT;
242 }
243 $$ = list;
244 }
245 |
246 event_name
247
248 event_name:
249 PE_EVENT_NAME event_def
250 {
251 int err;
252
253 err = parse_events_name($2, $1);
254 free($1);
255 if (err) {
256 free_list_evsel($2);
257 YYNOMEM;
258 }
259 $$ = $2;
260 }
261 |
262 event_def
263
264 event_def: event_pmu |
265 event_legacy_symbol |
266 event_legacy_cache sep_dc |
267 event_legacy_mem sep_dc |
268 event_legacy_tracepoint sep_dc |
269 event_legacy_numeric sep_dc |
270 event_legacy_raw sep_dc
271
272 event_pmu:
273 PE_NAME opt_pmu_config
274 {
275 struct parse_events_state *parse_state = _parse_state;
276 struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL;
277 char *pattern = NULL;
278
279 #define CLEANUP \
280 do { \
281 parse_events_terms__delete($2); \
282 parse_events_terms__delete(orig_terms); \
283 free(list); \
284 free($1); \
285 free(pattern); \
286 } while(0)
287
288 if (parse_events_copy_term_list($2, &orig_terms)) {
289 CLEANUP;
290 YYNOMEM;
291 }
292
293 list = alloc_list();
294 if (!list) {
295 CLEANUP;
296 YYNOMEM;
297 }
298 /* Attempt to add to list assuming $1 is a PMU name. */
299 if (parse_events_add_pmu(parse_state, list, $1, $2, /*auto_merge_stats=*/false, &@1)) {
300 struct perf_pmu *pmu = NULL;
301 int ok = 0;
302
303 /* Failure to add, try wildcard expansion of $1 as a PMU name. */
304 if (asprintf(&pattern, "%s*", $1) < 0) {
305 CLEANUP;
306 YYNOMEM;
307 }
308
309 while ((pmu = perf_pmus__scan(pmu)) != NULL) {
310 const char *name = pmu->name;
311
312 if (parse_events__filter_pmu(parse_state, pmu))
313 continue;
314
315 if (!strncmp(name, "uncore_", 7) &&
316 strncmp($1, "uncore_", 7))
317 name += 7;
318 if (!perf_pmu__match(pattern, name, $1) ||
319 !perf_pmu__match(pattern, pmu->alias_name, $1)) {
320 bool auto_merge_stats = perf_pmu__auto_merge_stats(pmu);
321
322 if (parse_events_copy_term_list(orig_terms, &terms)) {
323 CLEANUP;
324 YYNOMEM;
325 }
326 if (!parse_events_add_pmu(parse_state, list, pmu->name, terms,
327 auto_merge_stats, &@1)) {
328 ok++;
329 parse_state->wild_card_pmus = true;
330 }
331 parse_events_terms__delete(terms);
332 }
333 }
334
335 if (!ok) {
336 /* Failure to add, assume $1 is an event name. */
337 zfree(&list);
338 ok = !parse_events_multi_pmu_add(parse_state, $1, $2, &list, &@1);
339 $2 = NULL;
340 }
341 if (!ok) {
342 struct parse_events_error *error = parse_state->error;
343 char *help;
344
345 if (asprintf(&help, "Unable to find PMU or event on a PMU of '%s'", $1) < 0)
346 help = NULL;
347 parse_events_error__handle(error, @1.first_column,
348 strdup("Bad event or PMU"),
349 help);
350 CLEANUP;
351 YYABORT;
352 }
353 }
354 $$ = list;
355 list = NULL;
356 CLEANUP;
357 #undef CLEANUP
358 }
359 |
360 PE_NAME sep_dc
361 {
362 struct list_head *list;
363 int err;
364
365 err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1);
366 if (err < 0) {
367 struct parse_events_state *parse_state = _parse_state;
368 struct parse_events_error *error = parse_state->error;
369 char *help;
370
371 if (asprintf(&help, "Unable to find event on a PMU of '%s'", $1) < 0)
372 help = NULL;
373 parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help);
374 free($1);
375 PE_ABORT(err);
376 }
377 free($1);
378 $$ = list;
379 }
380
381 value_sym:
382 PE_VALUE_SYM_HW
383 |
384 PE_VALUE_SYM_SW
385
386 event_legacy_symbol:
387 value_sym '/' event_config '/'
388 {
389 struct list_head *list;
390 int type = $1 >> 16;
391 int config = $1 & 255;
392 int err;
393 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
394
395 list = alloc_list();
396 if (!list)
397 YYNOMEM;
398 err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);
399 parse_events_terms__delete($3);
400 if (err) {
401 free_list_evsel(list);
402 PE_ABORT(err);
403 }
404 $$ = list;
405 }
406 |
407 value_sym sep_slash_slash_dc
408 {
409 struct list_head *list;
410 int type = $1 >> 16;
411 int config = $1 & 255;
412 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
413 int err;
414
415 list = alloc_list();
416 if (!list)
417 YYNOMEM;
418 err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);
419 if (err)
420 PE_ABORT(err);
421 $$ = list;
422 }
423 |
424 PE_VALUE_SYM_TOOL sep_slash_slash_dc
425 {
426 struct list_head *list;
427 int err;
428
429 list = alloc_list();
430 if (!list)
431 YYNOMEM;
432 err = parse_events_add_tool(_parse_state, list, $1);
433 if (err)
434 YYNOMEM;
435 $$ = list;
436 }
437
438 event_legacy_cache:
439 PE_LEGACY_CACHE opt_event_config
440 {
441 struct parse_events_state *parse_state = _parse_state;
442 struct list_head *list;
443 int err;
444
445 list = alloc_list();
446 if (!list)
447 YYNOMEM;
448
449 err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2);
450
451 parse_events_terms__delete($2);
452 free($1);
453 if (err) {
454 free_list_evsel(list);
455 PE_ABORT(err);
456 }
457 $$ = list;
458 }
459
460 event_legacy_mem:
461 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
462 {
463 struct list_head *list;
464 int err;
465
466 list = alloc_list();
467 if (!list)
468 YYNOMEM;
469
470 err = parse_events_add_breakpoint(_parse_state, list,
471 $2, $6, $4, $7);
472 parse_events_terms__delete($7);
473 free($6);
474 if (err) {
475 free(list);
476 PE_ABORT(err);
477 }
478 $$ = list;
479 }
480 |
481 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config
482 {
483 struct list_head *list;
484 int err;
485
486 list = alloc_list();
487 if (!list)
488 YYNOMEM;
489
490 err = parse_events_add_breakpoint(_parse_state, list,
491 $2, NULL, $4, $5);
492 parse_events_terms__delete($5);
493 if (err) {
494 free(list);
495 PE_ABORT(err);
496 }
497 $$ = list;
498 }
499 |
500 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
501 {
502 struct list_head *list;
503 int err;
504
505 list = alloc_list();
506 if (!list)
507 YYNOMEM;
508
509 err = parse_events_add_breakpoint(_parse_state, list,
510 $2, $4, 0, $5);
511 parse_events_terms__delete($5);
512 free($4);
513 if (err) {
514 free(list);
515 PE_ABORT(err);
516 }
517 $$ = list;
518 }
519 |
520 PE_PREFIX_MEM PE_VALUE opt_event_config
521 {
522 struct list_head *list;
523 int err;
524
525 list = alloc_list();
526 if (!list)
527 YYNOMEM;
528 err = parse_events_add_breakpoint(_parse_state, list,
529 $2, NULL, 0, $3);
530 parse_events_terms__delete($3);
531 if (err) {
532 free(list);
533 PE_ABORT(err);
534 }
535 $$ = list;
536 }
537
538 event_legacy_tracepoint:
539 tracepoint_name opt_event_config
540 {
541 struct parse_events_state *parse_state = _parse_state;
542 struct parse_events_error *error = parse_state->error;
543 struct list_head *list;
544 int err;
545
546 list = alloc_list();
547 if (!list)
548 YYNOMEM;
549 if (error)
550 error->idx = @1.first_column;
551
552 err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event,
553 error, $2, &@1);
554
555 parse_events_terms__delete($2);
556 free($1.sys);
557 free($1.event);
558 if (err) {
559 free(list);
560 PE_ABORT(err);
561 }
562 $$ = list;
563 }
564
565 tracepoint_name:
566 PE_NAME ':' PE_NAME
567 {
568 struct tracepoint_name tracepoint = {$1, $3};
569
570 $$ = tracepoint;
571 }
572
573 event_legacy_numeric:
574 PE_VALUE ':' PE_VALUE opt_event_config
575 {
576 struct list_head *list;
577 int err;
578
579 list = alloc_list();
580 if (!list)
581 YYNOMEM;
582 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,
583 /*wildcard=*/false);
584 parse_events_terms__delete($4);
585 if (err) {
586 free(list);
587 PE_ABORT(err);
588 }
589 $$ = list;
590 }
591
592 event_legacy_raw:
593 PE_RAW opt_event_config
594 {
595 struct list_head *list;
596 int err;
597 u64 num;
598
599 list = alloc_list();
600 if (!list)
601 YYNOMEM;
602 errno = 0;
603 num = strtoull($1 + 1, NULL, 16);
604 /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */
605 if (errno)
606 YYABORT;
607 free($1);
608 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,
609 /*wildcard=*/false);
610 parse_events_terms__delete($2);
611 if (err) {
612 free(list);
613 PE_ABORT(err);
614 }
615 $$ = list;
616 }
617
618 opt_event_config:
619 '/' event_config '/'
620 {
621 $$ = $2;
622 }
623 |
624 '/' '/'
625 {
626 $$ = NULL;
627 }
628 |
629 {
630 $$ = NULL;
631 }
632
633 opt_pmu_config:
634 '/' event_config '/'
635 {
636 $$ = $2;
637 }
638 |
639 '/' '/'
640 {
641 $$ = NULL;
642 }
643
644 start_terms: event_config
645 {
646 struct parse_events_state *parse_state = _parse_state;
647 if (parse_state->terms) {
648 parse_events_terms__delete ($1);
649 YYABORT;
650 }
651 parse_state->terms = $1;
652 }
653
654 event_config:
655 event_config ',' event_term
656 {
657 struct list_head *head = $1;
658 struct parse_events_term *term = $3;
659
660 if (!head) {
661 parse_events_term__delete(term);
662 YYABORT;
663 }
664 list_add_tail(&term->list, head);
665 $$ = $1;
666 }
667 |
668 event_term
669 {
670 struct list_head *head = malloc(sizeof(*head));
671 struct parse_events_term *term = $1;
672
673 if (!head)
674 YYNOMEM;
675 INIT_LIST_HEAD(head);
676 list_add_tail(&term->list, head);
677 $$ = head;
678 }
679
680 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE
681
682 name_or_legacy: PE_NAME | PE_LEGACY_CACHE
683
684 event_term:
685 PE_RAW
686 {
687 struct parse_events_term *term;
688 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,
689 strdup("raw"), $1, &@1, &@1);
690
691 if (err) {
692 free($1);
693 PE_ABORT(err);
694 }
695 $$ = term;
696 }
697 |
698 name_or_raw '=' name_or_legacy
699 {
700 struct parse_events_term *term;
701 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);
702
703 if (err) {
704 free($1);
705 free($3);
706 PE_ABORT(err);
707 }
708 $$ = term;
709 }
710 |
711 name_or_raw '=' PE_VALUE
712 {
713 struct parse_events_term *term;
714 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
715 $1, $3, /*novalue=*/false, &@1, &@3);
716
717 if (err) {
718 free($1);
719 PE_ABORT(err);
720 }
721 $$ = term;
722 }
723 |
724 name_or_raw '=' PE_TERM_HW
725 {
726 struct parse_events_term *term;
727 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
728 $1, $3.str, &@1, &@3);
729
730 if (err) {
731 free($1);
732 free($3.str);
733 PE_ABORT(err);
734 }
735 $$ = term;
736 }
737 |
738 PE_LEGACY_CACHE
739 {
740 struct parse_events_term *term;
741 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
742 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
743
744 if (err) {
745 free($1);
746 PE_ABORT(err);
747 }
748 $$ = term;
749 }
750 |
751 PE_NAME
752 {
753 struct parse_events_term *term;
754 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
755 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
756
757 if (err) {
758 free($1);
759 PE_ABORT(err);
760 }
761 $$ = term;
762 }
763 |
764 PE_TERM_HW
765 {
766 struct parse_events_term *term;
767 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE,
768 $1.str, $1.num & 255, /*novalue=*/false,
769 &@1, /*loc_val=*/NULL);
770
771 if (err) {
772 free($1.str);
773 PE_ABORT(err);
774 }
775 $$ = term;
776 }
777 |
778 PE_TERM '=' name_or_legacy
779 {
780 struct parse_events_term *term;
781 int err = parse_events_term__str(&term, (enum parse_events__term_type)$1,
782 /*config=*/NULL, $3, &@1, &@3);
783
784 if (err) {
785 free($3);
786 PE_ABORT(err);
787 }
788 $$ = term;
789 }
790 |
791 PE_TERM '=' PE_TERM_HW
792 {
793 struct parse_events_term *term;
794 int err = parse_events_term__str(&term, (enum parse_events__term_type)$1,
795 /*config=*/NULL, $3.str, &@1, &@3);
796
797 if (err) {
798 free($3.str);
799 PE_ABORT(err);
800 }
801 $$ = term;
802 }
803 |
804 PE_TERM '=' PE_TERM
805 {
806 struct parse_events_term *term;
807 int err = parse_events_term__term(&term,
808 (enum parse_events__term_type)$1,
809 (enum parse_events__term_type)$3,
810 &@1, &@3);
811
812 if (err)
813 PE_ABORT(err);
814
815 $$ = term;
816 }
817 |
818 PE_TERM '=' PE_VALUE
819 {
820 struct parse_events_term *term;
821 int err = parse_events_term__num(&term, (enum parse_events__term_type)$1,
822 /*config=*/NULL, $3, /*novalue=*/false, &@1, &@3);
823
824 if (err)
825 PE_ABORT(err);
826
827 $$ = term;
828 }
829 |
830 PE_TERM
831 {
832 struct parse_events_term *term;
833 int err = parse_events_term__num(&term, (enum parse_events__term_type)$1,
834 /*config=*/NULL, /*num=*/1, /*novalue=*/true,
835 &@1, /*loc_val=*/NULL);
836
837 if (err)
838 PE_ABORT(err);
839
840 $$ = term;
841 }
842 |
843 PE_DRV_CFG_TERM
844 {
845 struct parse_events_term *term;
846 char *config = strdup($1);
847 int err;
848
849 if (!config)
850 YYNOMEM;
851 err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL);
852 if (err) {
853 free($1);
854 free(config);
855 PE_ABORT(err);
856 }
857 $$ = term;
858 }
859
860 sep_dc: ':' |
861
862 sep_slash_slash_dc: '/' '/' | ':' |
863
864 %%
865
866 void parse_events_error(YYLTYPE *loc, void *parse_state,
867 void *scanner __maybe_unused,
868 char const *msg __maybe_unused)
869 {
870 parse_events_evlist_error(parse_state, loc->last_column, "parser error");
871 }
872