1 %pure-parser 2 %parse-param {void *_data} 3 %parse-param {void *scanner} 4 %lex-param {void* scanner} 5 %locations 6 7 %{ 8 9 #define YYDEBUG 1 10 11 #include <linux/compiler.h> 12 #include <linux/list.h> 13 #include <linux/types.h> 14 #include "util.h" 15 #include "parse-events.h" 16 #include "parse-events-bison.h" 17 18 #define ABORT_ON(val) \ 19 do { \ 20 if (val) \ 21 YYABORT; \ 22 } while (0) 23 24 #define ALLOC_LIST(list) \ 25 do { \ 26 list = malloc(sizeof(*list)); \ 27 ABORT_ON(!list); \ 28 INIT_LIST_HEAD(list); \ 29 } while (0) 30 31 static inc_group_count(struct list_head *list, 32 struct parse_events_evlist *data) 33 { 34 /* Count groups only have more than 1 members */ 35 if (!list_is_last(list->next, list)) 36 data->nr_groups++; 37 } 38 39 %} 40 41 %token PE_START_EVENTS PE_START_TERMS 42 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 43 %token PE_EVENT_NAME 44 %token PE_NAME 45 %token PE_BPF_OBJECT PE_BPF_SOURCE 46 %token PE_MODIFIER_EVENT PE_MODIFIER_BP 47 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 48 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 49 %token PE_ERROR 50 %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT 51 %type <num> PE_VALUE 52 %type <num> PE_VALUE_SYM_HW 53 %type <num> PE_VALUE_SYM_SW 54 %type <num> PE_RAW 55 %type <num> PE_TERM 56 %type <str> PE_NAME 57 %type <str> PE_BPF_OBJECT 58 %type <str> PE_BPF_SOURCE 59 %type <str> PE_NAME_CACHE_TYPE 60 %type <str> PE_NAME_CACHE_OP_RESULT 61 %type <str> PE_MODIFIER_EVENT 62 %type <str> PE_MODIFIER_BP 63 %type <str> PE_EVENT_NAME 64 %type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT 65 %type <num> value_sym 66 %type <head> event_config 67 %type <term> event_term 68 %type <head> event_pmu 69 %type <head> event_legacy_symbol 70 %type <head> event_legacy_cache 71 %type <head> event_legacy_mem 72 %type <head> event_legacy_tracepoint 73 %type <tracepoint_name> tracepoint_name 74 %type <head> event_legacy_numeric 75 %type <head> event_legacy_raw 76 %type <head> event_bpf_file 77 %type <head> event_def 78 %type <head> event_mod 79 %type <head> event_name 80 %type <head> event 81 %type <head> events 82 %type <head> group_def 83 %type <head> group 84 %type <head> groups 85 86 %union 87 { 88 char *str; 89 u64 num; 90 struct list_head *head; 91 struct parse_events_term *term; 92 struct tracepoint_name { 93 char *sys; 94 char *event; 95 } tracepoint_name; 96 } 97 %% 98 99 start: 100 PE_START_EVENTS start_events 101 | 102 PE_START_TERMS start_terms 103 104 start_events: groups 105 { 106 struct parse_events_evlist *data = _data; 107 108 parse_events_update_lists($1, &data->list); 109 } 110 111 groups: 112 groups ',' group 113 { 114 struct list_head *list = $1; 115 struct list_head *group = $3; 116 117 parse_events_update_lists(group, list); 118 $$ = list; 119 } 120 | 121 groups ',' event 122 { 123 struct list_head *list = $1; 124 struct list_head *event = $3; 125 126 parse_events_update_lists(event, list); 127 $$ = list; 128 } 129 | 130 group 131 | 132 event 133 134 group: 135 group_def ':' PE_MODIFIER_EVENT 136 { 137 struct list_head *list = $1; 138 139 ABORT_ON(parse_events__modifier_group(list, $3)); 140 $$ = list; 141 } 142 | 143 group_def 144 145 group_def: 146 PE_NAME '{' events '}' 147 { 148 struct list_head *list = $3; 149 150 inc_group_count(list, _data); 151 parse_events__set_leader($1, list); 152 $$ = list; 153 } 154 | 155 '{' events '}' 156 { 157 struct list_head *list = $2; 158 159 inc_group_count(list, _data); 160 parse_events__set_leader(NULL, list); 161 $$ = list; 162 } 163 164 events: 165 events ',' event 166 { 167 struct list_head *event = $3; 168 struct list_head *list = $1; 169 170 parse_events_update_lists(event, list); 171 $$ = list; 172 } 173 | 174 event 175 176 event: event_mod 177 178 event_mod: 179 event_name PE_MODIFIER_EVENT 180 { 181 struct list_head *list = $1; 182 183 /* 184 * Apply modifier on all events added by single event definition 185 * (there could be more events added for multiple tracepoint 186 * definitions via '*?'. 187 */ 188 ABORT_ON(parse_events__modifier_event(list, $2, false)); 189 $$ = list; 190 } 191 | 192 event_name 193 194 event_name: 195 PE_EVENT_NAME event_def 196 { 197 ABORT_ON(parse_events_name($2, $1)); 198 free($1); 199 $$ = $2; 200 } 201 | 202 event_def 203 204 event_def: event_pmu | 205 event_legacy_symbol | 206 event_legacy_cache sep_dc | 207 event_legacy_mem | 208 event_legacy_tracepoint sep_dc | 209 event_legacy_numeric sep_dc | 210 event_legacy_raw sep_dc | 211 event_bpf_file 212 213 event_pmu: 214 PE_NAME '/' event_config '/' 215 { 216 struct parse_events_evlist *data = _data; 217 struct list_head *list; 218 219 ALLOC_LIST(list); 220 ABORT_ON(parse_events_add_pmu(data, list, $1, $3)); 221 parse_events__free_terms($3); 222 $$ = list; 223 } 224 | 225 PE_NAME '/' '/' 226 { 227 struct parse_events_evlist *data = _data; 228 struct list_head *list; 229 230 ALLOC_LIST(list); 231 ABORT_ON(parse_events_add_pmu(data, list, $1, NULL)); 232 $$ = list; 233 } 234 | 235 PE_KERNEL_PMU_EVENT sep_dc 236 { 237 struct parse_events_evlist *data = _data; 238 struct list_head *head; 239 struct parse_events_term *term; 240 struct list_head *list; 241 242 ALLOC_LIST(head); 243 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 244 $1, 1, &@1, NULL)); 245 list_add_tail(&term->list, head); 246 247 ALLOC_LIST(list); 248 ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); 249 parse_events__free_terms(head); 250 $$ = list; 251 } 252 | 253 PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc 254 { 255 struct parse_events_evlist *data = _data; 256 struct list_head *head; 257 struct parse_events_term *term; 258 struct list_head *list; 259 char pmu_name[128]; 260 snprintf(&pmu_name, 128, "%s-%s", $1, $3); 261 262 ALLOC_LIST(head); 263 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 264 &pmu_name, 1, &@1, NULL)); 265 list_add_tail(&term->list, head); 266 267 ALLOC_LIST(list); 268 ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); 269 parse_events__free_terms(head); 270 $$ = list; 271 } 272 273 value_sym: 274 PE_VALUE_SYM_HW 275 | 276 PE_VALUE_SYM_SW 277 278 event_legacy_symbol: 279 value_sym '/' event_config '/' 280 { 281 struct parse_events_evlist *data = _data; 282 struct list_head *list; 283 int type = $1 >> 16; 284 int config = $1 & 255; 285 286 ALLOC_LIST(list); 287 ABORT_ON(parse_events_add_numeric(data, list, type, config, $3)); 288 parse_events__free_terms($3); 289 $$ = list; 290 } 291 | 292 value_sym sep_slash_dc 293 { 294 struct parse_events_evlist *data = _data; 295 struct list_head *list; 296 int type = $1 >> 16; 297 int config = $1 & 255; 298 299 ALLOC_LIST(list); 300 ABORT_ON(parse_events_add_numeric(data, list, type, config, NULL)); 301 $$ = list; 302 } 303 304 event_legacy_cache: 305 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT 306 { 307 struct parse_events_evlist *data = _data; 308 struct list_head *list; 309 310 ALLOC_LIST(list); 311 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5)); 312 $$ = list; 313 } 314 | 315 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT 316 { 317 struct parse_events_evlist *data = _data; 318 struct list_head *list; 319 320 ALLOC_LIST(list); 321 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL)); 322 $$ = list; 323 } 324 | 325 PE_NAME_CACHE_TYPE 326 { 327 struct parse_events_evlist *data = _data; 328 struct list_head *list; 329 330 ALLOC_LIST(list); 331 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL)); 332 $$ = list; 333 } 334 335 event_legacy_mem: 336 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc 337 { 338 struct parse_events_evlist *data = _data; 339 struct list_head *list; 340 341 ALLOC_LIST(list); 342 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 343 (void *) $2, $6, $4)); 344 $$ = list; 345 } 346 | 347 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc 348 { 349 struct parse_events_evlist *data = _data; 350 struct list_head *list; 351 352 ALLOC_LIST(list); 353 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 354 (void *) $2, NULL, $4)); 355 $$ = list; 356 } 357 | 358 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 359 { 360 struct parse_events_evlist *data = _data; 361 struct list_head *list; 362 363 ALLOC_LIST(list); 364 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 365 (void *) $2, $4, 0)); 366 $$ = list; 367 } 368 | 369 PE_PREFIX_MEM PE_VALUE sep_dc 370 { 371 struct parse_events_evlist *data = _data; 372 struct list_head *list; 373 374 ALLOC_LIST(list); 375 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 376 (void *) $2, NULL, 0)); 377 $$ = list; 378 } 379 380 event_legacy_tracepoint: 381 tracepoint_name 382 { 383 struct parse_events_evlist *data = _data; 384 struct parse_events_error *error = data->error; 385 struct list_head *list; 386 387 ALLOC_LIST(list); 388 if (error) 389 error->idx = @1.first_column; 390 391 if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event, 392 error, NULL)) 393 return -1; 394 395 $$ = list; 396 } 397 | 398 tracepoint_name '/' event_config '/' 399 { 400 struct parse_events_evlist *data = _data; 401 struct parse_events_error *error = data->error; 402 struct list_head *list; 403 404 ALLOC_LIST(list); 405 if (error) 406 error->idx = @1.first_column; 407 408 if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event, 409 error, $3)) 410 return -1; 411 412 $$ = list; 413 } 414 415 tracepoint_name: 416 PE_NAME '-' PE_NAME ':' PE_NAME 417 { 418 char sys_name[128]; 419 struct tracepoint_name tracepoint; 420 421 snprintf(&sys_name, 128, "%s-%s", $1, $3); 422 tracepoint.sys = &sys_name; 423 tracepoint.event = $5; 424 425 $$ = tracepoint; 426 } 427 | 428 PE_NAME ':' PE_NAME 429 { 430 struct tracepoint_name tracepoint = {$1, $3}; 431 432 $$ = tracepoint; 433 } 434 435 event_legacy_numeric: 436 PE_VALUE ':' PE_VALUE 437 { 438 struct parse_events_evlist *data = _data; 439 struct list_head *list; 440 441 ALLOC_LIST(list); 442 ABORT_ON(parse_events_add_numeric(data, list, (u32)$1, $3, NULL)); 443 $$ = list; 444 } 445 446 event_legacy_raw: 447 PE_RAW 448 { 449 struct parse_events_evlist *data = _data; 450 struct list_head *list; 451 452 ALLOC_LIST(list); 453 ABORT_ON(parse_events_add_numeric(data, list, PERF_TYPE_RAW, $1, NULL)); 454 $$ = list; 455 } 456 457 event_bpf_file: 458 PE_BPF_OBJECT 459 { 460 struct parse_events_evlist *data = _data; 461 struct parse_events_error *error = data->error; 462 struct list_head *list; 463 464 ALLOC_LIST(list); 465 ABORT_ON(parse_events_load_bpf(data, list, $1, false)); 466 $$ = list; 467 } 468 | 469 PE_BPF_SOURCE 470 { 471 struct parse_events_evlist *data = _data; 472 struct list_head *list; 473 474 ALLOC_LIST(list); 475 ABORT_ON(parse_events_load_bpf(data, list, $1, true)); 476 $$ = list; 477 } 478 479 start_terms: event_config 480 { 481 struct parse_events_terms *data = _data; 482 data->terms = $1; 483 } 484 485 event_config: 486 event_config ',' event_term 487 { 488 struct list_head *head = $1; 489 struct parse_events_term *term = $3; 490 491 ABORT_ON(!head); 492 list_add_tail(&term->list, head); 493 $$ = $1; 494 } 495 | 496 event_term 497 { 498 struct list_head *head = malloc(sizeof(*head)); 499 struct parse_events_term *term = $1; 500 501 ABORT_ON(!head); 502 INIT_LIST_HEAD(head); 503 list_add_tail(&term->list, head); 504 $$ = head; 505 } 506 507 event_term: 508 PE_NAME '=' PE_NAME 509 { 510 struct parse_events_term *term; 511 512 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 513 $1, $3, &@1, &@3)); 514 $$ = term; 515 } 516 | 517 PE_NAME '=' PE_VALUE 518 { 519 struct parse_events_term *term; 520 521 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 522 $1, $3, &@1, &@3)); 523 $$ = term; 524 } 525 | 526 PE_NAME '=' PE_VALUE_SYM_HW 527 { 528 struct parse_events_term *term; 529 int config = $3 & 255; 530 531 ABORT_ON(parse_events_term__sym_hw(&term, $1, config)); 532 $$ = term; 533 } 534 | 535 PE_NAME 536 { 537 struct parse_events_term *term; 538 539 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 540 $1, 1, &@1, NULL)); 541 $$ = term; 542 } 543 | 544 PE_VALUE_SYM_HW 545 { 546 struct parse_events_term *term; 547 int config = $1 & 255; 548 549 ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); 550 $$ = term; 551 } 552 | 553 PE_TERM '=' PE_NAME 554 { 555 struct parse_events_term *term; 556 557 ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3)); 558 $$ = term; 559 } 560 | 561 PE_TERM '=' PE_VALUE 562 { 563 struct parse_events_term *term; 564 565 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, &@1, &@3)); 566 $$ = term; 567 } 568 | 569 PE_TERM 570 { 571 struct parse_events_term *term; 572 573 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL)); 574 $$ = term; 575 } 576 577 sep_dc: ':' | 578 579 sep_slash_dc: '/' | ':' | 580 581 %% 582 583 void parse_events_error(YYLTYPE *loc, void *data, 584 void *scanner __maybe_unused, 585 char const *msg __maybe_unused) 586 { 587 parse_events_evlist_error(data, loc->last_column, "parser error"); 588 } 589