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