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 #ifndef NDEBUG
10 #define YYDEBUG 1
11 #endif
12
13 #include <errno.h>
14 #include <linux/compiler.h>
15 #include <linux/types.h>
16 #include "pmu.h"
17 #include "pmus.h"
18 #include "evsel.h"
19 #include "parse-events.h"
20 #include "parse-events-bison.h"
21
22 int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner);
23 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
24
25 #define PE_ABORT(val) \
26 do { \
27 if (val == -ENOMEM) \
28 YYNOMEM; \
29 YYABORT; \
30 } while (0)
31
alloc_list(void)32 static struct list_head* alloc_list(void)
33 {
34 struct list_head *list;
35
36 list = malloc(sizeof(*list));
37 if (!list)
38 return NULL;
39
40 INIT_LIST_HEAD(list);
41 return list;
42 }
43
free_list_evsel(struct list_head * list_evsel)44 static void free_list_evsel(struct list_head* list_evsel)
45 {
46 struct evsel *evsel, *tmp;
47
48 list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
49 list_del_init(&evsel->core.node);
50 evsel__delete(evsel);
51 }
52 free(list_evsel);
53 }
54
55 %}
56
57 %token PE_START_EVENTS PE_START_TERMS
58 %token PE_VALUE PE_VALUE_SYM_HW PE_TERM
59 %token PE_EVENT_NAME
60 %token PE_RAW PE_NAME
61 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
62 %token PE_LEGACY_CACHE
63 %token PE_PREFIX_MEM
64 %token PE_ERROR
65 %token PE_DRV_CFG_TERM
66 %token PE_TERM_HW
67 %type <num> PE_VALUE
68 %type <num> PE_VALUE_SYM_HW
69 %type <mod> PE_MODIFIER_EVENT
70 %type <term_type> PE_TERM
71 %type <str> PE_RAW
72 %type <str> PE_NAME
73 %type <str> PE_LEGACY_CACHE
74 %type <str> PE_MODIFIER_BP
75 %type <str> PE_EVENT_NAME
76 %type <str> PE_DRV_CFG_TERM
77 %type <str> name_or_raw
78 %destructor { free ($$); } <str>
79 %type <term> event_term
80 %destructor { parse_events_term__delete ($$); } <term>
81 %type <list_terms> event_config
82 %type <list_terms> opt_event_config
83 %type <list_terms> opt_pmu_config
84 %destructor { parse_events_terms__delete ($$); } <list_terms>
85 %type <list_evsel> event_pmu
86 %type <list_evsel> event_legacy_symbol
87 %type <list_evsel> event_legacy_cache
88 %type <list_evsel> event_legacy_mem
89 %type <list_evsel> event_legacy_tracepoint
90 %type <list_evsel> event_legacy_numeric
91 %type <list_evsel> event_legacy_raw
92 %type <list_evsel> event_def
93 %type <list_evsel> event_mod
94 %type <list_evsel> event_name
95 %type <list_evsel> event
96 %type <list_evsel> events
97 %type <list_evsel> group_def
98 %type <list_evsel> group
99 %type <list_evsel> groups
100 %destructor { free_list_evsel ($$); } <list_evsel>
101 %type <tracepoint_name> tracepoint_name
102 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
103 %type <hardware_term> PE_TERM_HW
104 %destructor { free ($$.str); } <hardware_term>
105
106 %union
107 {
108 char *str;
109 u64 num;
110 struct parse_events_modifier mod;
111 enum parse_events__term_type term_type;
112 struct list_head *list_evsel;
113 struct parse_events_terms *list_terms;
114 struct parse_events_term *term;
115 struct tracepoint_name {
116 char *sys;
117 char *event;
118 } tracepoint_name;
119 struct hardware_term {
120 char *str;
121 u64 num;
122 } hardware_term;
123 }
124 %%
125
126 /*
127 * Entry points. We are either parsing events or terminals. Just terminal
128 * parsing is used for parsing events in sysfs.
129 */
130 start:
131 PE_START_EVENTS start_events
132 |
133 PE_START_TERMS start_terms
134
135 start_events: groups
136 {
137 /* Take the parsed events, groups.. and place into parse_state. */
138 struct list_head *groups = $1;
139 struct parse_events_state *parse_state = _parse_state;
140
141 list_splice_tail(groups, &parse_state->list);
142 free(groups);
143 }
144
145 groups: /* A list of groups or events. */
146 groups ',' group
147 {
148 /* Merge group into the list of events/groups. */
149 struct list_head *groups = $1;
150 struct list_head *group = $3;
151
152 list_splice_tail(group, groups);
153 free(group);
154 $$ = groups;
155 }
156 |
157 groups ',' event
158 {
159 /* Merge event into the list of events/groups. */
160 struct list_head *groups = $1;
161 struct list_head *event = $3;
162
163
164 list_splice_tail(event, groups);
165 free(event);
166 $$ = groups;
167 }
168 |
169 group
170 |
171 event
172
173 group:
174 group_def ':' PE_MODIFIER_EVENT
175 {
176 /* Apply the modifier to the events in the group_def. */
177 struct list_head *list = $1;
178 int err;
179
180 err = parse_events__modifier_group(_parse_state, &@3, list, $3);
181 if (err)
182 YYABORT;
183 $$ = list;
184 }
185 |
186 group_def
187
188 group_def:
189 PE_NAME '{' events '}'
190 {
191 struct list_head *list = $3;
192
193 /*
194 * Set the first entry of list to be the leader. Set the group name on
195 * the leader to $1 taking ownership.
196 */
197 parse_events__set_leader($1, list);
198 $$ = list;
199 }
200 |
201 '{' events '}'
202 {
203 struct list_head *list = $2;
204
205 /* Set the first entry of list to be the leader clearing the group name. */
206 parse_events__set_leader(NULL, list);
207 $$ = list;
208 }
209
210 events:
211 events ',' event
212 {
213 struct list_head *events = $1;
214 struct list_head *event = $3;
215
216 list_splice_tail(event, events);
217 free(event);
218 $$ = events;
219 }
220 |
221 event
222
223 event: event_mod
224
225 event_mod:
226 event_name PE_MODIFIER_EVENT
227 {
228 struct list_head *list = $1;
229 int err;
230
231 /*
232 * Apply modifier on all events added by single event definition
233 * (there could be more events added for multiple tracepoint
234 * definitions via '*?'.
235 */
236 err = parse_events__modifier_event(_parse_state, &@2, list, $2);
237 if (err)
238 YYABORT;
239 $$ = list;
240 }
241 |
242 event_name
243
244 event_name:
245 PE_EVENT_NAME event_def
246 {
247 /*
248 * When an event is parsed the text is rewound and the entire text of
249 * the event is set to the str of PE_EVENT_NAME token matched here. If
250 * no name was on an event via a term, set the name to the entire text
251 * taking ownership of the allocation.
252 */
253 int err = parse_events__set_default_name($2, $1);
254
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 /* List of created evsels. */
276 struct list_head *list = NULL;
277 int err = parse_events_multi_pmu_add_or_add_pmu(_parse_state, $1, $2, &list, &@1);
278
279 parse_events_terms__delete($2);
280 free($1);
281 if (err)
282 PE_ABORT(err);
283 $$ = list;
284 }
285 |
286 PE_NAME sep_dc
287 {
288 struct list_head *list;
289 int err;
290
291 err = parse_events_multi_pmu_add(_parse_state, $1, PERF_COUNT_HW_MAX, NULL, &list, &@1);
292 if (err < 0) {
293 struct parse_events_state *parse_state = _parse_state;
294 struct parse_events_error *error = parse_state->error;
295 char *help;
296
297 if (asprintf(&help, "Unable to find event on a PMU of '%s'", $1) < 0)
298 help = NULL;
299 parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help);
300 free($1);
301 PE_ABORT(err);
302 }
303 free($1);
304 $$ = list;
305 }
306
307 event_legacy_symbol:
308 PE_VALUE_SYM_HW '/' event_config '/'
309 {
310 struct list_head *list;
311 int err;
312
313 list = alloc_list();
314 if (!list)
315 YYNOMEM;
316 err = parse_events_add_numeric(_parse_state, list,
317 PERF_TYPE_HARDWARE, $1,
318 $3,
319 /*wildcard=*/true);
320 parse_events_terms__delete($3);
321 if (err) {
322 free_list_evsel(list);
323 PE_ABORT(err);
324 }
325 $$ = list;
326 }
327 |
328 PE_VALUE_SYM_HW sep_slash_slash_dc
329 {
330 struct list_head *list;
331 int err;
332
333 list = alloc_list();
334 if (!list)
335 YYNOMEM;
336 err = parse_events_add_numeric(_parse_state, list,
337 PERF_TYPE_HARDWARE, $1,
338 /*head_config=*/NULL,
339 /*wildcard=*/true);
340 if (err)
341 PE_ABORT(err);
342 $$ = list;
343 }
344
345 event_legacy_cache:
346 PE_LEGACY_CACHE opt_event_config
347 {
348 struct parse_events_state *parse_state = _parse_state;
349 struct list_head *list;
350 int err;
351
352 list = alloc_list();
353 if (!list)
354 YYNOMEM;
355
356 err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2);
357
358 parse_events_terms__delete($2);
359 free($1);
360 if (err) {
361 free_list_evsel(list);
362 PE_ABORT(err);
363 }
364 $$ = list;
365 }
366
367 event_legacy_mem:
368 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
369 {
370 struct list_head *list;
371 int err;
372
373 list = alloc_list();
374 if (!list)
375 YYNOMEM;
376
377 err = parse_events_add_breakpoint(_parse_state, list,
378 $2, $6, $4, $7);
379 parse_events_terms__delete($7);
380 free($6);
381 if (err) {
382 free(list);
383 PE_ABORT(err);
384 }
385 $$ = list;
386 }
387 |
388 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config
389 {
390 struct list_head *list;
391 int err;
392
393 list = alloc_list();
394 if (!list)
395 YYNOMEM;
396
397 err = parse_events_add_breakpoint(_parse_state, list,
398 $2, NULL, $4, $5);
399 parse_events_terms__delete($5);
400 if (err) {
401 free(list);
402 PE_ABORT(err);
403 }
404 $$ = list;
405 }
406 |
407 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
408 {
409 struct list_head *list;
410 int err;
411
412 list = alloc_list();
413 if (!list)
414 YYNOMEM;
415
416 err = parse_events_add_breakpoint(_parse_state, list,
417 $2, $4, 0, $5);
418 parse_events_terms__delete($5);
419 free($4);
420 if (err) {
421 free(list);
422 PE_ABORT(err);
423 }
424 $$ = list;
425 }
426 |
427 PE_PREFIX_MEM PE_VALUE opt_event_config
428 {
429 struct list_head *list;
430 int err;
431
432 list = alloc_list();
433 if (!list)
434 YYNOMEM;
435 err = parse_events_add_breakpoint(_parse_state, list,
436 $2, NULL, 0, $3);
437 parse_events_terms__delete($3);
438 if (err) {
439 free(list);
440 PE_ABORT(err);
441 }
442 $$ = list;
443 }
444
445 event_legacy_tracepoint:
446 tracepoint_name opt_event_config
447 {
448 struct parse_events_state *parse_state = _parse_state;
449 struct parse_events_error *error = parse_state->error;
450 struct list_head *list;
451 int err;
452
453 list = alloc_list();
454 if (!list)
455 YYNOMEM;
456
457 err = parse_events_add_tracepoint(parse_state, list, $1.sys, $1.event,
458 error, $2, &@1);
459
460 parse_events_terms__delete($2);
461 free($1.sys);
462 free($1.event);
463 if (err) {
464 free(list);
465 PE_ABORT(err);
466 }
467 $$ = list;
468 }
469
470 tracepoint_name:
471 PE_NAME ':' PE_NAME
472 {
473 struct tracepoint_name tracepoint = {$1, $3};
474
475 $$ = tracepoint;
476 }
477
478 event_legacy_numeric:
479 PE_VALUE ':' PE_VALUE opt_event_config
480 {
481 struct list_head *list;
482 int err;
483
484 list = alloc_list();
485 if (!list)
486 YYNOMEM;
487 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,
488 /*wildcard=*/false);
489 parse_events_terms__delete($4);
490 if (err) {
491 free(list);
492 PE_ABORT(err);
493 }
494 $$ = list;
495 }
496
497 event_legacy_raw:
498 PE_RAW opt_event_config
499 {
500 struct list_head *list;
501 int err;
502 u64 num;
503
504 list = alloc_list();
505 if (!list)
506 YYNOMEM;
507 errno = 0;
508 num = strtoull($1 + 1, NULL, 16);
509 /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */
510 if (errno)
511 YYABORT;
512 free($1);
513 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,
514 /*wildcard=*/false);
515 parse_events_terms__delete($2);
516 if (err) {
517 free(list);
518 PE_ABORT(err);
519 }
520 $$ = list;
521 }
522
523 opt_event_config:
524 '/' event_config '/'
525 {
526 $$ = $2;
527 }
528 |
529 '/' '/'
530 {
531 $$ = NULL;
532 }
533 |
534 {
535 $$ = NULL;
536 }
537
538 opt_pmu_config:
539 '/' event_config '/'
540 {
541 $$ = $2;
542 }
543 |
544 '/' '/'
545 {
546 $$ = NULL;
547 }
548
549 start_terms: event_config
550 {
551 struct parse_events_state *parse_state = _parse_state;
552 if (parse_state->terms) {
553 parse_events_terms__delete ($1);
554 YYABORT;
555 }
556 parse_state->terms = $1;
557 }
558
559 event_config:
560 event_config ',' event_term
561 {
562 struct parse_events_terms *head = $1;
563 struct parse_events_term *term = $3;
564
565 if (!head) {
566 parse_events_term__delete(term);
567 YYABORT;
568 }
569 list_add_tail(&term->list, &head->terms);
570 $$ = $1;
571 }
572 |
573 event_term
574 {
575 struct parse_events_terms *head = malloc(sizeof(*head));
576 struct parse_events_term *term = $1;
577
578 if (!head)
579 YYNOMEM;
580 parse_events_terms__init(head);
581 list_add_tail(&term->list, &head->terms);
582 $$ = head;
583 }
584
585 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE
586 |
587 PE_TERM_HW
588 {
589 $$ = $1.str;
590 }
591
592 event_term:
593 PE_RAW
594 {
595 struct parse_events_term *term;
596 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,
597 strdup("raw"), $1, &@1, &@1);
598
599 if (err) {
600 free($1);
601 PE_ABORT(err);
602 }
603 $$ = term;
604 }
605 |
606 name_or_raw '=' name_or_raw
607 {
608 struct parse_events_term *term;
609 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);
610
611 if (err) {
612 free($1);
613 free($3);
614 PE_ABORT(err);
615 }
616 $$ = term;
617 }
618 |
619 name_or_raw '=' PE_VALUE
620 {
621 struct parse_events_term *term;
622 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
623 $1, $3, /*novalue=*/false, &@1, &@3);
624
625 if (err) {
626 free($1);
627 PE_ABORT(err);
628 }
629 $$ = term;
630 }
631 |
632 PE_LEGACY_CACHE
633 {
634 struct parse_events_term *term;
635 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
636 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
637
638 if (err) {
639 free($1);
640 PE_ABORT(err);
641 }
642 $$ = term;
643 }
644 |
645 PE_NAME
646 {
647 struct parse_events_term *term;
648 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
649 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
650
651 if (err) {
652 free($1);
653 PE_ABORT(err);
654 }
655 $$ = term;
656 }
657 |
658 PE_TERM_HW
659 {
660 struct parse_events_term *term;
661 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE,
662 $1.str, $1.num & 255, /*novalue=*/false,
663 &@1, /*loc_val=*/NULL);
664
665 if (err) {
666 free($1.str);
667 PE_ABORT(err);
668 }
669 $$ = term;
670 }
671 |
672 PE_TERM '=' name_or_raw
673 {
674 struct parse_events_term *term;
675 int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3);
676
677 if (err) {
678 free($3);
679 PE_ABORT(err);
680 }
681 $$ = term;
682 }
683 |
684 PE_TERM '=' PE_TERM
685 {
686 struct parse_events_term *term;
687 int err = parse_events_term__term(&term, $1, $3, &@1, &@3);
688
689 if (err)
690 PE_ABORT(err);
691
692 $$ = term;
693 }
694 |
695 PE_TERM '=' PE_VALUE
696 {
697 struct parse_events_term *term;
698 int err = parse_events_term__num(&term, $1,
699 /*config=*/NULL, $3, /*novalue=*/false,
700 &@1, &@3);
701
702 if (err)
703 PE_ABORT(err);
704
705 $$ = term;
706 }
707 |
708 PE_TERM
709 {
710 struct parse_events_term *term;
711 int err = parse_events_term__num(&term, $1,
712 /*config=*/NULL, /*num=*/1, /*novalue=*/true,
713 &@1, /*loc_val=*/NULL);
714
715 if (err)
716 PE_ABORT(err);
717
718 $$ = term;
719 }
720 |
721 PE_DRV_CFG_TERM
722 {
723 struct parse_events_term *term;
724 char *config = strdup($1);
725 int err;
726
727 if (!config)
728 YYNOMEM;
729 err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL);
730 if (err) {
731 free($1);
732 free(config);
733 PE_ABORT(err);
734 }
735 $$ = term;
736 }
737
738 sep_dc: ':' |
739
740 sep_slash_slash_dc: '/' '/' | ':' |
741
742 %%
743
744 void parse_events_error(YYLTYPE *loc, void *_parse_state,
745 void *scanner __maybe_unused,
746 char const *msg __maybe_unused)
747 {
748 struct parse_events_state *parse_state = _parse_state;
749
750 if (!parse_state->error || !list_empty(&parse_state->error->list))
751 return;
752
753 parse_events_error__handle(parse_state->error, loc->last_column,
754 strdup("Unrecognized input"), NULL);
755 }
756