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