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