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