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