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