xref: /linux/tools/perf/util/parse-events.y (revision c31f4aa8fed048fa70e742c4bb49bb48dc489ab3)
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_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_PREFIX_MEM
63 %token PE_ERROR
64 %token PE_DRV_CFG_TERM
65 %type <num> PE_VALUE
66 %type <mod> PE_MODIFIER_EVENT
67 %type <term_type> PE_TERM
68 %type <str> PE_RAW
69 %type <str> PE_NAME
70 %type <str> PE_MODIFIER_BP
71 %type <str> PE_EVENT_NAME
72 %type <str> PE_DRV_CFG_TERM
73 %type <str> name_or_raw
74 %destructor { free ($$); } <str>
75 %type <term> event_term
76 %destructor { parse_events_term__delete ($$); } <term>
77 %type <list_terms> event_config
78 %type <list_terms> opt_event_config
79 %type <list_terms> opt_pmu_config
80 %destructor { parse_events_terms__delete ($$); } <list_terms>
81 %type <list_evsel> event_pmu
82 %type <list_evsel> event_legacy_mem
83 %type <list_evsel> event_legacy_tracepoint
84 %type <list_evsel> event_legacy_numeric
85 %type <list_evsel> event_legacy_raw
86 %type <list_evsel> event_def
87 %type <list_evsel> event_mod
88 %type <list_evsel> event_name
89 %type <list_evsel> event
90 %type <list_evsel> events
91 %type <list_evsel> group_def
92 %type <list_evsel> group
93 %type <list_evsel> groups
94 %destructor { free_list_evsel ($$); } <list_evsel>
95 %type <tracepoint_name> tracepoint_name
96 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
97 
98 %union
99 {
100 	char *str;
101 	u64 num;
102 	struct parse_events_modifier mod;
103 	enum parse_events__term_type term_type;
104 	struct list_head *list_evsel;
105 	struct parse_events_terms *list_terms;
106 	struct parse_events_term *term;
107 	struct tracepoint_name {
108 		char *sys;
109 		char *event;
110 	} tracepoint_name;
111 }
112 %%
113 
114  /*
115   * Entry points. We are either parsing events or terminals. Just terminal
116   * parsing is used for parsing events in sysfs.
117   */
118 start:
119 PE_START_EVENTS start_events
120 |
121 PE_START_TERMS  start_terms
122 
123 start_events: groups
124 {
125 	/* Take the parsed events, groups.. and place into parse_state. */
126 	struct list_head *groups  = $1;
127 	struct parse_events_state *parse_state = _parse_state;
128 
129 	list_splice_tail(groups, &parse_state->list);
130 	free(groups);
131 }
132 
133 groups: /* A list of groups or events. */
134 groups ',' group
135 {
136 	/* Merge group into the list of events/groups. */
137 	struct list_head *groups  = $1;
138 	struct list_head *group  = $3;
139 
140 	list_splice_tail(group, groups);
141 	free(group);
142 	$$ = groups;
143 }
144 |
145 groups ',' event
146 {
147 	/* Merge event into the list of events/groups. */
148 	struct list_head *groups  = $1;
149 	struct list_head *event = $3;
150 
151 
152 	list_splice_tail(event, groups);
153 	free(event);
154 	$$ = groups;
155 }
156 |
157 group
158 |
159 event
160 
161 group:
162 group_def ':' PE_MODIFIER_EVENT
163 {
164 	/* Apply the modifier to the events in the group_def. */
165 	struct list_head *list = $1;
166 	int err;
167 
168 	err = parse_events__modifier_group(_parse_state, &@3, list, $3);
169 	if (err)
170 		YYABORT;
171 	$$ = list;
172 }
173 |
174 group_def
175 
176 group_def:
177 PE_NAME '{' events '}'
178 {
179 	struct list_head *list = $3;
180 
181 	/*
182 	 * Set the first entry of list to be the leader. Set the group name on
183 	 * the leader to $1 taking ownership.
184 	 */
185 	parse_events__set_leader($1, list);
186 	$$ = list;
187 }
188 |
189 '{' events '}'
190 {
191 	struct list_head *list = $2;
192 
193 	/* Set the first entry of list to be the leader clearing the group name. */
194 	parse_events__set_leader(NULL, list);
195 	$$ = list;
196 }
197 
198 events:
199 events ',' event
200 {
201 	struct list_head *events  = $1;
202 	struct list_head *event = $3;
203 
204 	list_splice_tail(event, events);
205 	free(event);
206 	$$ = events;
207 }
208 |
209 event
210 
211 event: event_mod
212 
213 event_mod:
214 event_name PE_MODIFIER_EVENT
215 {
216 	struct list_head *list = $1;
217 	int err;
218 
219 	/*
220 	 * Apply modifier on all events added by single event definition
221 	 * (there could be more events added for multiple tracepoint
222 	 * definitions via '*?'.
223 	 */
224 	err = parse_events__modifier_event(_parse_state, &@2, list, $2);
225 	if (err)
226 		YYABORT;
227 	$$ = list;
228 }
229 |
230 event_name
231 
232 event_name:
233 PE_EVENT_NAME event_def
234 {
235 	/*
236 	 * When an event is parsed the text is rewound and the entire text of
237 	 * the event is set to the str of PE_EVENT_NAME token matched here. If
238 	 * no name was on an event via a term, set the name to the entire text
239 	 * taking ownership of the allocation.
240 	 */
241 	int err = parse_events__set_default_name($2, $1);
242 
243 	if (err) {
244 		free_list_evsel($2);
245 		YYNOMEM;
246 	}
247 	$$ = $2;
248 }
249 |
250 event_def
251 
252 event_def: event_pmu |
253 	   event_legacy_mem sep_dc |
254 	   event_legacy_tracepoint sep_dc |
255 	   event_legacy_numeric sep_dc |
256 	   event_legacy_raw sep_dc
257 
258 event_pmu:
259 PE_NAME opt_pmu_config
260 {
261 	/* List of created evsels. */
262 	struct list_head *list = NULL;
263 	int err = parse_events_multi_pmu_add_or_add_pmu(_parse_state, $1, $2, &list, &@1);
264 
265 	parse_events_terms__delete($2);
266 	free($1);
267 	if (err)
268 		PE_ABORT(err);
269 	$$ = list;
270 }
271 |
272 PE_NAME sep_dc
273 {
274 	struct list_head *list;
275 	int err;
276 
277 	err = parse_events_multi_pmu_add(_parse_state, $1, /*const_parsed_terms*/NULL, &list, &@1);
278 	if (err < 0) {
279 		struct parse_events_state *parse_state = _parse_state;
280 		struct parse_events_error *error = parse_state->error;
281 		char *help;
282 
283 		if (asprintf(&help, "Unable to find event on a PMU of '%s'", $1) < 0)
284 			help = NULL;
285 		parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help);
286 		free($1);
287 		PE_ABORT(err);
288 	}
289 	free($1);
290 	$$ = list;
291 }
292 
293 event_legacy_mem:
294 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
295 {
296 	struct list_head *list;
297 	int err;
298 
299 	list = alloc_list();
300 	if (!list)
301 		YYNOMEM;
302 
303 	err = parse_events_add_breakpoint(_parse_state, list,
304 					  $2, $6, $4, $7);
305 	parse_events_terms__delete($7);
306 	free($6);
307 	if (err) {
308 		free(list);
309 		PE_ABORT(err);
310 	}
311 	$$ = list;
312 }
313 |
314 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config
315 {
316 	struct list_head *list;
317 	int err;
318 
319 	list = alloc_list();
320 	if (!list)
321 		YYNOMEM;
322 
323 	err = parse_events_add_breakpoint(_parse_state, list,
324 					  $2, NULL, $4, $5);
325 	parse_events_terms__delete($5);
326 	if (err) {
327 		free(list);
328 		PE_ABORT(err);
329 	}
330 	$$ = list;
331 }
332 |
333 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
334 {
335 	struct list_head *list;
336 	int err;
337 
338 	list = alloc_list();
339 	if (!list)
340 		YYNOMEM;
341 
342 	err = parse_events_add_breakpoint(_parse_state, list,
343 					  $2, $4, 0, $5);
344 	parse_events_terms__delete($5);
345 	free($4);
346 	if (err) {
347 		free(list);
348 		PE_ABORT(err);
349 	}
350 	$$ = list;
351 }
352 |
353 PE_PREFIX_MEM PE_VALUE opt_event_config
354 {
355 	struct list_head *list;
356 	int err;
357 
358 	list = alloc_list();
359 	if (!list)
360 		YYNOMEM;
361 	err = parse_events_add_breakpoint(_parse_state, list,
362 					  $2, NULL, 0, $3);
363 	parse_events_terms__delete($3);
364 	if (err) {
365 		free(list);
366 		PE_ABORT(err);
367 	}
368 	$$ = list;
369 }
370 
371 event_legacy_tracepoint:
372 tracepoint_name opt_event_config
373 {
374 	struct parse_events_state *parse_state = _parse_state;
375 	struct parse_events_error *error = parse_state->error;
376 	struct list_head *list;
377 	int err;
378 
379 	list = alloc_list();
380 	if (!list)
381 		YYNOMEM;
382 
383 	err = parse_events_add_tracepoint(parse_state, list, $1.sys, $1.event,
384 					error, $2, &@1);
385 
386 	parse_events_terms__delete($2);
387 	free($1.sys);
388 	free($1.event);
389 	if (err) {
390 		free(list);
391 		PE_ABORT(err);
392 	}
393 	$$ = list;
394 }
395 
396 tracepoint_name:
397 PE_NAME ':' PE_NAME
398 {
399 	struct tracepoint_name tracepoint = {$1, $3};
400 
401 	$$ = tracepoint;
402 }
403 
404 event_legacy_numeric:
405 PE_VALUE ':' PE_VALUE opt_event_config
406 {
407 	struct list_head *list;
408 	int err;
409 
410 	list = alloc_list();
411 	if (!list)
412 		YYNOMEM;
413 	err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,
414 				       /*wildcard=*/false);
415 	parse_events_terms__delete($4);
416 	if (err) {
417 		free(list);
418 		PE_ABORT(err);
419 	}
420 	$$ = list;
421 }
422 
423 event_legacy_raw:
424 PE_RAW opt_event_config
425 {
426 	struct list_head *list;
427 	int err;
428 	u64 num;
429 
430 	list = alloc_list();
431 	if (!list)
432 		YYNOMEM;
433 	errno = 0;
434 	num = strtoull($1 + 1, NULL, 16);
435 	/* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */
436 	if (errno)
437 		YYABORT;
438 	free($1);
439 	err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,
440 				       /*wildcard=*/false);
441 	parse_events_terms__delete($2);
442 	if (err) {
443 		free(list);
444 		PE_ABORT(err);
445 	}
446 	$$ = list;
447 }
448 
449 opt_event_config:
450 '/' event_config '/'
451 {
452 	$$ = $2;
453 }
454 |
455 '/' '/'
456 {
457 	$$ = NULL;
458 }
459 |
460 {
461 	$$ = NULL;
462 }
463 
464 opt_pmu_config:
465 '/' event_config '/'
466 {
467 	$$ = $2;
468 }
469 |
470 '/' '/'
471 {
472 	$$ = NULL;
473 }
474 
475 start_terms: event_config
476 {
477 	struct parse_events_state *parse_state = _parse_state;
478 	if (parse_state->terms) {
479 		parse_events_terms__delete ($1);
480 		YYABORT;
481 	}
482 	parse_state->terms = $1;
483 }
484 
485 event_config:
486 event_config ',' event_term
487 {
488 	struct parse_events_terms *head = $1;
489 	struct parse_events_term *term = $3;
490 
491 	if (!head) {
492 		parse_events_term__delete(term);
493 		YYABORT;
494 	}
495 	list_add_tail(&term->list, &head->terms);
496 	$$ = $1;
497 }
498 |
499 event_term
500 {
501 	struct parse_events_terms *head = malloc(sizeof(*head));
502 	struct parse_events_term *term = $1;
503 
504 	if (!head)
505 		YYNOMEM;
506 	parse_events_terms__init(head);
507 	list_add_tail(&term->list, &head->terms);
508 	$$ = head;
509 }
510 
511 name_or_raw: PE_RAW | PE_NAME
512 
513 event_term:
514 PE_RAW
515 {
516 	struct parse_events_term *term;
517 	int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,
518 					 strdup("raw"), $1, &@1, &@1);
519 
520 	if (err) {
521 		free($1);
522 		PE_ABORT(err);
523 	}
524 	$$ = term;
525 }
526 |
527 name_or_raw '=' name_or_raw
528 {
529 	struct parse_events_term *term;
530 	int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);
531 
532 	if (err) {
533 		free($1);
534 		free($3);
535 		PE_ABORT(err);
536 	}
537 	$$ = term;
538 }
539 |
540 name_or_raw '=' PE_VALUE
541 {
542 	struct parse_events_term *term;
543 	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
544 					 $1, $3, /*novalue=*/false, &@1, &@3);
545 
546 	if (err) {
547 		free($1);
548 		PE_ABORT(err);
549 	}
550 	$$ = term;
551 }
552 |
553 PE_NAME
554 {
555 	struct parse_events_term *term;
556 	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
557 					 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
558 
559 	if (err) {
560 		free($1);
561 		PE_ABORT(err);
562 	}
563 	$$ = term;
564 }
565 |
566 PE_TERM '=' name_or_raw
567 {
568 	struct parse_events_term *term;
569 	int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3);
570 
571 	if (err) {
572 		free($3);
573 		PE_ABORT(err);
574 	}
575 	$$ = term;
576 }
577 |
578 PE_TERM '=' PE_TERM
579 {
580 	struct parse_events_term *term;
581 	int err = parse_events_term__term(&term, $1, $3, &@1, &@3);
582 
583 	if (err)
584 		PE_ABORT(err);
585 
586 	$$ = term;
587 }
588 |
589 PE_TERM '=' PE_VALUE
590 {
591 	struct parse_events_term *term;
592 	int err = parse_events_term__num(&term, $1,
593 					 /*config=*/NULL, $3, /*novalue=*/false,
594 					 &@1, &@3);
595 
596 	if (err)
597 		PE_ABORT(err);
598 
599 	$$ = term;
600 }
601 |
602 PE_TERM
603 {
604 	struct parse_events_term *term;
605 	int err = parse_events_term__num(&term, $1,
606 					 /*config=*/NULL, /*num=*/1, /*novalue=*/true,
607 					 &@1, /*loc_val=*/NULL);
608 
609 	if (err)
610 		PE_ABORT(err);
611 
612 	$$ = term;
613 }
614 |
615 PE_DRV_CFG_TERM
616 {
617 	struct parse_events_term *term;
618 	char *config = strdup($1);
619 	int err;
620 
621 	if (!config)
622 		YYNOMEM;
623 	err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL);
624 	if (err) {
625 		free($1);
626 		free(config);
627 		PE_ABORT(err);
628 	}
629 	$$ = term;
630 }
631 
632 sep_dc: ':' |
633 
634 %%
635 
636 void parse_events_error(YYLTYPE *loc, void *_parse_state,
637 			void *scanner __maybe_unused,
638 			char const *msg __maybe_unused)
639 {
640 	struct parse_events_state *parse_state = _parse_state;
641 
642 	if (!parse_state->error || !list_empty(&parse_state->error->list))
643 		return;
644 
645 	parse_events_error__handle(parse_state->error, loc->last_column,
646 				   strdup("Unrecognized input"), NULL);
647 }
648