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 540 err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event, 541 error, $2, &@1); 542 543 parse_events_terms__delete($2); 544 free($1.sys); 545 free($1.event); 546 if (err) { 547 free(list); 548 PE_ABORT(err); 549 } 550 $$ = list; 551 } 552 553 tracepoint_name: 554 PE_NAME ':' PE_NAME 555 { 556 struct tracepoint_name tracepoint = {$1, $3}; 557 558 $$ = tracepoint; 559 } 560 561 event_legacy_numeric: 562 PE_VALUE ':' PE_VALUE opt_event_config 563 { 564 struct list_head *list; 565 int err; 566 567 list = alloc_list(); 568 if (!list) 569 YYNOMEM; 570 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4, 571 /*wildcard=*/false); 572 parse_events_terms__delete($4); 573 if (err) { 574 free(list); 575 PE_ABORT(err); 576 } 577 $$ = list; 578 } 579 580 event_legacy_raw: 581 PE_RAW opt_event_config 582 { 583 struct list_head *list; 584 int err; 585 u64 num; 586 587 list = alloc_list(); 588 if (!list) 589 YYNOMEM; 590 errno = 0; 591 num = strtoull($1 + 1, NULL, 16); 592 /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */ 593 if (errno) 594 YYABORT; 595 free($1); 596 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2, 597 /*wildcard=*/false); 598 parse_events_terms__delete($2); 599 if (err) { 600 free(list); 601 PE_ABORT(err); 602 } 603 $$ = list; 604 } 605 606 opt_event_config: 607 '/' event_config '/' 608 { 609 $$ = $2; 610 } 611 | 612 '/' '/' 613 { 614 $$ = NULL; 615 } 616 | 617 { 618 $$ = NULL; 619 } 620 621 opt_pmu_config: 622 '/' event_config '/' 623 { 624 $$ = $2; 625 } 626 | 627 '/' '/' 628 { 629 $$ = NULL; 630 } 631 632 start_terms: event_config 633 { 634 struct parse_events_state *parse_state = _parse_state; 635 if (parse_state->terms) { 636 parse_events_terms__delete ($1); 637 YYABORT; 638 } 639 parse_state->terms = $1; 640 } 641 642 event_config: 643 event_config ',' event_term 644 { 645 struct parse_events_terms *head = $1; 646 struct parse_events_term *term = $3; 647 648 if (!head) { 649 parse_events_term__delete(term); 650 YYABORT; 651 } 652 list_add_tail(&term->list, &head->terms); 653 $$ = $1; 654 } 655 | 656 event_term 657 { 658 struct parse_events_terms *head = malloc(sizeof(*head)); 659 struct parse_events_term *term = $1; 660 661 if (!head) 662 YYNOMEM; 663 parse_events_terms__init(head); 664 list_add_tail(&term->list, &head->terms); 665 $$ = head; 666 } 667 668 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE 669 670 event_term: 671 PE_RAW 672 { 673 struct parse_events_term *term; 674 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW, 675 strdup("raw"), $1, &@1, &@1); 676 677 if (err) { 678 free($1); 679 PE_ABORT(err); 680 } 681 $$ = term; 682 } 683 | 684 name_or_raw '=' name_or_raw 685 { 686 struct parse_events_term *term; 687 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3); 688 689 if (err) { 690 free($1); 691 free($3); 692 PE_ABORT(err); 693 } 694 $$ = term; 695 } 696 | 697 name_or_raw '=' PE_VALUE 698 { 699 struct parse_events_term *term; 700 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 701 $1, $3, /*novalue=*/false, &@1, &@3); 702 703 if (err) { 704 free($1); 705 PE_ABORT(err); 706 } 707 $$ = term; 708 } 709 | 710 name_or_raw '=' PE_TERM_HW 711 { 712 struct parse_events_term *term; 713 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 714 $1, $3.str, &@1, &@3); 715 716 if (err) { 717 free($1); 718 free($3.str); 719 PE_ABORT(err); 720 } 721 $$ = term; 722 } 723 | 724 PE_LEGACY_CACHE 725 { 726 struct parse_events_term *term; 727 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE, 728 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL); 729 730 if (err) { 731 free($1); 732 PE_ABORT(err); 733 } 734 $$ = term; 735 } 736 | 737 PE_NAME 738 { 739 struct parse_events_term *term; 740 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 741 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL); 742 743 if (err) { 744 free($1); 745 PE_ABORT(err); 746 } 747 $$ = term; 748 } 749 | 750 PE_TERM_HW 751 { 752 struct parse_events_term *term; 753 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE, 754 $1.str, $1.num & 255, /*novalue=*/false, 755 &@1, /*loc_val=*/NULL); 756 757 if (err) { 758 free($1.str); 759 PE_ABORT(err); 760 } 761 $$ = term; 762 } 763 | 764 PE_TERM '=' name_or_raw 765 { 766 struct parse_events_term *term; 767 int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3); 768 769 if (err) { 770 free($3); 771 PE_ABORT(err); 772 } 773 $$ = term; 774 } 775 | 776 PE_TERM '=' PE_TERM_HW 777 { 778 struct parse_events_term *term; 779 int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3.str, &@1, &@3); 780 781 if (err) { 782 free($3.str); 783 PE_ABORT(err); 784 } 785 $$ = term; 786 } 787 | 788 PE_TERM '=' PE_TERM 789 { 790 struct parse_events_term *term; 791 int err = parse_events_term__term(&term, $1, $3, &@1, &@3); 792 793 if (err) 794 PE_ABORT(err); 795 796 $$ = term; 797 } 798 | 799 PE_TERM '=' PE_VALUE 800 { 801 struct parse_events_term *term; 802 int err = parse_events_term__num(&term, $1, 803 /*config=*/NULL, $3, /*novalue=*/false, 804 &@1, &@3); 805 806 if (err) 807 PE_ABORT(err); 808 809 $$ = term; 810 } 811 | 812 PE_TERM 813 { 814 struct parse_events_term *term; 815 int err = parse_events_term__num(&term, $1, 816 /*config=*/NULL, /*num=*/1, /*novalue=*/true, 817 &@1, /*loc_val=*/NULL); 818 819 if (err) 820 PE_ABORT(err); 821 822 $$ = term; 823 } 824 | 825 PE_DRV_CFG_TERM 826 { 827 struct parse_events_term *term; 828 char *config = strdup($1); 829 int err; 830 831 if (!config) 832 YYNOMEM; 833 err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL); 834 if (err) { 835 free($1); 836 free(config); 837 PE_ABORT(err); 838 } 839 $$ = term; 840 } 841 842 sep_dc: ':' | 843 844 sep_slash_slash_dc: '/' '/' | ':' | 845 846 %% 847 848 void parse_events_error(YYLTYPE *loc, void *parse_state, 849 void *scanner __maybe_unused, 850 char const *msg __maybe_unused) 851 { 852 parse_events_evlist_error(parse_state, loc->last_column, "parser error"); 853 } 854