xref: /linux/tools/perf/util/parse-events.y (revision afd876bbdc97664257523bb5f2dcedbb5cef40d0)
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 	int err;
251 
252 	err = parse_events_name($2, $1);
253 	free($1);
254 	if (err) {
255 		free_list_evsel($2);
256 		YYNOMEM;
257 	}
258 	$$ = $2;
259 }
260 |
261 event_def
262 
263 event_def: event_pmu |
264 	   event_legacy_hardware |
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_hardware:
308 PE_TERM_HW opt_pmu_config
309 {
310 	/* List of created evsels. */
311 	struct list_head *list = NULL;
312 	int err = parse_events_multi_pmu_add(_parse_state, $1.str, $1.num, $2, &list, &@1);
313 
314 	free($1.str);
315 	parse_events_terms__delete($2);
316 	if (err)
317 		PE_ABORT(err);
318 
319 	$$ = list;
320 }
321 |
322 PE_TERM_HW sep_dc
323 {
324 	struct list_head *list;
325 	int err;
326 
327 	err = parse_events_multi_pmu_add(_parse_state, $1.str, $1.num, NULL, &list, &@1);
328 	free($1.str);
329 	if (err)
330 		PE_ABORT(err);
331 	$$ = list;
332 }
333 
334 event_legacy_symbol:
335 PE_VALUE_SYM_SW '/' event_config '/'
336 {
337 	struct list_head *list;
338 	int err;
339 
340 	list = alloc_list();
341 	if (!list)
342 		YYNOMEM;
343 	err = parse_events_add_numeric(_parse_state, list,
344 				/*type=*/PERF_TYPE_SOFTWARE, /*config=*/$1,
345 				$3, /*wildcard=*/false);
346 	parse_events_terms__delete($3);
347 	if (err) {
348 		free_list_evsel(list);
349 		PE_ABORT(err);
350 	}
351 	$$ = list;
352 }
353 |
354 PE_VALUE_SYM_SW sep_slash_slash_dc
355 {
356 	struct list_head *list;
357 	int err;
358 
359 	list = alloc_list();
360 	if (!list)
361 		YYNOMEM;
362 	err = parse_events_add_numeric(_parse_state, list,
363 				/*type=*/PERF_TYPE_SOFTWARE, /*config=*/$1,
364 				/*head_config=*/NULL, /*wildcard=*/false);
365 	if (err)
366 		PE_ABORT(err);
367 	$$ = list;
368 }
369 |
370 PE_VALUE_SYM_TOOL sep_slash_slash_dc
371 {
372 	struct list_head *list;
373 	int err;
374 
375 	list = alloc_list();
376 	if (!list)
377 		YYNOMEM;
378 	err = parse_events_add_tool(_parse_state, list, $1);
379 	if (err)
380 		YYNOMEM;
381 	$$ = list;
382 }
383 
384 event_legacy_cache:
385 PE_LEGACY_CACHE opt_event_config
386 {
387 	struct parse_events_state *parse_state = _parse_state;
388 	struct list_head *list;
389 	int err;
390 
391 	list = alloc_list();
392 	if (!list)
393 		YYNOMEM;
394 
395 	err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2);
396 
397 	parse_events_terms__delete($2);
398 	free($1);
399 	if (err) {
400 		free_list_evsel(list);
401 		PE_ABORT(err);
402 	}
403 	$$ = list;
404 }
405 
406 event_legacy_mem:
407 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH 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, $6, $4, $7);
418 	parse_events_terms__delete($7);
419 	free($6);
420 	if (err) {
421 		free(list);
422 		PE_ABORT(err);
423 	}
424 	$$ = list;
425 }
426 |
427 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH 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 
436 	err = parse_events_add_breakpoint(_parse_state, list,
437 					  $2, NULL, $4, $5);
438 	parse_events_terms__delete($5);
439 	if (err) {
440 		free(list);
441 		PE_ABORT(err);
442 	}
443 	$$ = list;
444 }
445 |
446 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
447 {
448 	struct list_head *list;
449 	int err;
450 
451 	list = alloc_list();
452 	if (!list)
453 		YYNOMEM;
454 
455 	err = parse_events_add_breakpoint(_parse_state, list,
456 					  $2, $4, 0, $5);
457 	parse_events_terms__delete($5);
458 	free($4);
459 	if (err) {
460 		free(list);
461 		PE_ABORT(err);
462 	}
463 	$$ = list;
464 }
465 |
466 PE_PREFIX_MEM PE_VALUE opt_event_config
467 {
468 	struct list_head *list;
469 	int err;
470 
471 	list = alloc_list();
472 	if (!list)
473 		YYNOMEM;
474 	err = parse_events_add_breakpoint(_parse_state, list,
475 					  $2, NULL, 0, $3);
476 	parse_events_terms__delete($3);
477 	if (err) {
478 		free(list);
479 		PE_ABORT(err);
480 	}
481 	$$ = list;
482 }
483 
484 event_legacy_tracepoint:
485 tracepoint_name opt_event_config
486 {
487 	struct parse_events_state *parse_state = _parse_state;
488 	struct parse_events_error *error = parse_state->error;
489 	struct list_head *list;
490 	int err;
491 
492 	list = alloc_list();
493 	if (!list)
494 		YYNOMEM;
495 
496 	err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event,
497 					error, $2, &@1);
498 
499 	parse_events_terms__delete($2);
500 	free($1.sys);
501 	free($1.event);
502 	if (err) {
503 		free(list);
504 		PE_ABORT(err);
505 	}
506 	$$ = list;
507 }
508 
509 tracepoint_name:
510 PE_NAME ':' PE_NAME
511 {
512 	struct tracepoint_name tracepoint = {$1, $3};
513 
514 	$$ = tracepoint;
515 }
516 
517 event_legacy_numeric:
518 PE_VALUE ':' PE_VALUE opt_event_config
519 {
520 	struct list_head *list;
521 	int err;
522 
523 	list = alloc_list();
524 	if (!list)
525 		YYNOMEM;
526 	err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,
527 				       /*wildcard=*/false);
528 	parse_events_terms__delete($4);
529 	if (err) {
530 		free(list);
531 		PE_ABORT(err);
532 	}
533 	$$ = list;
534 }
535 
536 event_legacy_raw:
537 PE_RAW opt_event_config
538 {
539 	struct list_head *list;
540 	int err;
541 	u64 num;
542 
543 	list = alloc_list();
544 	if (!list)
545 		YYNOMEM;
546 	errno = 0;
547 	num = strtoull($1 + 1, NULL, 16);
548 	/* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */
549 	if (errno)
550 		YYABORT;
551 	free($1);
552 	err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,
553 				       /*wildcard=*/false);
554 	parse_events_terms__delete($2);
555 	if (err) {
556 		free(list);
557 		PE_ABORT(err);
558 	}
559 	$$ = list;
560 }
561 
562 opt_event_config:
563 '/' event_config '/'
564 {
565 	$$ = $2;
566 }
567 |
568 '/' '/'
569 {
570 	$$ = NULL;
571 }
572 |
573 {
574 	$$ = NULL;
575 }
576 
577 opt_pmu_config:
578 '/' event_config '/'
579 {
580 	$$ = $2;
581 }
582 |
583 '/' '/'
584 {
585 	$$ = NULL;
586 }
587 
588 start_terms: event_config
589 {
590 	struct parse_events_state *parse_state = _parse_state;
591 	if (parse_state->terms) {
592 		parse_events_terms__delete ($1);
593 		YYABORT;
594 	}
595 	parse_state->terms = $1;
596 }
597 
598 event_config:
599 event_config ',' event_term
600 {
601 	struct parse_events_terms *head = $1;
602 	struct parse_events_term *term = $3;
603 
604 	if (!head) {
605 		parse_events_term__delete(term);
606 		YYABORT;
607 	}
608 	list_add_tail(&term->list, &head->terms);
609 	$$ = $1;
610 }
611 |
612 event_term
613 {
614 	struct parse_events_terms *head = malloc(sizeof(*head));
615 	struct parse_events_term *term = $1;
616 
617 	if (!head)
618 		YYNOMEM;
619 	parse_events_terms__init(head);
620 	list_add_tail(&term->list, &head->terms);
621 	$$ = head;
622 }
623 
624 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE
625 |
626 PE_TERM_HW
627 {
628 	$$ = $1.str;
629 }
630 
631 event_term:
632 PE_RAW
633 {
634 	struct parse_events_term *term;
635 	int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,
636 					 strdup("raw"), $1, &@1, &@1);
637 
638 	if (err) {
639 		free($1);
640 		PE_ABORT(err);
641 	}
642 	$$ = term;
643 }
644 |
645 name_or_raw '=' name_or_raw
646 {
647 	struct parse_events_term *term;
648 	int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);
649 
650 	if (err) {
651 		free($1);
652 		free($3);
653 		PE_ABORT(err);
654 	}
655 	$$ = term;
656 }
657 |
658 name_or_raw '=' PE_VALUE
659 {
660 	struct parse_events_term *term;
661 	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
662 					 $1, $3, /*novalue=*/false, &@1, &@3);
663 
664 	if (err) {
665 		free($1);
666 		PE_ABORT(err);
667 	}
668 	$$ = term;
669 }
670 |
671 PE_LEGACY_CACHE
672 {
673 	struct parse_events_term *term;
674 	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
675 					 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
676 
677 	if (err) {
678 		free($1);
679 		PE_ABORT(err);
680 	}
681 	$$ = term;
682 }
683 |
684 PE_NAME
685 {
686 	struct parse_events_term *term;
687 	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
688 					 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
689 
690 	if (err) {
691 		free($1);
692 		PE_ABORT(err);
693 	}
694 	$$ = term;
695 }
696 |
697 PE_TERM_HW
698 {
699 	struct parse_events_term *term;
700 	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE,
701 					 $1.str, $1.num & 255, /*novalue=*/false,
702 					 &@1, /*loc_val=*/NULL);
703 
704 	if (err) {
705 		free($1.str);
706 		PE_ABORT(err);
707 	}
708 	$$ = term;
709 }
710 |
711 PE_TERM '=' name_or_raw
712 {
713 	struct parse_events_term *term;
714 	int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3);
715 
716 	if (err) {
717 		free($3);
718 		PE_ABORT(err);
719 	}
720 	$$ = term;
721 }
722 |
723 PE_TERM '=' PE_TERM
724 {
725 	struct parse_events_term *term;
726 	int err = parse_events_term__term(&term, $1, $3, &@1, &@3);
727 
728 	if (err)
729 		PE_ABORT(err);
730 
731 	$$ = term;
732 }
733 |
734 PE_TERM '=' PE_VALUE
735 {
736 	struct parse_events_term *term;
737 	int err = parse_events_term__num(&term, $1,
738 					 /*config=*/NULL, $3, /*novalue=*/false,
739 					 &@1, &@3);
740 
741 	if (err)
742 		PE_ABORT(err);
743 
744 	$$ = term;
745 }
746 |
747 PE_TERM
748 {
749 	struct parse_events_term *term;
750 	int err = parse_events_term__num(&term, $1,
751 					 /*config=*/NULL, /*num=*/1, /*novalue=*/true,
752 					 &@1, /*loc_val=*/NULL);
753 
754 	if (err)
755 		PE_ABORT(err);
756 
757 	$$ = term;
758 }
759 |
760 PE_DRV_CFG_TERM
761 {
762 	struct parse_events_term *term;
763 	char *config = strdup($1);
764 	int err;
765 
766 	if (!config)
767 		YYNOMEM;
768 	err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL);
769 	if (err) {
770 		free($1);
771 		free(config);
772 		PE_ABORT(err);
773 	}
774 	$$ = term;
775 }
776 
777 sep_dc: ':' |
778 
779 sep_slash_slash_dc: '/' '/' | ':' |
780 
781 %%
782 
783 void parse_events_error(YYLTYPE *loc, void *_parse_state,
784 			void *scanner __maybe_unused,
785 			char const *msg __maybe_unused)
786 {
787 	struct parse_events_state *parse_state = _parse_state;
788 
789 	if (!parse_state->error || !list_empty(&parse_state->error->list))
790 		return;
791 
792 	parse_events_error__handle(parse_state->error, loc->last_column,
793 				   strdup("Unrecognized input"), NULL);
794 }
795