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