1 %pure-parser 2 %parse-param {void *_data} 3 %parse-param {void *scanner} 4 %lex-param {void* scanner} 5 6 %{ 7 8 #define YYDEBUG 1 9 10 #include <linux/compiler.h> 11 #include <linux/list.h> 12 #include "types.h" 13 #include "util.h" 14 #include "parse-events.h" 15 #include "parse-events-bison.h" 16 17 extern int parse_events_lex (YYSTYPE* lvalp, void* scanner); 18 19 #define ABORT_ON(val) \ 20 do { \ 21 if (val) \ 22 YYABORT; \ 23 } while (0) 24 25 #define ALLOC_LIST(list) \ 26 do { \ 27 list = malloc(sizeof(*list)); \ 28 ABORT_ON(!list); \ 29 INIT_LIST_HEAD(list); \ 30 } while (0) 31 32 static inc_group_count(struct list_head *list, 33 struct parse_events_evlist *data) 34 { 35 /* Count groups only have more than 1 members */ 36 if (!list_is_last(list->next, list)) 37 data->nr_groups++; 38 } 39 40 %} 41 42 %token PE_START_EVENTS PE_START_TERMS 43 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 44 %token PE_EVENT_NAME 45 %token PE_NAME 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 %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 <num> value_sym 62 %type <head> event_config 63 %type <term> event_term 64 %type <head> event_pmu 65 %type <head> event_legacy_symbol 66 %type <head> event_legacy_cache 67 %type <head> event_legacy_mem 68 %type <head> event_legacy_tracepoint 69 %type <head> event_legacy_numeric 70 %type <head> event_legacy_raw 71 %type <head> event_def 72 %type <head> event_mod 73 %type <head> event_name 74 %type <head> event 75 %type <head> events 76 %type <head> group_def 77 %type <head> group 78 %type <head> groups 79 80 %union 81 { 82 char *str; 83 u64 num; 84 struct list_head *head; 85 struct parse_events_term *term; 86 } 87 %% 88 89 start: 90 PE_START_EVENTS start_events 91 | 92 PE_START_TERMS start_terms 93 94 start_events: groups 95 { 96 struct parse_events_evlist *data = _data; 97 98 parse_events_update_lists($1, &data->list); 99 } 100 101 groups: 102 groups ',' group 103 { 104 struct list_head *list = $1; 105 struct list_head *group = $3; 106 107 parse_events_update_lists(group, list); 108 $$ = list; 109 } 110 | 111 groups ',' event 112 { 113 struct list_head *list = $1; 114 struct list_head *event = $3; 115 116 parse_events_update_lists(event, list); 117 $$ = list; 118 } 119 | 120 group 121 | 122 event 123 124 group: 125 group_def ':' PE_MODIFIER_EVENT 126 { 127 struct list_head *list = $1; 128 129 ABORT_ON(parse_events__modifier_group(list, $3)); 130 $$ = list; 131 } 132 | 133 group_def 134 135 group_def: 136 PE_NAME '{' events '}' 137 { 138 struct list_head *list = $3; 139 140 inc_group_count(list, _data); 141 parse_events__set_leader($1, list); 142 $$ = list; 143 } 144 | 145 '{' events '}' 146 { 147 struct list_head *list = $2; 148 149 inc_group_count(list, _data); 150 parse_events__set_leader(NULL, list); 151 $$ = list; 152 } 153 154 events: 155 events ',' event 156 { 157 struct list_head *event = $3; 158 struct list_head *list = $1; 159 160 parse_events_update_lists(event, list); 161 $$ = list; 162 } 163 | 164 event 165 166 event: event_mod 167 168 event_mod: 169 event_name PE_MODIFIER_EVENT 170 { 171 struct list_head *list = $1; 172 173 /* 174 * Apply modifier on all events added by single event definition 175 * (there could be more events added for multiple tracepoint 176 * definitions via '*?'. 177 */ 178 ABORT_ON(parse_events__modifier_event(list, $2, false)); 179 $$ = list; 180 } 181 | 182 event_name 183 184 event_name: 185 PE_EVENT_NAME event_def 186 { 187 ABORT_ON(parse_events_name($2, $1)); 188 free($1); 189 $$ = $2; 190 } 191 | 192 event_def 193 194 event_def: event_pmu | 195 event_legacy_symbol | 196 event_legacy_cache sep_dc | 197 event_legacy_mem | 198 event_legacy_tracepoint sep_dc | 199 event_legacy_numeric sep_dc | 200 event_legacy_raw sep_dc 201 202 event_pmu: 203 PE_NAME '/' event_config '/' 204 { 205 struct parse_events_evlist *data = _data; 206 struct list_head *list; 207 208 ALLOC_LIST(list); 209 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, $3)); 210 parse_events__free_terms($3); 211 $$ = list; 212 } 213 214 value_sym: 215 PE_VALUE_SYM_HW 216 | 217 PE_VALUE_SYM_SW 218 219 event_legacy_symbol: 220 value_sym '/' event_config '/' 221 { 222 struct parse_events_evlist *data = _data; 223 struct list_head *list; 224 int type = $1 >> 16; 225 int config = $1 & 255; 226 227 ALLOC_LIST(list); 228 ABORT_ON(parse_events_add_numeric(list, &data->idx, 229 type, config, $3)); 230 parse_events__free_terms($3); 231 $$ = list; 232 } 233 | 234 value_sym sep_slash_dc 235 { 236 struct parse_events_evlist *data = _data; 237 struct list_head *list; 238 int type = $1 >> 16; 239 int config = $1 & 255; 240 241 ALLOC_LIST(list); 242 ABORT_ON(parse_events_add_numeric(list, &data->idx, 243 type, config, NULL)); 244 $$ = list; 245 } 246 247 event_legacy_cache: 248 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT 249 { 250 struct parse_events_evlist *data = _data; 251 struct list_head *list; 252 253 ALLOC_LIST(list); 254 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5)); 255 $$ = list; 256 } 257 | 258 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT 259 { 260 struct parse_events_evlist *data = _data; 261 struct list_head *list; 262 263 ALLOC_LIST(list); 264 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL)); 265 $$ = list; 266 } 267 | 268 PE_NAME_CACHE_TYPE 269 { 270 struct parse_events_evlist *data = _data; 271 struct list_head *list; 272 273 ALLOC_LIST(list); 274 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL)); 275 $$ = list; 276 } 277 278 event_legacy_mem: 279 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 280 { 281 struct parse_events_evlist *data = _data; 282 struct list_head *list; 283 284 ALLOC_LIST(list); 285 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 286 (void *) $2, $4)); 287 $$ = list; 288 } 289 | 290 PE_PREFIX_MEM PE_VALUE sep_dc 291 { 292 struct parse_events_evlist *data = _data; 293 struct list_head *list; 294 295 ALLOC_LIST(list); 296 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 297 (void *) $2, NULL)); 298 $$ = list; 299 } 300 301 event_legacy_tracepoint: 302 PE_NAME ':' PE_NAME 303 { 304 struct parse_events_evlist *data = _data; 305 struct list_head *list; 306 307 ALLOC_LIST(list); 308 ABORT_ON(parse_events_add_tracepoint(list, &data->idx, $1, $3)); 309 $$ = list; 310 } 311 312 event_legacy_numeric: 313 PE_VALUE ':' PE_VALUE 314 { 315 struct parse_events_evlist *data = _data; 316 struct list_head *list; 317 318 ALLOC_LIST(list); 319 ABORT_ON(parse_events_add_numeric(list, &data->idx, (u32)$1, $3, NULL)); 320 $$ = list; 321 } 322 323 event_legacy_raw: 324 PE_RAW 325 { 326 struct parse_events_evlist *data = _data; 327 struct list_head *list; 328 329 ALLOC_LIST(list); 330 ABORT_ON(parse_events_add_numeric(list, &data->idx, 331 PERF_TYPE_RAW, $1, NULL)); 332 $$ = list; 333 } 334 335 start_terms: event_config 336 { 337 struct parse_events_terms *data = _data; 338 data->terms = $1; 339 } 340 341 event_config: 342 event_config ',' event_term 343 { 344 struct list_head *head = $1; 345 struct parse_events_term *term = $3; 346 347 ABORT_ON(!head); 348 list_add_tail(&term->list, head); 349 $$ = $1; 350 } 351 | 352 event_term 353 { 354 struct list_head *head = malloc(sizeof(*head)); 355 struct parse_events_term *term = $1; 356 357 ABORT_ON(!head); 358 INIT_LIST_HEAD(head); 359 list_add_tail(&term->list, head); 360 $$ = head; 361 } 362 363 event_term: 364 PE_NAME '=' PE_NAME 365 { 366 struct parse_events_term *term; 367 368 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 369 $1, $3)); 370 $$ = term; 371 } 372 | 373 PE_NAME '=' PE_VALUE 374 { 375 struct parse_events_term *term; 376 377 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 378 $1, $3)); 379 $$ = term; 380 } 381 | 382 PE_NAME '=' PE_VALUE_SYM_HW 383 { 384 struct parse_events_term *term; 385 int config = $3 & 255; 386 387 ABORT_ON(parse_events_term__sym_hw(&term, $1, config)); 388 $$ = term; 389 } 390 | 391 PE_NAME 392 { 393 struct parse_events_term *term; 394 395 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 396 $1, 1)); 397 $$ = term; 398 } 399 | 400 PE_VALUE_SYM_HW 401 { 402 struct parse_events_term *term; 403 int config = $1 & 255; 404 405 ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); 406 $$ = term; 407 } 408 | 409 PE_TERM '=' PE_NAME 410 { 411 struct parse_events_term *term; 412 413 ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3)); 414 $$ = term; 415 } 416 | 417 PE_TERM '=' PE_VALUE 418 { 419 struct parse_events_term *term; 420 421 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3)); 422 $$ = term; 423 } 424 | 425 PE_TERM 426 { 427 struct parse_events_term *term; 428 429 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1)); 430 $$ = term; 431 } 432 433 sep_dc: ':' | 434 435 sep_slash_dc: '/' | ':' | 436 437 %% 438 439 void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused, 440 char const *msg __maybe_unused) 441 { 442 } 443