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