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