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