1 %define api.pure full 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 <errno.h> 12 #include <fnmatch.h> 13 #include <stdio.h> 14 #include <linux/compiler.h> 15 #include <linux/types.h> 16 #include <linux/zalloc.h> 17 #include "pmu.h" 18 #include "pmus.h" 19 #include "evsel.h" 20 #include "parse-events.h" 21 #include "parse-events-bison.h" 22 23 int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner); 24 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg); 25 26 #define PE_ABORT(val) \ 27 do { \ 28 if (val == -ENOMEM) \ 29 YYNOMEM; \ 30 YYABORT; \ 31 } while (0) 32 33 static struct list_head* alloc_list(void) 34 { 35 struct list_head *list; 36 37 list = malloc(sizeof(*list)); 38 if (!list) 39 return NULL; 40 41 INIT_LIST_HEAD(list); 42 return list; 43 } 44 45 static void free_list_evsel(struct list_head* list_evsel) 46 { 47 struct evsel *evsel, *tmp; 48 49 list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) { 50 list_del_init(&evsel->core.node); 51 evsel__delete(evsel); 52 } 53 free(list_evsel); 54 } 55 56 %} 57 58 %token PE_START_EVENTS PE_START_TERMS 59 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM 60 %token PE_VALUE_SYM_TOOL 61 %token PE_EVENT_NAME 62 %token PE_RAW PE_NAME 63 %token PE_BPF_OBJECT PE_BPF_SOURCE 64 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH 65 %token PE_LEGACY_CACHE 66 %token PE_PREFIX_MEM 67 %token PE_ERROR 68 %token PE_DRV_CFG_TERM 69 %token PE_TERM_HW 70 %type <num> PE_VALUE 71 %type <num> PE_VALUE_SYM_HW 72 %type <num> PE_VALUE_SYM_SW 73 %type <num> PE_VALUE_SYM_TOOL 74 %type <num> PE_TERM 75 %type <num> value_sym 76 %type <str> PE_RAW 77 %type <str> PE_NAME 78 %type <str> PE_BPF_OBJECT 79 %type <str> PE_BPF_SOURCE 80 %type <str> PE_LEGACY_CACHE 81 %type <str> PE_MODIFIER_EVENT 82 %type <str> PE_MODIFIER_BP 83 %type <str> PE_EVENT_NAME 84 %type <str> PE_DRV_CFG_TERM 85 %type <str> name_or_raw name_or_legacy 86 %destructor { free ($$); } <str> 87 %type <term> event_term 88 %destructor { parse_events_term__delete ($$); } <term> 89 %type <list_terms> event_config 90 %type <list_terms> opt_event_config 91 %type <list_terms> opt_pmu_config 92 %destructor { parse_events_terms__delete ($$); } <list_terms> 93 %type <list_evsel> event_pmu 94 %type <list_evsel> event_legacy_symbol 95 %type <list_evsel> event_legacy_cache 96 %type <list_evsel> event_legacy_mem 97 %type <list_evsel> event_legacy_tracepoint 98 %type <list_evsel> event_legacy_numeric 99 %type <list_evsel> event_legacy_raw 100 %type <list_evsel> event_bpf_file 101 %type <list_evsel> event_def 102 %type <list_evsel> event_mod 103 %type <list_evsel> event_name 104 %type <list_evsel> event 105 %type <list_evsel> events 106 %type <list_evsel> group_def 107 %type <list_evsel> group 108 %type <list_evsel> groups 109 %destructor { free_list_evsel ($$); } <list_evsel> 110 %type <tracepoint_name> tracepoint_name 111 %type <hardware_term> PE_TERM_HW 112 %destructor { free ($$.str); } <hardware_term> 113 114 %union 115 { 116 char *str; 117 u64 num; 118 struct list_head *list_evsel; 119 struct list_head *list_terms; 120 struct parse_events_term *term; 121 struct tracepoint_name { 122 char *sys; 123 char *event; 124 } tracepoint_name; 125 struct hardware_term { 126 char *str; 127 u64 num; 128 } hardware_term; 129 } 130 %% 131 132 start: 133 PE_START_EVENTS start_events 134 | 135 PE_START_TERMS start_terms 136 137 start_events: groups 138 { 139 struct parse_events_state *parse_state = _parse_state; 140 141 /* frees $1 */ 142 parse_events_update_lists($1, &parse_state->list); 143 } 144 145 groups: 146 groups ',' group 147 { 148 struct list_head *list = $1; 149 struct list_head *group = $3; 150 151 /* frees $3 */ 152 parse_events_update_lists(group, list); 153 $$ = list; 154 } 155 | 156 groups ',' event 157 { 158 struct list_head *list = $1; 159 struct list_head *event = $3; 160 161 /* frees $3 */ 162 parse_events_update_lists(event, list); 163 $$ = list; 164 } 165 | 166 group 167 | 168 event 169 170 group: 171 group_def ':' PE_MODIFIER_EVENT 172 { 173 struct list_head *list = $1; 174 int err; 175 176 err = parse_events__modifier_group(list, $3); 177 free($3); 178 if (err) { 179 struct parse_events_state *parse_state = _parse_state; 180 struct parse_events_error *error = parse_state->error; 181 182 parse_events_error__handle(error, @3.first_column, 183 strdup("Bad modifier"), NULL); 184 free_list_evsel(list); 185 YYABORT; 186 } 187 $$ = list; 188 } 189 | 190 group_def 191 192 group_def: 193 PE_NAME '{' events '}' 194 { 195 struct list_head *list = $3; 196 197 /* Takes ownership of $1. */ 198 parse_events__set_leader($1, list); 199 $$ = list; 200 } 201 | 202 '{' events '}' 203 { 204 struct list_head *list = $2; 205 206 parse_events__set_leader(NULL, list); 207 $$ = list; 208 } 209 210 events: 211 events ',' event 212 { 213 struct list_head *event = $3; 214 struct list_head *list = $1; 215 216 /* frees $3 */ 217 parse_events_update_lists(event, list); 218 $$ = list; 219 } 220 | 221 event 222 223 event: event_mod 224 225 event_mod: 226 event_name PE_MODIFIER_EVENT 227 { 228 struct list_head *list = $1; 229 int err; 230 231 /* 232 * Apply modifier on all events added by single event definition 233 * (there could be more events added for multiple tracepoint 234 * definitions via '*?'. 235 */ 236 err = parse_events__modifier_event(list, $2, false); 237 free($2); 238 if (err) { 239 struct parse_events_state *parse_state = _parse_state; 240 struct parse_events_error *error = parse_state->error; 241 242 parse_events_error__handle(error, @2.first_column, 243 strdup("Bad modifier"), NULL); 244 free_list_evsel(list); 245 YYABORT; 246 } 247 $$ = list; 248 } 249 | 250 event_name 251 252 event_name: 253 PE_EVENT_NAME event_def 254 { 255 int err; 256 257 err = parse_events_name($2, $1); 258 free($1); 259 if (err) { 260 free_list_evsel($2); 261 YYNOMEM; 262 } 263 $$ = $2; 264 } 265 | 266 event_def 267 268 event_def: event_pmu | 269 event_legacy_symbol | 270 event_legacy_cache sep_dc | 271 event_legacy_mem sep_dc | 272 event_legacy_tracepoint sep_dc | 273 event_legacy_numeric sep_dc | 274 event_legacy_raw sep_dc | 275 event_bpf_file 276 277 event_pmu: 278 PE_NAME opt_pmu_config 279 { 280 struct parse_events_state *parse_state = _parse_state; 281 struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL; 282 char *pattern = NULL; 283 284 #define CLEANUP \ 285 do { \ 286 parse_events_terms__delete($2); \ 287 parse_events_terms__delete(orig_terms); \ 288 free(list); \ 289 free($1); \ 290 free(pattern); \ 291 } while(0) 292 293 if (parse_events_copy_term_list($2, &orig_terms)) { 294 CLEANUP; 295 YYNOMEM; 296 } 297 298 list = alloc_list(); 299 if (!list) { 300 CLEANUP; 301 YYNOMEM; 302 } 303 /* Attempt to add to list assuming $1 is a PMU name. */ 304 if (parse_events_add_pmu(parse_state, list, $1, $2, /*auto_merge_stats=*/false, &@1)) { 305 struct perf_pmu *pmu = NULL; 306 int ok = 0; 307 308 /* Failure to add, try wildcard expansion of $1 as a PMU name. */ 309 if (asprintf(&pattern, "%s*", $1) < 0) { 310 CLEANUP; 311 YYNOMEM; 312 } 313 314 while ((pmu = perf_pmus__scan(pmu)) != NULL) { 315 char *name = pmu->name; 316 317 if (parse_events__filter_pmu(parse_state, pmu)) 318 continue; 319 320 if (!strncmp(name, "uncore_", 7) && 321 strncmp($1, "uncore_", 7)) 322 name += 7; 323 if (!perf_pmu__match(pattern, name, $1) || 324 !perf_pmu__match(pattern, pmu->alias_name, $1)) { 325 bool auto_merge_stats = perf_pmu__auto_merge_stats(pmu); 326 327 if (parse_events_copy_term_list(orig_terms, &terms)) { 328 CLEANUP; 329 YYNOMEM; 330 } 331 if (!parse_events_add_pmu(parse_state, list, pmu->name, terms, 332 auto_merge_stats, &@1)) { 333 ok++; 334 parse_state->wild_card_pmus = true; 335 } 336 parse_events_terms__delete(terms); 337 } 338 } 339 340 if (!ok) { 341 /* Failure to add, assume $1 is an event name. */ 342 zfree(&list); 343 ok = !parse_events_multi_pmu_add(parse_state, $1, $2, &list, &@1); 344 $2 = NULL; 345 } 346 if (!ok) { 347 struct parse_events_error *error = parse_state->error; 348 char *help; 349 350 if (asprintf(&help, "Unabled to find PMU or event on a PMU of '%s'", $1) < 0) 351 help = NULL; 352 parse_events_error__handle(error, @1.first_column, 353 strdup("Bad event or PMU"), 354 help); 355 CLEANUP; 356 YYABORT; 357 } 358 } 359 $$ = list; 360 list = NULL; 361 CLEANUP; 362 #undef CLEANUP 363 } 364 | 365 PE_NAME sep_dc 366 { 367 struct list_head *list; 368 int err; 369 370 err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1); 371 if (err < 0) { 372 struct parse_events_state *parse_state = _parse_state; 373 struct parse_events_error *error = parse_state->error; 374 char *help; 375 376 if (asprintf(&help, "Unabled to find PMU or event on a PMU of '%s'", $1) < 0) 377 help = NULL; 378 parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help); 379 free($1); 380 PE_ABORT(err); 381 } 382 free($1); 383 $$ = list; 384 } 385 386 value_sym: 387 PE_VALUE_SYM_HW 388 | 389 PE_VALUE_SYM_SW 390 391 event_legacy_symbol: 392 value_sym '/' event_config '/' 393 { 394 struct list_head *list; 395 int type = $1 >> 16; 396 int config = $1 & 255; 397 int err; 398 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 399 400 list = alloc_list(); 401 if (!list) 402 YYNOMEM; 403 err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard); 404 parse_events_terms__delete($3); 405 if (err) { 406 free_list_evsel(list); 407 PE_ABORT(err); 408 } 409 $$ = list; 410 } 411 | 412 value_sym sep_slash_slash_dc 413 { 414 struct list_head *list; 415 int type = $1 >> 16; 416 int config = $1 & 255; 417 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 418 int err; 419 420 list = alloc_list(); 421 if (!list) 422 YYNOMEM; 423 err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard); 424 if (err) 425 PE_ABORT(err); 426 $$ = list; 427 } 428 | 429 PE_VALUE_SYM_TOOL sep_slash_slash_dc 430 { 431 struct list_head *list; 432 int err; 433 434 list = alloc_list(); 435 if (!list) 436 YYNOMEM; 437 err = parse_events_add_tool(_parse_state, list, $1); 438 if (err) 439 YYNOMEM; 440 $$ = list; 441 } 442 443 event_legacy_cache: 444 PE_LEGACY_CACHE opt_event_config 445 { 446 struct parse_events_state *parse_state = _parse_state; 447 struct list_head *list; 448 int err; 449 450 list = alloc_list(); 451 if (!list) 452 YYNOMEM; 453 454 err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2); 455 456 parse_events_terms__delete($2); 457 free($1); 458 if (err) { 459 free_list_evsel(list); 460 PE_ABORT(err); 461 } 462 $$ = list; 463 } 464 465 event_legacy_mem: 466 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config 467 { 468 struct list_head *list; 469 int err; 470 471 list = alloc_list(); 472 if (!list) 473 YYNOMEM; 474 475 err = parse_events_add_breakpoint(_parse_state, list, 476 $2, $6, $4, $7); 477 parse_events_terms__delete($7); 478 free($6); 479 if (err) { 480 free(list); 481 PE_ABORT(err); 482 } 483 $$ = list; 484 } 485 | 486 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config 487 { 488 struct list_head *list; 489 int err; 490 491 list = alloc_list(); 492 if (!list) 493 YYNOMEM; 494 495 err = parse_events_add_breakpoint(_parse_state, list, 496 $2, NULL, $4, $5); 497 parse_events_terms__delete($5); 498 if (err) { 499 free(list); 500 PE_ABORT(err); 501 } 502 $$ = list; 503 } 504 | 505 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config 506 { 507 struct list_head *list; 508 int err; 509 510 list = alloc_list(); 511 if (!list) 512 YYNOMEM; 513 514 err = parse_events_add_breakpoint(_parse_state, list, 515 $2, $4, 0, $5); 516 parse_events_terms__delete($5); 517 free($4); 518 if (err) { 519 free(list); 520 PE_ABORT(err); 521 } 522 $$ = list; 523 } 524 | 525 PE_PREFIX_MEM PE_VALUE opt_event_config 526 { 527 struct list_head *list; 528 int err; 529 530 list = alloc_list(); 531 if (!list) 532 YYNOMEM; 533 err = parse_events_add_breakpoint(_parse_state, list, 534 $2, NULL, 0, $3); 535 parse_events_terms__delete($3); 536 if (err) { 537 free(list); 538 PE_ABORT(err); 539 } 540 $$ = list; 541 } 542 543 event_legacy_tracepoint: 544 tracepoint_name opt_event_config 545 { 546 struct parse_events_state *parse_state = _parse_state; 547 struct parse_events_error *error = parse_state->error; 548 struct list_head *list; 549 int err; 550 551 list = alloc_list(); 552 if (!list) 553 YYNOMEM; 554 if (error) 555 error->idx = @1.first_column; 556 557 err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event, 558 error, $2, &@1); 559 560 parse_events_terms__delete($2); 561 free($1.sys); 562 free($1.event); 563 if (err) { 564 free(list); 565 PE_ABORT(err); 566 } 567 $$ = list; 568 } 569 570 tracepoint_name: 571 PE_NAME ':' PE_NAME 572 { 573 struct tracepoint_name tracepoint = {$1, $3}; 574 575 $$ = tracepoint; 576 } 577 578 event_legacy_numeric: 579 PE_VALUE ':' PE_VALUE opt_event_config 580 { 581 struct list_head *list; 582 int err; 583 584 list = alloc_list(); 585 if (!list) 586 YYNOMEM; 587 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4, 588 /*wildcard=*/false); 589 parse_events_terms__delete($4); 590 if (err) { 591 free(list); 592 PE_ABORT(err); 593 } 594 $$ = list; 595 } 596 597 event_legacy_raw: 598 PE_RAW opt_event_config 599 { 600 struct list_head *list; 601 int err; 602 u64 num; 603 604 list = alloc_list(); 605 if (!list) 606 YYNOMEM; 607 errno = 0; 608 num = strtoull($1 + 1, NULL, 16); 609 /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */ 610 if (errno) 611 YYABORT; 612 free($1); 613 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2, 614 /*wildcard=*/false); 615 parse_events_terms__delete($2); 616 if (err) { 617 free(list); 618 PE_ABORT(err); 619 } 620 $$ = list; 621 } 622 623 event_bpf_file: 624 PE_BPF_OBJECT opt_event_config 625 { 626 struct parse_events_state *parse_state = _parse_state; 627 struct list_head *list; 628 int err; 629 630 list = alloc_list(); 631 if (!list) 632 YYNOMEM; 633 err = parse_events_load_bpf(parse_state, list, $1, false, $2, &@1); 634 parse_events_terms__delete($2); 635 free($1); 636 if (err) { 637 free(list); 638 PE_ABORT(err); 639 } 640 $$ = list; 641 } 642 | 643 PE_BPF_SOURCE opt_event_config 644 { 645 struct list_head *list; 646 int err; 647 648 list = alloc_list(); 649 if (!list) 650 YYNOMEM; 651 err = parse_events_load_bpf(_parse_state, list, $1, true, $2, &@1); 652 parse_events_terms__delete($2); 653 if (err) { 654 free(list); 655 PE_ABORT(err); 656 } 657 $$ = list; 658 } 659 660 opt_event_config: 661 '/' event_config '/' 662 { 663 $$ = $2; 664 } 665 | 666 '/' '/' 667 { 668 $$ = NULL; 669 } 670 | 671 { 672 $$ = NULL; 673 } 674 675 opt_pmu_config: 676 '/' event_config '/' 677 { 678 $$ = $2; 679 } 680 | 681 '/' '/' 682 { 683 $$ = NULL; 684 } 685 686 start_terms: event_config 687 { 688 struct parse_events_state *parse_state = _parse_state; 689 if (parse_state->terms) { 690 parse_events_terms__delete ($1); 691 YYABORT; 692 } 693 parse_state->terms = $1; 694 } 695 696 event_config: 697 event_config ',' event_term 698 { 699 struct list_head *head = $1; 700 struct parse_events_term *term = $3; 701 702 if (!head) { 703 parse_events_term__delete(term); 704 YYABORT; 705 } 706 list_add_tail(&term->list, head); 707 $$ = $1; 708 } 709 | 710 event_term 711 { 712 struct list_head *head = malloc(sizeof(*head)); 713 struct parse_events_term *term = $1; 714 715 if (!head) 716 YYNOMEM; 717 INIT_LIST_HEAD(head); 718 list_add_tail(&term->list, head); 719 $$ = head; 720 } 721 722 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE 723 724 name_or_legacy: PE_NAME | PE_LEGACY_CACHE 725 726 event_term: 727 PE_RAW 728 { 729 struct parse_events_term *term; 730 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW, 731 strdup("raw"), $1, &@1, &@1); 732 733 if (err) { 734 free($1); 735 PE_ABORT(err); 736 } 737 $$ = term; 738 } 739 | 740 name_or_raw '=' name_or_legacy 741 { 742 struct parse_events_term *term; 743 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3); 744 745 if (err) { 746 free($1); 747 free($3); 748 PE_ABORT(err); 749 } 750 $$ = term; 751 } 752 | 753 name_or_raw '=' PE_VALUE 754 { 755 struct parse_events_term *term; 756 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 757 $1, $3, false, &@1, &@3); 758 759 if (err) { 760 free($1); 761 PE_ABORT(err); 762 } 763 $$ = term; 764 } 765 | 766 name_or_raw '=' PE_TERM_HW 767 { 768 struct parse_events_term *term; 769 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 770 $1, $3.str, &@1, &@3); 771 772 if (err) { 773 free($1); 774 free($3.str); 775 PE_ABORT(err); 776 } 777 $$ = term; 778 } 779 | 780 PE_LEGACY_CACHE 781 { 782 struct parse_events_term *term; 783 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE, 784 $1, 1, true, &@1, NULL); 785 786 if (err) { 787 free($1); 788 PE_ABORT(err); 789 } 790 $$ = term; 791 } 792 | 793 PE_NAME 794 { 795 struct parse_events_term *term; 796 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 797 $1, 1, true, &@1, NULL); 798 799 if (err) { 800 free($1); 801 PE_ABORT(err); 802 } 803 $$ = term; 804 } 805 | 806 PE_TERM_HW 807 { 808 struct parse_events_term *term; 809 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE, 810 $1.str, $1.num & 255, false, &@1, NULL); 811 812 if (err) { 813 free($1.str); 814 PE_ABORT(err); 815 } 816 $$ = term; 817 } 818 | 819 PE_TERM '=' name_or_legacy 820 { 821 struct parse_events_term *term; 822 int err = parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3); 823 824 if (err) { 825 free($3); 826 PE_ABORT(err); 827 } 828 $$ = term; 829 } 830 | 831 PE_TERM '=' PE_TERM_HW 832 { 833 struct parse_events_term *term; 834 int err = parse_events_term__str(&term, (int)$1, NULL, $3.str, &@1, &@3); 835 836 if (err) { 837 free($3.str); 838 PE_ABORT(err); 839 } 840 $$ = term; 841 } 842 | 843 PE_TERM '=' PE_TERM 844 { 845 struct parse_events_term *term; 846 int err = parse_events_term__term(&term, (int)$1, (int)$3, &@1, &@3); 847 848 if (err) 849 PE_ABORT(err); 850 851 $$ = term; 852 } 853 | 854 PE_TERM '=' PE_VALUE 855 { 856 struct parse_events_term *term; 857 int err = parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3); 858 859 if (err) 860 PE_ABORT(err); 861 862 $$ = term; 863 } 864 | 865 PE_TERM 866 { 867 struct parse_events_term *term; 868 int err = parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL); 869 870 if (err) 871 PE_ABORT(err); 872 873 $$ = term; 874 } 875 876 sep_dc: ':' | 877 878 sep_slash_slash_dc: '/' '/' | ':' | 879 880 %% 881 882 void parse_events_error(YYLTYPE *loc, void *parse_state, 883 void *scanner __maybe_unused, 884 char const *msg __maybe_unused) 885 { 886 parse_events_evlist_error(parse_state, loc->last_column, "parser error"); 887 } 888