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