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 23int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner); 24void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg); 25 26#define PE_ABORT(val) \ 27do { \ 28 if (val == -ENOMEM) \ 29 YYNOMEM; \ 30 YYABORT; \ 31} while (0) 32 33static 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 45static 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 129start: 130PE_START_EVENTS start_events 131| 132PE_START_TERMS start_terms 133 134start_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 142groups: 143groups ',' 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| 153groups ',' 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| 163group 164| 165event 166 167group: 168group_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| 187group_def 188 189group_def: 190PE_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 207events: 208events ',' 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| 218event 219 220event: event_mod 221 222event_mod: 223event_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| 247event_name 248 249event_name: 250PE_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| 263event_def 264 265event_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 273event_pmu: 274PE_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| 361PE_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 382value_sym: 383PE_VALUE_SYM_HW 384| 385PE_VALUE_SYM_SW 386 387event_legacy_symbol: 388value_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| 408value_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| 425PE_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 439event_legacy_cache: 440PE_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 461event_legacy_mem: 462PE_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| 482PE_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| 501PE_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| 521PE_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 539event_legacy_tracepoint: 540tracepoint_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 566tracepoint_name: 567PE_NAME ':' PE_NAME 568{ 569 struct tracepoint_name tracepoint = {$1, $3}; 570 571 $$ = tracepoint; 572} 573 574event_legacy_numeric: 575PE_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 593event_legacy_raw: 594PE_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 619opt_event_config: 620'/' event_config '/' 621{ 622 $$ = $2; 623} 624| 625'/' '/' 626{ 627 $$ = NULL; 628} 629| 630{ 631 $$ = NULL; 632} 633 634opt_pmu_config: 635'/' event_config '/' 636{ 637 $$ = $2; 638} 639| 640'/' '/' 641{ 642 $$ = NULL; 643} 644 645start_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 655event_config: 656event_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| 669event_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 681name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE 682 683event_term: 684PE_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| 697name_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| 710name_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| 723name_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| 737PE_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| 750PE_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| 763PE_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| 777PE_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| 790PE_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| 803PE_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| 817PE_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| 829PE_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| 842PE_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 859sep_dc: ':' | 860 861sep_slash_slash_dc: '/' '/' | ':' | 862 863%% 864 865void 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