1 %pure-parser 2 %parse-param {void *_data} 3 %parse-param {void *scanner} 4 %lex-param {void* scanner} 5 6 %{ 7 8 #define YYDEBUG 1 9 10 #include <linux/compiler.h> 11 #include <linux/list.h> 12 #include "types.h" 13 #include "util.h" 14 #include "parse-events.h" 15 #include "parse-events-bison.h" 16 17 extern int parse_events_lex (YYSTYPE* lvalp, void* scanner); 18 19 #define ABORT_ON(val) \ 20 do { \ 21 if (val) \ 22 YYABORT; \ 23 } while (0) 24 25 static inc_group_count(struct list_head *list, 26 struct parse_events_evlist *data) 27 { 28 /* Count groups only have more than 1 members */ 29 if (!list_is_last(list->next, list)) 30 data->nr_groups++; 31 } 32 33 %} 34 35 %token PE_START_EVENTS PE_START_TERMS 36 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 37 %token PE_EVENT_NAME 38 %token PE_NAME 39 %token PE_MODIFIER_EVENT PE_MODIFIER_BP 40 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 41 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 42 %token PE_ERROR 43 %type <num> PE_VALUE 44 %type <num> PE_VALUE_SYM_HW 45 %type <num> PE_VALUE_SYM_SW 46 %type <num> PE_RAW 47 %type <num> PE_TERM 48 %type <str> PE_NAME 49 %type <str> PE_NAME_CACHE_TYPE 50 %type <str> PE_NAME_CACHE_OP_RESULT 51 %type <str> PE_MODIFIER_EVENT 52 %type <str> PE_MODIFIER_BP 53 %type <str> PE_EVENT_NAME 54 %type <num> value_sym 55 %type <head> event_config 56 %type <term> event_term 57 %type <head> event_pmu 58 %type <head> event_legacy_symbol 59 %type <head> event_legacy_cache 60 %type <head> event_legacy_mem 61 %type <head> event_legacy_tracepoint 62 %type <head> event_legacy_numeric 63 %type <head> event_legacy_raw 64 %type <head> event_def 65 %type <head> event_mod 66 %type <head> event_name 67 %type <head> event 68 %type <head> events 69 %type <head> group_def 70 %type <head> group 71 %type <head> groups 72 73 %union 74 { 75 char *str; 76 u64 num; 77 struct list_head *head; 78 struct parse_events_term *term; 79 } 80 %% 81 82 start: 83 PE_START_EVENTS start_events 84 | 85 PE_START_TERMS start_terms 86 87 start_events: groups 88 { 89 struct parse_events_evlist *data = _data; 90 91 parse_events_update_lists($1, &data->list); 92 } 93 94 groups: 95 groups ',' group 96 { 97 struct list_head *list = $1; 98 struct list_head *group = $3; 99 100 parse_events_update_lists(group, list); 101 $$ = list; 102 } 103 | 104 groups ',' event 105 { 106 struct list_head *list = $1; 107 struct list_head *event = $3; 108 109 parse_events_update_lists(event, list); 110 $$ = list; 111 } 112 | 113 group 114 | 115 event 116 117 group: 118 group_def ':' PE_MODIFIER_EVENT 119 { 120 struct list_head *list = $1; 121 122 ABORT_ON(parse_events__modifier_group(list, $3)); 123 $$ = list; 124 } 125 | 126 group_def 127 128 group_def: 129 PE_NAME '{' events '}' 130 { 131 struct list_head *list = $3; 132 133 inc_group_count(list, _data); 134 parse_events__set_leader($1, list); 135 $$ = list; 136 } 137 | 138 '{' events '}' 139 { 140 struct list_head *list = $2; 141 142 inc_group_count(list, _data); 143 parse_events__set_leader(NULL, list); 144 $$ = list; 145 } 146 147 events: 148 events ',' event 149 { 150 struct list_head *event = $3; 151 struct list_head *list = $1; 152 153 parse_events_update_lists(event, list); 154 $$ = list; 155 } 156 | 157 event 158 159 event: event_mod 160 161 event_mod: 162 event_name PE_MODIFIER_EVENT 163 { 164 struct list_head *list = $1; 165 166 /* 167 * Apply modifier on all events added by single event definition 168 * (there could be more events added for multiple tracepoint 169 * definitions via '*?'. 170 */ 171 ABORT_ON(parse_events__modifier_event(list, $2, false)); 172 $$ = list; 173 } 174 | 175 event_name 176 177 event_name: 178 PE_EVENT_NAME event_def 179 { 180 ABORT_ON(parse_events_name($2, $1)); 181 free($1); 182 $$ = $2; 183 } 184 | 185 event_def 186 187 event_def: event_pmu | 188 event_legacy_symbol | 189 event_legacy_cache sep_dc | 190 event_legacy_mem | 191 event_legacy_tracepoint sep_dc | 192 event_legacy_numeric sep_dc | 193 event_legacy_raw sep_dc 194 195 event_pmu: 196 PE_NAME '/' event_config '/' 197 { 198 struct parse_events_evlist *data = _data; 199 struct list_head *list = NULL; 200 201 ABORT_ON(parse_events_add_pmu(&list, &data->idx, $1, $3)); 202 parse_events__free_terms($3); 203 $$ = list; 204 } 205 206 value_sym: 207 PE_VALUE_SYM_HW 208 | 209 PE_VALUE_SYM_SW 210 211 event_legacy_symbol: 212 value_sym '/' event_config '/' 213 { 214 struct parse_events_evlist *data = _data; 215 struct list_head *list = NULL; 216 int type = $1 >> 16; 217 int config = $1 & 255; 218 219 ABORT_ON(parse_events_add_numeric(&list, &data->idx, 220 type, config, $3)); 221 parse_events__free_terms($3); 222 $$ = list; 223 } 224 | 225 value_sym sep_slash_dc 226 { 227 struct parse_events_evlist *data = _data; 228 struct list_head *list = NULL; 229 int type = $1 >> 16; 230 int config = $1 & 255; 231 232 ABORT_ON(parse_events_add_numeric(&list, &data->idx, 233 type, config, NULL)); 234 $$ = list; 235 } 236 237 event_legacy_cache: 238 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT 239 { 240 struct parse_events_evlist *data = _data; 241 struct list_head *list = NULL; 242 243 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, $5)); 244 $$ = list; 245 } 246 | 247 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT 248 { 249 struct parse_events_evlist *data = _data; 250 struct list_head *list = NULL; 251 252 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, NULL)); 253 $$ = list; 254 } 255 | 256 PE_NAME_CACHE_TYPE 257 { 258 struct parse_events_evlist *data = _data; 259 struct list_head *list = NULL; 260 261 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, NULL, NULL)); 262 $$ = list; 263 } 264 265 event_legacy_mem: 266 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 267 { 268 struct parse_events_evlist *data = _data; 269 struct list_head *list = NULL; 270 271 ABORT_ON(parse_events_add_breakpoint(&list, &data->idx, 272 (void *) $2, $4)); 273 $$ = list; 274 } 275 | 276 PE_PREFIX_MEM PE_VALUE sep_dc 277 { 278 struct parse_events_evlist *data = _data; 279 struct list_head *list = NULL; 280 281 ABORT_ON(parse_events_add_breakpoint(&list, &data->idx, 282 (void *) $2, NULL)); 283 $$ = list; 284 } 285 286 event_legacy_tracepoint: 287 PE_NAME ':' PE_NAME 288 { 289 struct parse_events_evlist *data = _data; 290 struct list_head *list = NULL; 291 292 ABORT_ON(parse_events_add_tracepoint(&list, &data->idx, $1, $3)); 293 $$ = list; 294 } 295 296 event_legacy_numeric: 297 PE_VALUE ':' PE_VALUE 298 { 299 struct parse_events_evlist *data = _data; 300 struct list_head *list = NULL; 301 302 ABORT_ON(parse_events_add_numeric(&list, &data->idx, (u32)$1, $3, NULL)); 303 $$ = list; 304 } 305 306 event_legacy_raw: 307 PE_RAW 308 { 309 struct parse_events_evlist *data = _data; 310 struct list_head *list = NULL; 311 312 ABORT_ON(parse_events_add_numeric(&list, &data->idx, 313 PERF_TYPE_RAW, $1, NULL)); 314 $$ = list; 315 } 316 317 start_terms: event_config 318 { 319 struct parse_events_terms *data = _data; 320 data->terms = $1; 321 } 322 323 event_config: 324 event_config ',' event_term 325 { 326 struct list_head *head = $1; 327 struct parse_events_term *term = $3; 328 329 ABORT_ON(!head); 330 list_add_tail(&term->list, head); 331 $$ = $1; 332 } 333 | 334 event_term 335 { 336 struct list_head *head = malloc(sizeof(*head)); 337 struct parse_events_term *term = $1; 338 339 ABORT_ON(!head); 340 INIT_LIST_HEAD(head); 341 list_add_tail(&term->list, head); 342 $$ = head; 343 } 344 345 event_term: 346 PE_NAME '=' PE_NAME 347 { 348 struct parse_events_term *term; 349 350 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 351 $1, $3)); 352 $$ = term; 353 } 354 | 355 PE_NAME '=' PE_VALUE 356 { 357 struct parse_events_term *term; 358 359 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 360 $1, $3)); 361 $$ = term; 362 } 363 | 364 PE_NAME '=' PE_VALUE_SYM_HW 365 { 366 struct parse_events_term *term; 367 int config = $3 & 255; 368 369 ABORT_ON(parse_events_term__sym_hw(&term, $1, config)); 370 $$ = term; 371 } 372 | 373 PE_NAME 374 { 375 struct parse_events_term *term; 376 377 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 378 $1, 1)); 379 $$ = term; 380 } 381 | 382 PE_VALUE_SYM_HW 383 { 384 struct parse_events_term *term; 385 int config = $1 & 255; 386 387 ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); 388 $$ = term; 389 } 390 | 391 PE_TERM '=' PE_NAME 392 { 393 struct parse_events_term *term; 394 395 ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3)); 396 $$ = term; 397 } 398 | 399 PE_TERM '=' PE_VALUE 400 { 401 struct parse_events_term *term; 402 403 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3)); 404 $$ = term; 405 } 406 | 407 PE_TERM 408 { 409 struct parse_events_term *term; 410 411 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1)); 412 $$ = term; 413 } 414 415 sep_dc: ':' | 416 417 sep_slash_dc: '/' | ':' | 418 419 %% 420 421 void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused, 422 char const *msg __maybe_unused) 423 { 424 } 425