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