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