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