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