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 PE_TERM_HW 608 { 609 $$ = $1.str; 610 } 611 612 event_term: 613 PE_RAW 614 { 615 struct parse_events_term *term; 616 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW, 617 strdup("raw"), $1, &@1, &@1); 618 619 if (err) { 620 free($1); 621 PE_ABORT(err); 622 } 623 $$ = term; 624 } 625 | 626 name_or_raw '=' name_or_raw 627 { 628 struct parse_events_term *term; 629 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3); 630 631 if (err) { 632 free($1); 633 free($3); 634 PE_ABORT(err); 635 } 636 $$ = term; 637 } 638 | 639 name_or_raw '=' PE_VALUE 640 { 641 struct parse_events_term *term; 642 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 643 $1, $3, /*novalue=*/false, &@1, &@3); 644 645 if (err) { 646 free($1); 647 PE_ABORT(err); 648 } 649 $$ = term; 650 } 651 | 652 PE_LEGACY_CACHE 653 { 654 struct parse_events_term *term; 655 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE, 656 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL); 657 658 if (err) { 659 free($1); 660 PE_ABORT(err); 661 } 662 $$ = term; 663 } 664 | 665 PE_NAME 666 { 667 struct parse_events_term *term; 668 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 669 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL); 670 671 if (err) { 672 free($1); 673 PE_ABORT(err); 674 } 675 $$ = term; 676 } 677 | 678 PE_TERM_HW 679 { 680 struct parse_events_term *term; 681 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE, 682 $1.str, $1.num & 255, /*novalue=*/false, 683 &@1, /*loc_val=*/NULL); 684 685 if (err) { 686 free($1.str); 687 PE_ABORT(err); 688 } 689 $$ = term; 690 } 691 | 692 PE_TERM '=' name_or_raw 693 { 694 struct parse_events_term *term; 695 int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3); 696 697 if (err) { 698 free($3); 699 PE_ABORT(err); 700 } 701 $$ = term; 702 } 703 | 704 PE_TERM '=' PE_TERM 705 { 706 struct parse_events_term *term; 707 int err = parse_events_term__term(&term, $1, $3, &@1, &@3); 708 709 if (err) 710 PE_ABORT(err); 711 712 $$ = term; 713 } 714 | 715 PE_TERM '=' PE_VALUE 716 { 717 struct parse_events_term *term; 718 int err = parse_events_term__num(&term, $1, 719 /*config=*/NULL, $3, /*novalue=*/false, 720 &@1, &@3); 721 722 if (err) 723 PE_ABORT(err); 724 725 $$ = term; 726 } 727 | 728 PE_TERM 729 { 730 struct parse_events_term *term; 731 int err = parse_events_term__num(&term, $1, 732 /*config=*/NULL, /*num=*/1, /*novalue=*/true, 733 &@1, /*loc_val=*/NULL); 734 735 if (err) 736 PE_ABORT(err); 737 738 $$ = term; 739 } 740 | 741 PE_DRV_CFG_TERM 742 { 743 struct parse_events_term *term; 744 char *config = strdup($1); 745 int err; 746 747 if (!config) 748 YYNOMEM; 749 err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL); 750 if (err) { 751 free($1); 752 free(config); 753 PE_ABORT(err); 754 } 755 $$ = term; 756 } 757 758 sep_dc: ':' | 759 760 sep_slash_slash_dc: '/' '/' | ':' | 761 762 %% 763 764 void parse_events_error(YYLTYPE *loc, void *parse_state, 765 void *scanner __maybe_unused, 766 char const *msg __maybe_unused) 767 { 768 parse_events_evlist_error(parse_state, loc->last_column, "parser error"); 769 } 770