2 %parse
-param
{void *_parse_state
}
3 %parse
-param
{void *scanner
}
4 %lex
-param
{void* scanner
}
13 #include <linux/compiler.h>
14 #include <linux/types.h>
15 #include <linux/zalloc.h>
18 #include "parse-events.h"
19 #include "parse-events-bison.h"
21 void parse_events_error
(YYLTYPE *loc
, void *parse_state
, void *scanner
, char const *msg
);
23 #define ABORT_ON(val) \
29 static struct list_head
* alloc_list
(void)
31 struct list_head
*list
;
33 list
= malloc
(sizeof
(*list
));
41 static void free_list_evsel
(struct list_head
* list_evsel
)
43 struct evsel
*evsel
, *tmp
;
45 list_for_each_entry_safe
(evsel
, tmp
, list_evsel
, core.node
) {
46 list_del_init
(&evsel
->core.node
);
52 static void inc_group_count
(struct list_head
*list
,
53 struct parse_events_state
*parse_state
)
55 /* Count groups only have more than 1 members */
56 if
(!list_is_last
(list
->next
, list
))
57 parse_state
->nr_groups
++;
62 %token PE_START_EVENTS PE_START_TERMS
63 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
64 %token PE_VALUE_SYM_TOOL
67 %token PE_BPF_OBJECT PE_BPF_SOURCE
68 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
69 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
70 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
72 %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE
73 %token PE_ARRAY_ALL PE_ARRAY_RANGE
74 %token PE_DRV_CFG_TERM
76 %type
<num
> PE_VALUE_SYM_HW
77 %type
<num
> PE_VALUE_SYM_SW
78 %type
<num
> PE_VALUE_SYM_TOOL
83 %type
<str
> PE_BPF_OBJECT
84 %type
<str
> PE_BPF_SOURCE
85 %type
<str
> PE_NAME_CACHE_TYPE
86 %type
<str
> PE_NAME_CACHE_OP_RESULT
87 %type
<str
> PE_MODIFIER_EVENT
88 %type
<str
> PE_MODIFIER_BP
89 %type
<str
> PE_EVENT_NAME
90 %type
<str
> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE
91 %type
<str
> PE_DRV_CFG_TERM
92 %destructor
{ free
($$
); } <str
>
93 %type
<term
> event_term
94 %destructor
{ parse_events_term__delete
($$
); } <term
>
95 %type
<list_terms
> event_config
96 %type
<list_terms
> opt_event_config
97 %type
<list_terms
> opt_pmu_config
98 %destructor
{ parse_events_terms__delete
($$
); } <list_terms
>
99 %type
<list_evsel
> event_pmu
100 %type
<list_evsel
> event_legacy_symbol
101 %type
<list_evsel
> event_legacy_cache
102 %type
<list_evsel
> event_legacy_mem
103 %type
<list_evsel
> event_legacy_tracepoint
104 %type
<list_evsel
> event_legacy_numeric
105 %type
<list_evsel
> event_legacy_raw
106 %type
<list_evsel
> event_bpf_file
107 %type
<list_evsel
> event_def
108 %type
<list_evsel
> event_mod
109 %type
<list_evsel
> event_name
110 %type
<list_evsel
> event
111 %type
<list_evsel
> events
112 %type
<list_evsel
> group_def
113 %type
<list_evsel
> group
114 %type
<list_evsel
> groups
115 %destructor
{ free_list_evsel
($$
); } <list_evsel
>
116 %type
<tracepoint_name
> tracepoint_name
117 %destructor
{ free
($$.sys
); free
($$.event
); } <tracepoint_name
>
119 %type
<array
> array_term
120 %type
<array
> array_terms
121 %destructor
{ free
($$.ranges
); } <array
>
127 struct list_head
*list_evsel
;
128 struct list_head
*list_terms
;
129 struct parse_events_term
*term
;
130 struct tracepoint_name
{
134 struct parse_events_array array
;
139 PE_START_EVENTS start_events
141 PE_START_TERMS start_terms
145 struct parse_events_state
*parse_state
= _parse_state
;
148 parse_events_update_lists
($1, &parse_state
->list
);
154 struct list_head
*list
= $1;
155 struct list_head
*group
= $3;
158 parse_events_update_lists
(group
, list
);
164 struct list_head
*list
= $1;
165 struct list_head
*event
= $3;
168 parse_events_update_lists
(event
, list
);
177 group_def
':' PE_MODIFIER_EVENT
179 struct list_head
*list
= $1;
182 err
= parse_events__modifier_group
(list
, $3);
185 free_list_evsel
(list
);
194 PE_NAME
'{' events
'}'
196 struct list_head
*list
= $3;
198 inc_group_count
(list
, _parse_state
);
199 parse_events__set_leader
($1, list
, _parse_state
);
206 struct list_head
*list
= $2;
208 inc_group_count
(list
, _parse_state
);
209 parse_events__set_leader
(NULL
, list
, _parse_state
);
216 struct list_head
*event
= $3;
217 struct list_head
*list
= $1;
220 parse_events_update_lists
(event
, list
);
229 event_name PE_MODIFIER_EVENT
231 struct list_head
*list
= $1;
235 * Apply modifier on all events added by single event definition
236 * (there could be more events added for multiple tracepoint
237 * definitions via '*?'.
239 err
= parse_events__modifier_event
(list
, $2, false
);
242 free_list_evsel
(list
);
251 PE_EVENT_NAME event_def
255 err
= parse_events_name
($2, $1);
266 event_def: event_pmu |
267 event_legacy_symbol |
268 event_legacy_cache sep_dc |
270 event_legacy_tracepoint sep_dc |
271 event_legacy_numeric sep_dc |
272 event_legacy_raw sep_dc |
276 PE_NAME opt_pmu_config
278 struct parse_events_state
*parse_state
= _parse_state
;
279 struct parse_events_error
*error = parse_state
->error;
280 struct list_head
*list
= NULL
, *orig_terms
= NULL
, *terms
= NULL
;
281 char *pattern
= NULL
;
283 #define CLEANUP_YYABORT \
285 parse_events_terms__delete
($2); \
286 parse_events_terms__delete
(orig_terms
); \
293 if
(parse_events_copy_term_list
($2, &orig_terms
))
297 error->idx
= @
1.first_column
;
302 if
(parse_events_add_pmu
(_parse_state
, list
, $1, $2, false
, false
)) {
303 struct perf_pmu
*pmu
= NULL
;
306 if
(asprintf
(&pattern
, "%s*", $1) < 0)
309 while
((pmu
= perf_pmu__scan
(pmu
)) != NULL
) {
310 char *name
= pmu
->name
;
312 if
(!strncmp
(name
, "uncore_", 7) &&
313 strncmp
($1, "uncore_", 7))
315 if
(!fnmatch
(pattern
, name
, 0)) {
316 if
(parse_events_copy_term_list
(orig_terms
, &terms
))
318 if
(!parse_events_add_pmu
(_parse_state
, list
, pmu
->name
, terms
, true
, false
))
320 parse_events_terms__delete
(terms
);
327 parse_events_terms__delete
($2);
328 parse_events_terms__delete
(orig_terms
);
332 #undef CLEANUP_YYABORT
335 PE_KERNEL_PMU_EVENT sep_dc
337 struct list_head
*list
;
340 err
= parse_events_multi_pmu_add
(_parse_state
, $1, &list
);
347 PE_PMU_EVENT_PRE
'-' PE_PMU_EVENT_SUF sep_dc
349 struct list_head
*list
;
352 snprintf
(pmu_name
, sizeof
(pmu_name
), "%s-%s", $1, $3);
355 if
(parse_events_multi_pmu_add
(_parse_state
, pmu_name
, &list
) < 0)
360 PE_PMU_EVENT_FAKE sep_dc
362 struct list_head
*list
;
369 err
= parse_events_add_pmu
(_parse_state
, list
, $1, NULL
, false
, false
);
378 PE_PMU_EVENT_FAKE opt_pmu_config
380 struct list_head
*list
;
387 err
= parse_events_add_pmu
(_parse_state
, list
, $1, $2, false
, false
);
389 parse_events_terms__delete
($2);
403 value_sym
'/' event_config
'/'
405 struct list_head
*list
;
407 int config
= $1 & 255;
412 err
= parse_events_add_numeric
(_parse_state
, list
, type
, config
, $3);
413 parse_events_terms__delete
($3);
415 free_list_evsel
(list
);
421 value_sym sep_slash_slash_dc
423 struct list_head
*list
;
425 int config
= $1 & 255;
429 ABORT_ON
(parse_events_add_numeric
(_parse_state
, list
, type
, config
, NULL
));
433 PE_VALUE_SYM_TOOL sep_slash_slash_dc
435 struct list_head
*list
;
439 ABORT_ON
(parse_events_add_tool
(_parse_state
, list
, $1));
444 PE_NAME_CACHE_TYPE
'-' PE_NAME_CACHE_OP_RESULT
'-' PE_NAME_CACHE_OP_RESULT opt_event_config
446 struct parse_events_state
*parse_state
= _parse_state
;
447 struct parse_events_error
*error = parse_state
->error;
448 struct list_head
*list
;
453 err
= parse_events_add_cache
(list
, &parse_state
->idx
, $1, $3, $5, error, $6);
454 parse_events_terms__delete
($6);
459 free_list_evsel
(list
);
465 PE_NAME_CACHE_TYPE
'-' PE_NAME_CACHE_OP_RESULT opt_event_config
467 struct parse_events_state
*parse_state
= _parse_state
;
468 struct parse_events_error
*error = parse_state
->error;
469 struct list_head
*list
;
474 err
= parse_events_add_cache
(list
, &parse_state
->idx
, $1, $3, NULL
, error, $4);
475 parse_events_terms__delete
($4);
479 free_list_evsel
(list
);
485 PE_NAME_CACHE_TYPE opt_event_config
487 struct parse_events_state
*parse_state
= _parse_state
;
488 struct parse_events_error
*error = parse_state
->error;
489 struct list_head
*list
;
494 err
= parse_events_add_cache
(list
, &parse_state
->idx
, $1, NULL
, NULL
, error, $2);
495 parse_events_terms__delete
($2);
498 free_list_evsel
(list
);
505 PE_PREFIX_MEM PE_VALUE
'/' PE_VALUE
':' PE_MODIFIER_BP sep_dc
507 struct parse_events_state
*parse_state
= _parse_state
;
508 struct list_head
*list
;
513 err
= parse_events_add_breakpoint
(list
, &parse_state
->idx
,
514 (void *) $2, $6, $4);
523 PE_PREFIX_MEM PE_VALUE
'/' PE_VALUE sep_dc
525 struct parse_events_state
*parse_state
= _parse_state
;
526 struct list_head
*list
;
530 if
(parse_events_add_breakpoint
(list
, &parse_state
->idx
,
531 (void *) $2, NULL
, $4)) {
538 PE_PREFIX_MEM PE_VALUE
':' PE_MODIFIER_BP sep_dc
540 struct parse_events_state
*parse_state
= _parse_state
;
541 struct list_head
*list
;
546 err
= parse_events_add_breakpoint
(list
, &parse_state
->idx
,
556 PE_PREFIX_MEM PE_VALUE sep_dc
558 struct parse_events_state
*parse_state
= _parse_state
;
559 struct list_head
*list
;
563 if
(parse_events_add_breakpoint
(list
, &parse_state
->idx
,
564 (void *) $2, NULL
, 0)) {
571 event_legacy_tracepoint:
572 tracepoint_name opt_event_config
574 struct parse_events_state
*parse_state
= _parse_state
;
575 struct parse_events_error
*error = parse_state
->error;
576 struct list_head
*list
;
582 error->idx
= @
1.first_column
;
584 err
= parse_events_add_tracepoint
(list
, &parse_state
->idx
, $1.sys
, $1.event
,
587 parse_events_terms__delete
($2);
598 PE_NAME
'-' PE_NAME
':' PE_NAME
600 struct tracepoint_name tracepoint
;
602 ABORT_ON
(asprintf
(&tracepoint.sys
, "%s-%s", $1, $3) < 0);
603 tracepoint.event
= $5;
611 struct tracepoint_name tracepoint
= {$1, $3};
616 event_legacy_numeric:
617 PE_VALUE
':' PE_VALUE opt_event_config
619 struct list_head
*list
;
624 err
= parse_events_add_numeric
(_parse_state
, list
, (u32
)$1, $3, $4);
625 parse_events_terms__delete
($4);
634 PE_RAW opt_event_config
636 struct list_head
*list
;
641 err
= parse_events_add_numeric
(_parse_state
, list
, PERF_TYPE_RAW
, $1, $2);
642 parse_events_terms__delete
($2);
651 PE_BPF_OBJECT opt_event_config
653 struct parse_events_state
*parse_state
= _parse_state
;
654 struct list_head
*list
;
659 err
= parse_events_load_bpf
(parse_state
, list
, $1, false
, $2);
660 parse_events_terms__delete
($2);
669 PE_BPF_SOURCE opt_event_config
671 struct list_head
*list
;
676 err
= parse_events_load_bpf
(_parse_state
, list
, $1, true
, $2);
677 parse_events_terms__delete
($2);
711 start_terms: event_config
713 struct parse_events_state
*parse_state
= _parse_state
;
714 if
(parse_state
->terms
) {
715 parse_events_terms__delete
($1);
718 parse_state
->terms
= $1;
722 event_config
',' event_term
724 struct list_head
*head
= $1;
725 struct parse_events_term
*term
= $3;
728 parse_events_term__delete
(term
);
731 list_add_tail
(&term
->list
, head
);
737 struct list_head
*head
= malloc
(sizeof
(*head
));
738 struct parse_events_term
*term
= $1;
741 INIT_LIST_HEAD
(head
);
742 list_add_tail
(&term
->list
, head
);
749 struct parse_events_term
*term
;
751 ABORT_ON
(parse_events_term__num
(&term
, PARSE_EVENTS__TERM_TYPE_CONFIG
,
752 NULL
, $1, false
, &@
1, NULL
));
758 struct parse_events_term
*term
;
760 if
(parse_events_term__str
(&term
, PARSE_EVENTS__TERM_TYPE_USER
,
771 struct parse_events_term
*term
;
773 if
(parse_events_term__num
(&term
, PARSE_EVENTS__TERM_TYPE_USER
,
774 $1, $3, false
, &@
1, &@
3)) {
781 PE_NAME
'=' PE_VALUE_SYM_HW
783 struct parse_events_term
*term
;
784 int config
= $3 & 255;
786 if
(parse_events_term__sym_hw
(&term
, $1, config
)) {
795 struct parse_events_term
*term
;
797 if
(parse_events_term__num
(&term
, PARSE_EVENTS__TERM_TYPE_USER
,
798 $1, 1, true
, &@
1, NULL
)) {
807 struct parse_events_term
*term
;
808 int config
= $1 & 255;
810 ABORT_ON
(parse_events_term__sym_hw
(&term
, NULL
, config
));
816 struct parse_events_term
*term
;
818 if
(parse_events_term__str
(&term
, (int)$1, NULL
, $3, &@
1, &@
3)) {
827 struct parse_events_term
*term
;
829 ABORT_ON
(parse_events_term__num
(&term
, (int)$1, NULL
, $3, false
, &@
1, &@
3));
835 struct parse_events_term
*term
;
837 ABORT_ON
(parse_events_term__num
(&term
, (int)$1, NULL
, 1, true
, &@
1, NULL
));
841 PE_NAME array
'=' PE_NAME
843 struct parse_events_term
*term
;
845 if
(parse_events_term__str
(&term
, PARSE_EVENTS__TERM_TYPE_USER
,
856 PE_NAME array
'=' PE_VALUE
858 struct parse_events_term
*term
;
860 if
(parse_events_term__num
(&term
, PARSE_EVENTS__TERM_TYPE_USER
,
861 $1, $4, false
, &@
1, &@
4)) {
872 struct parse_events_term
*term
;
873 char *config
= strdup
($1);
876 if
(parse_events_term__str
(&term
, PARSE_EVENTS__TERM_TYPE_DRV_CFG
,
877 config
, $1, &@
1, NULL
)) {
898 array_terms
',' array_term
900 struct parse_events_array new_array
;
902 new_array.nr_ranges
= $1.nr_ranges
+ $3.nr_ranges
;
903 new_array.ranges
= realloc
($1.ranges
,
904 sizeof
(new_array.ranges
[0]) *
905 new_array.nr_ranges
);
906 ABORT_ON
(!new_array.ranges
);
907 memcpy
(&new_array.ranges
[$1.nr_ranges
], $3.ranges
,
908 $3.nr_ranges
* sizeof
(new_array.ranges
[0]));
918 struct parse_events_array array
;
921 array.ranges
= malloc
(sizeof
(array.ranges
[0]));
922 ABORT_ON
(!array.ranges
);
923 array.ranges
[0].start
= $1;
924 array.ranges
[0].length
= 1;
928 PE_VALUE PE_ARRAY_RANGE PE_VALUE
930 struct parse_events_array array
;
934 array.ranges
= malloc
(sizeof
(array.ranges
[0]));
935 ABORT_ON
(!array.ranges
);
936 array.ranges
[0].start
= $1;
937 array.ranges
[0].length
= $3 - $1 + 1;
943 sep_slash_slash_dc: '/' '/' |
':' |
947 void parse_events_error
(YYLTYPE *loc
, void *parse_state
,
948 void *scanner __maybe_unused
,
949 char const *msg __maybe_unused
)
951 parse_events_evlist_error
(parse_state
, loc
->last_column
, "parser error");