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