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