1 %pure-parser 2 %parse-param {void *_data} 3 %parse-param {void *scanner} 4 %lex-param {void* scanner} 5 %locations 6 7 %{ 8 9 #define YYDEBUG 1 10 11 #include <linux/compiler.h> 12 #include <linux/list.h> 13 #include <linux/types.h> 14 #include "util.h" 15 #include "parse-events.h" 16 #include "parse-events-bison.h" 17 18 #define ABORT_ON(val) \ 19 do { \ 20 if (val) \ 21 YYABORT; \ 22 } while (0) 23 24 #define ALLOC_LIST(list) \ 25 do { \ 26 list = malloc(sizeof(*list)); \ 27 ABORT_ON(!list); \ 28 INIT_LIST_HEAD(list); \ 29 } while (0) 30 31 static void inc_group_count(struct list_head *list, 32 struct parse_events_evlist *data) 33 { 34 /* Count groups only have more than 1 members */ 35 if (!list_is_last(list->next, list)) 36 data->nr_groups++; 37 } 38 39 %} 40 41 %token PE_START_EVENTS PE_START_TERMS 42 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 43 %token PE_EVENT_NAME 44 %token PE_NAME 45 %token PE_BPF_OBJECT PE_BPF_SOURCE 46 %token PE_MODIFIER_EVENT PE_MODIFIER_BP 47 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 48 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 49 %token PE_ERROR 50 %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT 51 %token PE_ARRAY_ALL PE_ARRAY_RANGE 52 %token PE_DRV_CFG_TERM 53 %type <num> PE_VALUE 54 %type <num> PE_VALUE_SYM_HW 55 %type <num> PE_VALUE_SYM_SW 56 %type <num> PE_RAW 57 %type <num> PE_TERM 58 %type <str> PE_NAME 59 %type <str> PE_BPF_OBJECT 60 %type <str> PE_BPF_SOURCE 61 %type <str> PE_NAME_CACHE_TYPE 62 %type <str> PE_NAME_CACHE_OP_RESULT 63 %type <str> PE_MODIFIER_EVENT 64 %type <str> PE_MODIFIER_BP 65 %type <str> PE_EVENT_NAME 66 %type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT 67 %type <str> PE_DRV_CFG_TERM 68 %type <num> value_sym 69 %type <head> event_config 70 %type <head> opt_event_config 71 %type <term> event_term 72 %type <head> event_pmu 73 %type <head> event_legacy_symbol 74 %type <head> event_legacy_cache 75 %type <head> event_legacy_mem 76 %type <head> event_legacy_tracepoint 77 %type <tracepoint_name> tracepoint_name 78 %type <head> event_legacy_numeric 79 %type <head> event_legacy_raw 80 %type <head> event_bpf_file 81 %type <head> event_def 82 %type <head> event_mod 83 %type <head> event_name 84 %type <head> event 85 %type <head> events 86 %type <head> group_def 87 %type <head> group 88 %type <head> groups 89 %type <array> array 90 %type <array> array_term 91 %type <array> array_terms 92 93 %union 94 { 95 char *str; 96 u64 num; 97 struct list_head *head; 98 struct parse_events_term *term; 99 struct tracepoint_name { 100 char *sys; 101 char *event; 102 } tracepoint_name; 103 struct parse_events_array array; 104 } 105 %% 106 107 start: 108 PE_START_EVENTS start_events 109 | 110 PE_START_TERMS start_terms 111 112 start_events: groups 113 { 114 struct parse_events_evlist *data = _data; 115 116 parse_events_update_lists($1, &data->list); 117 } 118 119 groups: 120 groups ',' group 121 { 122 struct list_head *list = $1; 123 struct list_head *group = $3; 124 125 parse_events_update_lists(group, list); 126 $$ = list; 127 } 128 | 129 groups ',' event 130 { 131 struct list_head *list = $1; 132 struct list_head *event = $3; 133 134 parse_events_update_lists(event, list); 135 $$ = list; 136 } 137 | 138 group 139 | 140 event 141 142 group: 143 group_def ':' PE_MODIFIER_EVENT 144 { 145 struct list_head *list = $1; 146 147 ABORT_ON(parse_events__modifier_group(list, $3)); 148 $$ = list; 149 } 150 | 151 group_def 152 153 group_def: 154 PE_NAME '{' events '}' 155 { 156 struct list_head *list = $3; 157 158 inc_group_count(list, _data); 159 parse_events__set_leader($1, list); 160 $$ = list; 161 } 162 | 163 '{' events '}' 164 { 165 struct list_head *list = $2; 166 167 inc_group_count(list, _data); 168 parse_events__set_leader(NULL, list); 169 $$ = list; 170 } 171 172 events: 173 events ',' event 174 { 175 struct list_head *event = $3; 176 struct list_head *list = $1; 177 178 parse_events_update_lists(event, list); 179 $$ = list; 180 } 181 | 182 event 183 184 event: event_mod 185 186 event_mod: 187 event_name PE_MODIFIER_EVENT 188 { 189 struct list_head *list = $1; 190 191 /* 192 * Apply modifier on all events added by single event definition 193 * (there could be more events added for multiple tracepoint 194 * definitions via '*?'. 195 */ 196 ABORT_ON(parse_events__modifier_event(list, $2, false)); 197 $$ = list; 198 } 199 | 200 event_name 201 202 event_name: 203 PE_EVENT_NAME event_def 204 { 205 ABORT_ON(parse_events_name($2, $1)); 206 free($1); 207 $$ = $2; 208 } 209 | 210 event_def 211 212 event_def: event_pmu | 213 event_legacy_symbol | 214 event_legacy_cache sep_dc | 215 event_legacy_mem | 216 event_legacy_tracepoint sep_dc | 217 event_legacy_numeric sep_dc | 218 event_legacy_raw sep_dc | 219 event_bpf_file 220 221 event_pmu: 222 PE_NAME opt_event_config 223 { 224 struct parse_events_evlist *data = _data; 225 struct list_head *list; 226 227 ALLOC_LIST(list); 228 ABORT_ON(parse_events_add_pmu(data, list, $1, $2)); 229 parse_events_terms__delete($2); 230 $$ = list; 231 } 232 | 233 PE_KERNEL_PMU_EVENT sep_dc 234 { 235 struct parse_events_evlist *data = _data; 236 struct list_head *head; 237 struct parse_events_term *term; 238 struct list_head *list; 239 240 ALLOC_LIST(head); 241 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 242 $1, 1, &@1, NULL)); 243 list_add_tail(&term->list, head); 244 245 ALLOC_LIST(list); 246 ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); 247 parse_events_terms__delete(head); 248 $$ = list; 249 } 250 | 251 PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc 252 { 253 struct parse_events_evlist *data = _data; 254 struct list_head *head; 255 struct parse_events_term *term; 256 struct list_head *list; 257 char pmu_name[128]; 258 snprintf(&pmu_name, 128, "%s-%s", $1, $3); 259 260 ALLOC_LIST(head); 261 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 262 &pmu_name, 1, &@1, NULL)); 263 list_add_tail(&term->list, head); 264 265 ALLOC_LIST(list); 266 ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); 267 parse_events_terms__delete(head); 268 $$ = list; 269 } 270 271 value_sym: 272 PE_VALUE_SYM_HW 273 | 274 PE_VALUE_SYM_SW 275 276 event_legacy_symbol: 277 value_sym '/' event_config '/' 278 { 279 struct parse_events_evlist *data = _data; 280 struct list_head *list; 281 int type = $1 >> 16; 282 int config = $1 & 255; 283 284 ALLOC_LIST(list); 285 ABORT_ON(parse_events_add_numeric(data, list, type, config, $3)); 286 parse_events_terms__delete($3); 287 $$ = list; 288 } 289 | 290 value_sym sep_slash_dc 291 { 292 struct parse_events_evlist *data = _data; 293 struct list_head *list; 294 int type = $1 >> 16; 295 int config = $1 & 255; 296 297 ALLOC_LIST(list); 298 ABORT_ON(parse_events_add_numeric(data, list, type, config, NULL)); 299 $$ = list; 300 } 301 302 event_legacy_cache: 303 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config 304 { 305 struct parse_events_evlist *data = _data; 306 struct parse_events_error *error = data->error; 307 struct list_head *list; 308 309 ALLOC_LIST(list); 310 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5, error, $6)); 311 parse_events_terms__delete($6); 312 $$ = list; 313 } 314 | 315 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config 316 { 317 struct parse_events_evlist *data = _data; 318 struct parse_events_error *error = data->error; 319 struct list_head *list; 320 321 ALLOC_LIST(list); 322 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL, error, $4)); 323 parse_events_terms__delete($4); 324 $$ = list; 325 } 326 | 327 PE_NAME_CACHE_TYPE opt_event_config 328 { 329 struct parse_events_evlist *data = _data; 330 struct parse_events_error *error = data->error; 331 struct list_head *list; 332 333 ALLOC_LIST(list); 334 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL, error, $2)); 335 parse_events_terms__delete($2); 336 $$ = list; 337 } 338 339 event_legacy_mem: 340 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc 341 { 342 struct parse_events_evlist *data = _data; 343 struct list_head *list; 344 345 ALLOC_LIST(list); 346 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 347 (void *) $2, $6, $4)); 348 $$ = list; 349 } 350 | 351 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc 352 { 353 struct parse_events_evlist *data = _data; 354 struct list_head *list; 355 356 ALLOC_LIST(list); 357 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 358 (void *) $2, NULL, $4)); 359 $$ = list; 360 } 361 | 362 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 363 { 364 struct parse_events_evlist *data = _data; 365 struct list_head *list; 366 367 ALLOC_LIST(list); 368 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 369 (void *) $2, $4, 0)); 370 $$ = list; 371 } 372 | 373 PE_PREFIX_MEM PE_VALUE sep_dc 374 { 375 struct parse_events_evlist *data = _data; 376 struct list_head *list; 377 378 ALLOC_LIST(list); 379 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 380 (void *) $2, NULL, 0)); 381 $$ = list; 382 } 383 384 event_legacy_tracepoint: 385 tracepoint_name opt_event_config 386 { 387 struct parse_events_evlist *data = _data; 388 struct parse_events_error *error = data->error; 389 struct list_head *list; 390 391 ALLOC_LIST(list); 392 if (error) 393 error->idx = @1.first_column; 394 395 if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event, 396 error, $2)) 397 return -1; 398 399 $$ = list; 400 } 401 402 tracepoint_name: 403 PE_NAME '-' PE_NAME ':' PE_NAME 404 { 405 char sys_name[128]; 406 struct tracepoint_name tracepoint; 407 408 snprintf(&sys_name, 128, "%s-%s", $1, $3); 409 tracepoint.sys = &sys_name; 410 tracepoint.event = $5; 411 412 $$ = tracepoint; 413 } 414 | 415 PE_NAME ':' PE_NAME 416 { 417 struct tracepoint_name tracepoint = {$1, $3}; 418 419 $$ = tracepoint; 420 } 421 422 event_legacy_numeric: 423 PE_VALUE ':' PE_VALUE opt_event_config 424 { 425 struct parse_events_evlist *data = _data; 426 struct list_head *list; 427 428 ALLOC_LIST(list); 429 ABORT_ON(parse_events_add_numeric(data, list, (u32)$1, $3, $4)); 430 parse_events_terms__delete($4); 431 $$ = list; 432 } 433 434 event_legacy_raw: 435 PE_RAW opt_event_config 436 { 437 struct parse_events_evlist *data = _data; 438 struct list_head *list; 439 440 ALLOC_LIST(list); 441 ABORT_ON(parse_events_add_numeric(data, list, PERF_TYPE_RAW, $1, $2)); 442 parse_events_terms__delete($2); 443 $$ = list; 444 } 445 446 event_bpf_file: 447 PE_BPF_OBJECT opt_event_config 448 { 449 struct parse_events_evlist *data = _data; 450 struct parse_events_error *error = data->error; 451 struct list_head *list; 452 453 ALLOC_LIST(list); 454 ABORT_ON(parse_events_load_bpf(data, list, $1, false, $2)); 455 parse_events_terms__delete($2); 456 $$ = list; 457 } 458 | 459 PE_BPF_SOURCE opt_event_config 460 { 461 struct parse_events_evlist *data = _data; 462 struct list_head *list; 463 464 ALLOC_LIST(list); 465 ABORT_ON(parse_events_load_bpf(data, list, $1, true, $2)); 466 parse_events_terms__delete($2); 467 $$ = list; 468 } 469 470 opt_event_config: 471 '/' event_config '/' 472 { 473 $$ = $2; 474 } 475 | 476 '/' '/' 477 { 478 $$ = NULL; 479 } 480 | 481 { 482 $$ = NULL; 483 } 484 485 start_terms: event_config 486 { 487 struct parse_events_terms *data = _data; 488 data->terms = $1; 489 } 490 491 event_config: 492 event_config ',' event_term 493 { 494 struct list_head *head = $1; 495 struct parse_events_term *term = $3; 496 497 ABORT_ON(!head); 498 list_add_tail(&term->list, head); 499 $$ = $1; 500 } 501 | 502 event_term 503 { 504 struct list_head *head = malloc(sizeof(*head)); 505 struct parse_events_term *term = $1; 506 507 ABORT_ON(!head); 508 INIT_LIST_HEAD(head); 509 list_add_tail(&term->list, head); 510 $$ = head; 511 } 512 513 event_term: 514 PE_NAME '=' PE_NAME 515 { 516 struct parse_events_term *term; 517 518 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 519 $1, $3, &@1, &@3)); 520 $$ = term; 521 } 522 | 523 PE_NAME '=' PE_VALUE 524 { 525 struct parse_events_term *term; 526 527 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 528 $1, $3, &@1, &@3)); 529 $$ = term; 530 } 531 | 532 PE_NAME '=' PE_VALUE_SYM_HW 533 { 534 struct parse_events_term *term; 535 int config = $3 & 255; 536 537 ABORT_ON(parse_events_term__sym_hw(&term, $1, config)); 538 $$ = term; 539 } 540 | 541 PE_NAME 542 { 543 struct parse_events_term *term; 544 545 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 546 $1, 1, &@1, NULL)); 547 $$ = term; 548 } 549 | 550 PE_VALUE_SYM_HW 551 { 552 struct parse_events_term *term; 553 int config = $1 & 255; 554 555 ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); 556 $$ = term; 557 } 558 | 559 PE_TERM '=' PE_NAME 560 { 561 struct parse_events_term *term; 562 563 ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3)); 564 $$ = term; 565 } 566 | 567 PE_TERM '=' PE_VALUE 568 { 569 struct parse_events_term *term; 570 571 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, &@1, &@3)); 572 $$ = term; 573 } 574 | 575 PE_TERM 576 { 577 struct parse_events_term *term; 578 579 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL)); 580 $$ = term; 581 } 582 | 583 PE_NAME array '=' PE_NAME 584 { 585 struct parse_events_term *term; 586 int i; 587 588 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 589 $1, $4, &@1, &@4)); 590 591 term->array = $2; 592 $$ = term; 593 } 594 | 595 PE_NAME array '=' PE_VALUE 596 { 597 struct parse_events_term *term; 598 599 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 600 $1, $4, &@1, &@4)); 601 term->array = $2; 602 $$ = term; 603 } 604 | 605 PE_DRV_CFG_TERM 606 { 607 struct parse_events_term *term; 608 609 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, 610 $1, $1, &@1, NULL)); 611 $$ = term; 612 } 613 614 array: 615 '[' array_terms ']' 616 { 617 $$ = $2; 618 } 619 | 620 PE_ARRAY_ALL 621 { 622 $$.nr_ranges = 0; 623 $$.ranges = NULL; 624 } 625 626 array_terms: 627 array_terms ',' array_term 628 { 629 struct parse_events_array new_array; 630 631 new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges; 632 new_array.ranges = malloc(sizeof(new_array.ranges[0]) * 633 new_array.nr_ranges); 634 ABORT_ON(!new_array.ranges); 635 memcpy(&new_array.ranges[0], $1.ranges, 636 $1.nr_ranges * sizeof(new_array.ranges[0])); 637 memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges, 638 $3.nr_ranges * sizeof(new_array.ranges[0])); 639 free($1.ranges); 640 free($3.ranges); 641 $$ = new_array; 642 } 643 | 644 array_term 645 646 array_term: 647 PE_VALUE 648 { 649 struct parse_events_array array; 650 651 array.nr_ranges = 1; 652 array.ranges = malloc(sizeof(array.ranges[0])); 653 ABORT_ON(!array.ranges); 654 array.ranges[0].start = $1; 655 array.ranges[0].length = 1; 656 $$ = array; 657 } 658 | 659 PE_VALUE PE_ARRAY_RANGE PE_VALUE 660 { 661 struct parse_events_array array; 662 663 ABORT_ON($3 < $1); 664 array.nr_ranges = 1; 665 array.ranges = malloc(sizeof(array.ranges[0])); 666 ABORT_ON(!array.ranges); 667 array.ranges[0].start = $1; 668 array.ranges[0].length = $3 - $1 + 1; 669 $$ = array; 670 } 671 672 sep_dc: ':' | 673 674 sep_slash_dc: '/' | ':' | 675 676 %% 677 678 void parse_events_error(YYLTYPE *loc, void *data, 679 void *scanner __maybe_unused, 680 char const *msg __maybe_unused) 681 { 682 parse_events_evlist_error(data, loc->last_column, "parser error"); 683 } 684