]> Git Repo - J-linux.git/blob - tools/perf/util/parse-events.y
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / tools / perf / util / parse-events.y
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 }
This page took 0.067542 seconds and 4 git commands to generate.