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_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH 64 %token PE_LEGACY_CACHE 65 %token PE_PREFIX_MEM 66 %token PE_ERROR 67 %token PE_DRV_CFG_TERM 68 %token PE_TERM_HW 69 %type <num> PE_VALUE 70 %type <num> PE_VALUE_SYM_HW 71 %type <num> PE_VALUE_SYM_SW 72 %type <num> PE_VALUE_SYM_TOOL 73 %type <num> PE_TERM 74 %type <num> value_sym 75 %type <str> PE_RAW 76 %type <str> PE_NAME 77 %type <str> PE_LEGACY_CACHE 78 %type <str> PE_MODIFIER_EVENT 79 %type <str> PE_MODIFIER_BP 80 %type <str> PE_EVENT_NAME 81 %type <str> PE_DRV_CFG_TERM 82 %type <str> name_or_raw 83 %destructor { free ($$); } <str> 84 %type <term> event_term 85 %destructor { parse_events_term__delete ($$); } <term> 86 %type <list_terms> event_config 87 %type <list_terms> opt_event_config 88 %type <list_terms> opt_pmu_config 89 %destructor { parse_events_terms__delete ($$); } <list_terms> 90 %type <list_evsel> event_pmu 91 %type <list_evsel> event_legacy_symbol 92 %type <list_evsel> event_legacy_cache 93 %type <list_evsel> event_legacy_mem 94 %type <list_evsel> event_legacy_tracepoint 95 %type <list_evsel> event_legacy_numeric 96 %type <list_evsel> event_legacy_raw 97 %type <list_evsel> event_def 98 %type <list_evsel> event_mod 99 %type <list_evsel> event_name 100 %type <list_evsel> event 101 %type <list_evsel> events 102 %type <list_evsel> group_def 103 %type <list_evsel> group 104 %type <list_evsel> groups 105 %destructor { free_list_evsel ($$); } <list_evsel> 106 %type <tracepoint_name> tracepoint_name 107 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name> 108 %type <hardware_term> PE_TERM_HW 109 %destructor { free ($$.str); } <hardware_term> 110 111 %union 112 { 113 char *str; 114 u64 num; 115 struct list_head *list_evsel; 116 struct list_head *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 struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL; 278 char *pattern = NULL; 279 280 #define CLEANUP \ 281 do { \ 282 parse_events_terms__delete($2); \ 283 parse_events_terms__delete(orig_terms); \ 284 free(list); \ 285 free($1); \ 286 free(pattern); \ 287 } while(0) 288 289 if (parse_events_copy_term_list($2, &orig_terms)) { 290 CLEANUP; 291 YYNOMEM; 292 } 293 294 list = alloc_list(); 295 if (!list) { 296 CLEANUP; 297 YYNOMEM; 298 } 299 /* Attempt to add to list assuming $1 is a PMU name. */ 300 if (parse_events_add_pmu(parse_state, list, $1, $2, /*auto_merge_stats=*/false, &@1)) { 301 struct perf_pmu *pmu = NULL; 302 int ok = 0; 303 304 /* Failure to add, try wildcard expansion of $1 as a PMU name. */ 305 if (asprintf(&pattern, "%s*", $1) < 0) { 306 CLEANUP; 307 YYNOMEM; 308 } 309 310 while ((pmu = perf_pmus__scan(pmu)) != NULL) { 311 const char *name = pmu->name; 312 313 if (parse_events__filter_pmu(parse_state, pmu)) 314 continue; 315 316 if (!strncmp(name, "uncore_", 7) && 317 strncmp($1, "uncore_", 7)) 318 name += 7; 319 if (!perf_pmu__match(pattern, name, $1) || 320 !perf_pmu__match(pattern, pmu->alias_name, $1)) { 321 bool auto_merge_stats = perf_pmu__auto_merge_stats(pmu); 322 323 if (parse_events_copy_term_list(orig_terms, &terms)) { 324 CLEANUP; 325 YYNOMEM; 326 } 327 if (!parse_events_add_pmu(parse_state, list, pmu->name, terms, 328 auto_merge_stats, &@1)) { 329 ok++; 330 parse_state->wild_card_pmus = true; 331 } 332 parse_events_terms__delete(terms); 333 } 334 } 335 336 if (!ok) { 337 /* Failure to add, assume $1 is an event name. */ 338 zfree(&list); 339 ok = !parse_events_multi_pmu_add(parse_state, $1, $2, &list, &@1); 340 $2 = NULL; 341 } 342 if (!ok) { 343 struct parse_events_error *error = parse_state->error; 344 char *help; 345 346 if (asprintf(&help, "Unable to find PMU or event on a PMU of '%s'", $1) < 0) 347 help = NULL; 348 parse_events_error__handle(error, @1.first_column, 349 strdup("Bad event or PMU"), 350 help); 351 CLEANUP; 352 YYABORT; 353 } 354 } 355 $$ = list; 356 list = NULL; 357 CLEANUP; 358 #undef CLEANUP 359 } 360 | 361 PE_NAME sep_dc 362 { 363 struct list_head *list; 364 int err; 365 366 err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1); 367 if (err < 0) { 368 struct parse_events_state *parse_state = _parse_state; 369 struct parse_events_error *error = parse_state->error; 370 char *help; 371 372 if (asprintf(&help, "Unable to find event on a PMU of '%s'", $1) < 0) 373 help = NULL; 374 parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help); 375 free($1); 376 PE_ABORT(err); 377 } 378 free($1); 379 $$ = list; 380 } 381 382 value_sym: 383 PE_VALUE_SYM_HW 384 | 385 PE_VALUE_SYM_SW 386 387 event_legacy_symbol: 388 value_sym '/' event_config '/' 389 { 390 struct list_head *list; 391 int type = $1 >> 16; 392 int config = $1 & 255; 393 int err; 394 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 395 396 list = alloc_list(); 397 if (!list) 398 YYNOMEM; 399 err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard); 400 parse_events_terms__delete($3); 401 if (err) { 402 free_list_evsel(list); 403 PE_ABORT(err); 404 } 405 $$ = list; 406 } 407 | 408 value_sym sep_slash_slash_dc 409 { 410 struct list_head *list; 411 int type = $1 >> 16; 412 int config = $1 & 255; 413 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 414 int err; 415 416 list = alloc_list(); 417 if (!list) 418 YYNOMEM; 419 err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard); 420 if (err) 421 PE_ABORT(err); 422 $$ = list; 423 } 424 | 425 PE_VALUE_SYM_TOOL sep_slash_slash_dc 426 { 427 struct list_head *list; 428 int err; 429 430 list = alloc_list(); 431 if (!list) 432 YYNOMEM; 433 err = parse_events_add_tool(_parse_state, list, $1); 434 if (err) 435 YYNOMEM; 436 $$ = list; 437 } 438 439 event_legacy_cache: 440 PE_LEGACY_CACHE opt_event_config 441 { 442 struct parse_events_state *parse_state = _parse_state; 443 struct list_head *list; 444 int err; 445 446 list = alloc_list(); 447 if (!list) 448 YYNOMEM; 449 450 err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2); 451 452 parse_events_terms__delete($2); 453 free($1); 454 if (err) { 455 free_list_evsel(list); 456 PE_ABORT(err); 457 } 458 $$ = list; 459 } 460 461 event_legacy_mem: 462 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config 463 { 464 struct list_head *list; 465 int err; 466 467 list = alloc_list(); 468 if (!list) 469 YYNOMEM; 470 471 err = parse_events_add_breakpoint(_parse_state, list, 472 $2, $6, $4, $7); 473 parse_events_terms__delete($7); 474 free($6); 475 if (err) { 476 free(list); 477 PE_ABORT(err); 478 } 479 $$ = list; 480 } 481 | 482 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config 483 { 484 struct list_head *list; 485 int err; 486 487 list = alloc_list(); 488 if (!list) 489 YYNOMEM; 490 491 err = parse_events_add_breakpoint(_parse_state, list, 492 $2, NULL, $4, $5); 493 parse_events_terms__delete($5); 494 if (err) { 495 free(list); 496 PE_ABORT(err); 497 } 498 $$ = list; 499 } 500 | 501 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config 502 { 503 struct list_head *list; 504 int err; 505 506 list = alloc_list(); 507 if (!list) 508 YYNOMEM; 509 510 err = parse_events_add_breakpoint(_parse_state, list, 511 $2, $4, 0, $5); 512 parse_events_terms__delete($5); 513 free($4); 514 if (err) { 515 free(list); 516 PE_ABORT(err); 517 } 518 $$ = list; 519 } 520 | 521 PE_PREFIX_MEM PE_VALUE opt_event_config 522 { 523 struct list_head *list; 524 int err; 525 526 list = alloc_list(); 527 if (!list) 528 YYNOMEM; 529 err = parse_events_add_breakpoint(_parse_state, list, 530 $2, NULL, 0, $3); 531 parse_events_terms__delete($3); 532 if (err) { 533 free(list); 534 PE_ABORT(err); 535 } 536 $$ = list; 537 } 538 539 event_legacy_tracepoint: 540 tracepoint_name opt_event_config 541 { 542 struct parse_events_state *parse_state = _parse_state; 543 struct parse_events_error *error = parse_state->error; 544 struct list_head *list; 545 int err; 546 547 list = alloc_list(); 548 if (!list) 549 YYNOMEM; 550 if (error) 551 error->idx = @1.first_column; 552 553 err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event, 554 error, $2, &@1); 555 556 parse_events_terms__delete($2); 557 free($1.sys); 558 free($1.event); 559 if (err) { 560 free(list); 561 PE_ABORT(err); 562 } 563 $$ = list; 564 } 565 566 tracepoint_name: 567 PE_NAME ':' PE_NAME 568 { 569 struct tracepoint_name tracepoint = {$1, $3}; 570 571 $$ = tracepoint; 572 } 573 574 event_legacy_numeric: 575 PE_VALUE ':' PE_VALUE opt_event_config 576 { 577 struct list_head *list; 578 int err; 579 580 list = alloc_list(); 581 if (!list) 582 YYNOMEM; 583 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4, 584 /*wildcard=*/false); 585 parse_events_terms__delete($4); 586 if (err) { 587 free(list); 588 PE_ABORT(err); 589 } 590 $$ = list; 591 } 592 593 event_legacy_raw: 594 PE_RAW opt_event_config 595 { 596 struct list_head *list; 597 int err; 598 u64 num; 599 600 list = alloc_list(); 601 if (!list) 602 YYNOMEM; 603 errno = 0; 604 num = strtoull($1 + 1, NULL, 16); 605 /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */ 606 if (errno) 607 YYABORT; 608 free($1); 609 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2, 610 /*wildcard=*/false); 611 parse_events_terms__delete($2); 612 if (err) { 613 free(list); 614 PE_ABORT(err); 615 } 616 $$ = list; 617 } 618 619 opt_event_config: 620 '/' event_config '/' 621 { 622 $$ = $2; 623 } 624 | 625 '/' '/' 626 { 627 $$ = NULL; 628 } 629 | 630 { 631 $$ = NULL; 632 } 633 634 opt_pmu_config: 635 '/' event_config '/' 636 { 637 $$ = $2; 638 } 639 | 640 '/' '/' 641 { 642 $$ = NULL; 643 } 644 645 start_terms: event_config 646 { 647 struct parse_events_state *parse_state = _parse_state; 648 if (parse_state->terms) { 649 parse_events_terms__delete ($1); 650 YYABORT; 651 } 652 parse_state->terms = $1; 653 } 654 655 event_config: 656 event_config ',' event_term 657 { 658 struct list_head *head = $1; 659 struct parse_events_term *term = $3; 660 661 if (!head) { 662 parse_events_term__delete(term); 663 YYABORT; 664 } 665 list_add_tail(&term->list, head); 666 $$ = $1; 667 } 668 | 669 event_term 670 { 671 struct list_head *head = malloc(sizeof(*head)); 672 struct parse_events_term *term = $1; 673 674 if (!head) 675 YYNOMEM; 676 INIT_LIST_HEAD(head); 677 list_add_tail(&term->list, head); 678 $$ = head; 679 } 680 681 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE 682 683 event_term: 684 PE_RAW 685 { 686 struct parse_events_term *term; 687 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW, 688 strdup("raw"), $1, &@1, &@1); 689 690 if (err) { 691 free($1); 692 PE_ABORT(err); 693 } 694 $$ = term; 695 } 696 | 697 name_or_raw '=' name_or_raw 698 { 699 struct parse_events_term *term; 700 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3); 701 702 if (err) { 703 free($1); 704 free($3); 705 PE_ABORT(err); 706 } 707 $$ = term; 708 } 709 | 710 name_or_raw '=' PE_VALUE 711 { 712 struct parse_events_term *term; 713 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 714 $1, $3, /*novalue=*/false, &@1, &@3); 715 716 if (err) { 717 free($1); 718 PE_ABORT(err); 719 } 720 $$ = term; 721 } 722 | 723 name_or_raw '=' PE_TERM_HW 724 { 725 struct parse_events_term *term; 726 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 727 $1, $3.str, &@1, &@3); 728 729 if (err) { 730 free($1); 731 free($3.str); 732 PE_ABORT(err); 733 } 734 $$ = term; 735 } 736 | 737 PE_LEGACY_CACHE 738 { 739 struct parse_events_term *term; 740 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE, 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_NAME 751 { 752 struct parse_events_term *term; 753 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 754 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL); 755 756 if (err) { 757 free($1); 758 PE_ABORT(err); 759 } 760 $$ = term; 761 } 762 | 763 PE_TERM_HW 764 { 765 struct parse_events_term *term; 766 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE, 767 $1.str, $1.num & 255, /*novalue=*/false, 768 &@1, /*loc_val=*/NULL); 769 770 if (err) { 771 free($1.str); 772 PE_ABORT(err); 773 } 774 $$ = term; 775 } 776 | 777 PE_TERM '=' name_or_raw 778 { 779 struct parse_events_term *term; 780 int err = parse_events_term__str(&term, (enum parse_events__term_type)$1, 781 /*config=*/NULL, $3, &@1, &@3); 782 783 if (err) { 784 free($3); 785 PE_ABORT(err); 786 } 787 $$ = term; 788 } 789 | 790 PE_TERM '=' PE_TERM_HW 791 { 792 struct parse_events_term *term; 793 int err = parse_events_term__str(&term, (enum parse_events__term_type)$1, 794 /*config=*/NULL, $3.str, &@1, &@3); 795 796 if (err) { 797 free($3.str); 798 PE_ABORT(err); 799 } 800 $$ = term; 801 } 802 | 803 PE_TERM '=' PE_TERM 804 { 805 struct parse_events_term *term; 806 int err = parse_events_term__term(&term, 807 (enum parse_events__term_type)$1, 808 (enum parse_events__term_type)$3, 809 &@1, &@3); 810 811 if (err) 812 PE_ABORT(err); 813 814 $$ = term; 815 } 816 | 817 PE_TERM '=' PE_VALUE 818 { 819 struct parse_events_term *term; 820 int err = parse_events_term__num(&term, (enum parse_events__term_type)$1, 821 /*config=*/NULL, $3, /*novalue=*/false, &@1, &@3); 822 823 if (err) 824 PE_ABORT(err); 825 826 $$ = term; 827 } 828 | 829 PE_TERM 830 { 831 struct parse_events_term *term; 832 int err = parse_events_term__num(&term, (enum parse_events__term_type)$1, 833 /*config=*/NULL, /*num=*/1, /*novalue=*/true, 834 &@1, /*loc_val=*/NULL); 835 836 if (err) 837 PE_ABORT(err); 838 839 $$ = term; 840 } 841 | 842 PE_DRV_CFG_TERM 843 { 844 struct parse_events_term *term; 845 char *config = strdup($1); 846 int err; 847 848 if (!config) 849 YYNOMEM; 850 err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL); 851 if (err) { 852 free($1); 853 free(config); 854 PE_ABORT(err); 855 } 856 $$ = term; 857 } 858 859 sep_dc: ':' | 860 861 sep_slash_slash_dc: '/' '/' | ':' | 862 863 %% 864 865 void parse_events_error(YYLTYPE *loc, void *parse_state, 866 void *scanner __maybe_unused, 867 char const *msg __maybe_unused) 868 { 869 parse_events_evlist_error(parse_state, loc->last_column, "parser error"); 870 } 871