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