at master 647 lines 12 kB view raw
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 22int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner); 23void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg); 24 25#define PE_ABORT(val) \ 26do { \ 27 if (val == -ENOMEM) \ 28 YYNOMEM; \ 29 YYABORT; \ 30} while (0) 31 32static 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 44static 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 */ 118start: 119PE_START_EVENTS start_events 120| 121PE_START_TERMS start_terms 122 123start_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 133groups: /* A list of groups or events. */ 134groups ',' 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| 145groups ',' 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| 157group 158| 159event 160 161group: 162group_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| 174group_def 175 176group_def: 177PE_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 198events: 199events ',' 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| 209event 210 211event: event_mod 212 213event_mod: 214event_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| 230event_name 231 232event_name: 233PE_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| 250event_def 251 252event_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 258event_pmu: 259PE_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| 272PE_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 293event_legacy_mem: 294PE_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| 314PE_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| 333PE_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| 353PE_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 371event_legacy_tracepoint: 372tracepoint_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 396tracepoint_name: 397PE_NAME ':' PE_NAME 398{ 399 struct tracepoint_name tracepoint = {$1, $3}; 400 401 $$ = tracepoint; 402} 403 404event_legacy_numeric: 405PE_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 423event_legacy_raw: 424PE_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 449opt_event_config: 450'/' event_config '/' 451{ 452 $$ = $2; 453} 454| 455'/' '/' 456{ 457 $$ = NULL; 458} 459| 460{ 461 $$ = NULL; 462} 463 464opt_pmu_config: 465'/' event_config '/' 466{ 467 $$ = $2; 468} 469| 470'/' '/' 471{ 472 $$ = NULL; 473} 474 475start_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 485event_config: 486event_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| 499event_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 511name_or_raw: PE_RAW | PE_NAME 512 513event_term: 514PE_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| 527name_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| 540name_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| 553PE_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| 566PE_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| 578PE_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| 589PE_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| 602PE_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| 615PE_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 632sep_dc: ':' | 633 634%% 635 636void 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}