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