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 error->idx = @1.first_column; 393 error->str = strdup("unknown tracepoint"); 394 return -1; 395 } 396 $$ = list; 397 } 398 399 event_legacy_numeric: 400 PE_VALUE ':' PE_VALUE 401 { 402 struct parse_events_evlist *data = _data; 403 struct list_head *list; 404 405 ALLOC_LIST(list); 406 ABORT_ON(parse_events_add_numeric(data, list, (u32)$1, $3, NULL)); 407 $$ = list; 408 } 409 410 event_legacy_raw: 411 PE_RAW 412 { 413 struct parse_events_evlist *data = _data; 414 struct list_head *list; 415 416 ALLOC_LIST(list); 417 ABORT_ON(parse_events_add_numeric(data, list, PERF_TYPE_RAW, $1, NULL)); 418 $$ = list; 419 } 420 421 start_terms: event_config 422 { 423 struct parse_events_terms *data = _data; 424 data->terms = $1; 425 } 426 427 event_config: 428 event_config ',' event_term 429 { 430 struct list_head *head = $1; 431 struct parse_events_term *term = $3; 432 433 ABORT_ON(!head); 434 list_add_tail(&term->list, head); 435 $$ = $1; 436 } 437 | 438 event_term 439 { 440 struct list_head *head = malloc(sizeof(*head)); 441 struct parse_events_term *term = $1; 442 443 ABORT_ON(!head); 444 INIT_LIST_HEAD(head); 445 list_add_tail(&term->list, head); 446 $$ = head; 447 } 448 449 event_term: 450 PE_NAME '=' PE_NAME 451 { 452 struct parse_events_term *term; 453 454 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 455 $1, $3, &@1, &@3)); 456 $$ = term; 457 } 458 | 459 PE_NAME '=' PE_VALUE 460 { 461 struct parse_events_term *term; 462 463 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 464 $1, $3, &@1, &@3)); 465 $$ = term; 466 } 467 | 468 PE_NAME '=' PE_VALUE_SYM_HW 469 { 470 struct parse_events_term *term; 471 int config = $3 & 255; 472 473 ABORT_ON(parse_events_term__sym_hw(&term, $1, config)); 474 $$ = term; 475 } 476 | 477 PE_NAME 478 { 479 struct parse_events_term *term; 480 481 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 482 $1, 1, &@1, NULL)); 483 $$ = term; 484 } 485 | 486 PE_VALUE_SYM_HW 487 { 488 struct parse_events_term *term; 489 int config = $1 & 255; 490 491 ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); 492 $$ = term; 493 } 494 | 495 PE_TERM '=' PE_NAME 496 { 497 struct parse_events_term *term; 498 499 ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3)); 500 $$ = term; 501 } 502 | 503 PE_TERM '=' PE_VALUE 504 { 505 struct parse_events_term *term; 506 507 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, &@1, &@3)); 508 $$ = term; 509 } 510 | 511 PE_TERM 512 { 513 struct parse_events_term *term; 514 515 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL)); 516 $$ = term; 517 } 518 519 sep_dc: ':' | 520 521 sep_slash_dc: '/' | ':' | 522 523 %% 524 525 void parse_events_error(YYLTYPE *loc, void *data, 526 void *scanner __maybe_unused, 527 char const *msg __maybe_unused) 528 { 529 parse_events_evlist_error(data, loc->last_column, "parser error"); 530 } 531