brintos

brintos / linux-shallow public Read only

0
0
Text · 14.3 KiB · b3c51f0 Raw
779 lines · plain
1%define api.pure full2%parse-param {void *_parse_state}3%parse-param {void *scanner}4%lex-param {void* scanner}5%locations6 7%{8 9#ifndef NDEBUG10#define YYDEBUG 111#endif12 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_TERMS58%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM59%token PE_VALUE_SYM_TOOL60%token PE_EVENT_NAME61%token PE_RAW PE_NAME62%token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH63%token PE_LEGACY_CACHE64%token PE_PREFIX_MEM65%token PE_ERROR66%token PE_DRV_CFG_TERM67%token PE_TERM_HW68%type <num> PE_VALUE69%type <num> PE_VALUE_SYM_HW70%type <num> PE_VALUE_SYM_SW71%type <num> PE_VALUE_SYM_TOOL72%type <mod> PE_MODIFIER_EVENT73%type <term_type> PE_TERM74%type <num> value_sym75%type <str> PE_RAW76%type <str> PE_NAME77%type <str> PE_LEGACY_CACHE78%type <str> PE_MODIFIER_BP79%type <str> PE_EVENT_NAME80%type <str> PE_DRV_CFG_TERM81%type <str> name_or_raw82%destructor { free ($$); } <str>83%type <term> event_term84%destructor { parse_events_term__delete ($$); } <term>85%type <list_terms> event_config86%type <list_terms> opt_event_config87%type <list_terms> opt_pmu_config88%destructor { parse_events_terms__delete ($$); } <list_terms>89%type <list_evsel> event_pmu90%type <list_evsel> event_legacy_symbol91%type <list_evsel> event_legacy_cache92%type <list_evsel> event_legacy_mem93%type <list_evsel> event_legacy_tracepoint94%type <list_evsel> event_legacy_numeric95%type <list_evsel> event_legacy_raw96%type <list_evsel> event_def97%type <list_evsel> event_mod98%type <list_evsel> event_name99%type <list_evsel> event100%type <list_evsel> events101%type <list_evsel> group_def102%type <list_evsel> group103%type <list_evsel> groups104%destructor { free_list_evsel ($$); } <list_evsel>105%type <tracepoint_name> tracepoint_name106%destructor { free ($$.sys); free ($$.event); } <tracepoint_name>107%type <hardware_term> PE_TERM_HW108%destructor { free ($$.str); } <hardware_term>109 110%union111{112	char *str;113	u64 num;114	struct parse_events_modifier mod;115	enum parse_events__term_type term_type;116	struct list_head *list_evsel;117	struct parse_events_terms *list_terms;118	struct parse_events_term *term;119	struct tracepoint_name {120		char *sys;121		char *event;122	} tracepoint_name;123	struct hardware_term {124		char *str;125		u64 num;126	} hardware_term;127}128%%129 130 /*131  * Entry points. We are either parsing events or terminals. Just terminal132  * parsing is used for parsing events in sysfs.133  */134start:135PE_START_EVENTS start_events136|137PE_START_TERMS  start_terms138 139start_events: groups140{141	/* Take the parsed events, groups.. and place into parse_state. */142	struct list_head *groups  = $1;143	struct parse_events_state *parse_state = _parse_state;144 145	list_splice_tail(groups, &parse_state->list);146	free(groups);147}148 149groups: /* A list of groups or events. */150groups ',' group151{152	/* Merge group into the list of events/groups. */153	struct list_head *groups  = $1;154	struct list_head *group  = $3;155 156	list_splice_tail(group, groups);157	free(group);158	$$ = groups;159}160|161groups ',' event162{163	/* Merge event into the list of events/groups. */164	struct list_head *groups  = $1;165	struct list_head *event = $3;166 167 168	list_splice_tail(event, groups);169	free(event);170	$$ = groups;171}172|173group174|175event176 177group:178group_def ':' PE_MODIFIER_EVENT179{180	/* Apply the modifier to the events in the group_def. */181	struct list_head *list = $1;182	int err;183 184	err = parse_events__modifier_group(_parse_state, &@3, list, $3);185	if (err)186		YYABORT;187	$$ = list;188}189|190group_def191 192group_def:193PE_NAME '{' events '}'194{195	struct list_head *list = $3;196 197	/*198	 * Set the first entry of list to be the leader. Set the group name on199	 * the leader to $1 taking ownership.200	 */201	parse_events__set_leader($1, list);202	$$ = list;203}204|205'{' events '}'206{207	struct list_head *list = $2;208 209	/* Set the first entry of list to be the leader clearing the group name. */210	parse_events__set_leader(NULL, list);211	$$ = list;212}213 214events:215events ',' event216{217	struct list_head *events  = $1;218	struct list_head *event = $3;219 220	list_splice_tail(event, events);221	free(event);222	$$ = events;223}224|225event226 227event: event_mod228 229event_mod:230event_name PE_MODIFIER_EVENT231{232	struct list_head *list = $1;233	int err;234 235	/*236	 * Apply modifier on all events added by single event definition237	 * (there could be more events added for multiple tracepoint238	 * definitions via '*?'.239	 */240	err = parse_events__modifier_event(_parse_state, &@2, list, $2);241	if (err)242		YYABORT;243	$$ = list;244}245|246event_name247 248event_name:249PE_EVENT_NAME event_def250{251	/*252	 * When an event is parsed the text is rewound and the entire text of253	 * the event is set to the str of PE_EVENT_NAME token matched here. If254	 * no name was on an event via a term, set the name to the entire text255	 * taking ownership of the allocation.256	 */257	int err = parse_events__set_default_name($2, $1);258 259	if (err) {260		free_list_evsel($2);261		YYNOMEM;262	}263	$$ = $2;264}265|266event_def267 268event_def: event_pmu |269	   event_legacy_symbol |270	   event_legacy_cache sep_dc |271	   event_legacy_mem sep_dc |272	   event_legacy_tracepoint sep_dc |273	   event_legacy_numeric sep_dc |274	   event_legacy_raw sep_dc275 276event_pmu:277PE_NAME opt_pmu_config278{279	/* List of created evsels. */280	struct list_head *list = NULL;281	int err = parse_events_multi_pmu_add_or_add_pmu(_parse_state, $1, $2, &list, &@1);282 283	parse_events_terms__delete($2);284	free($1);285	if (err)286		PE_ABORT(err);287	$$ = list;288}289|290PE_NAME sep_dc291{292	struct list_head *list;293	int err;294 295	err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1);296	if (err < 0) {297		struct parse_events_state *parse_state = _parse_state;298		struct parse_events_error *error = parse_state->error;299		char *help;300 301		if (asprintf(&help, "Unable to find event on a PMU of '%s'", $1) < 0)302			help = NULL;303		parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help);304		free($1);305		PE_ABORT(err);306	}307	free($1);308	$$ = list;309}310 311value_sym:312PE_VALUE_SYM_HW313|314PE_VALUE_SYM_SW315 316event_legacy_symbol:317value_sym '/' event_config '/'318{319	struct list_head *list;320	int type = $1 >> 16;321	int config = $1 & 255;322	int err;323	bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);324 325	list = alloc_list();326	if (!list)327		YYNOMEM;328	err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);329	parse_events_terms__delete($3);330	if (err) {331		free_list_evsel(list);332		PE_ABORT(err);333	}334	$$ = list;335}336|337value_sym sep_slash_slash_dc338{339	struct list_head *list;340	int type = $1 >> 16;341	int config = $1 & 255;342	bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);343	int err;344 345	list = alloc_list();346	if (!list)347		YYNOMEM;348	err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);349	if (err)350		PE_ABORT(err);351	$$ = list;352}353|354PE_VALUE_SYM_TOOL sep_slash_slash_dc355{356	struct list_head *list;357	int err;358 359	list = alloc_list();360	if (!list)361		YYNOMEM;362	err = parse_events_add_tool(_parse_state, list, $1);363	if (err)364		YYNOMEM;365	$$ = list;366}367 368event_legacy_cache:369PE_LEGACY_CACHE opt_event_config370{371	struct parse_events_state *parse_state = _parse_state;372	struct list_head *list;373	int err;374 375	list = alloc_list();376	if (!list)377		YYNOMEM;378 379	err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2);380 381	parse_events_terms__delete($2);382	free($1);383	if (err) {384		free_list_evsel(list);385		PE_ABORT(err);386	}387	$$ = list;388}389 390event_legacy_mem:391PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config392{393	struct list_head *list;394	int err;395 396	list = alloc_list();397	if (!list)398		YYNOMEM;399 400	err = parse_events_add_breakpoint(_parse_state, list,401					  $2, $6, $4, $7);402	parse_events_terms__delete($7);403	free($6);404	if (err) {405		free(list);406		PE_ABORT(err);407	}408	$$ = list;409}410|411PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config412{413	struct list_head *list;414	int err;415 416	list = alloc_list();417	if (!list)418		YYNOMEM;419 420	err = parse_events_add_breakpoint(_parse_state, list,421					  $2, NULL, $4, $5);422	parse_events_terms__delete($5);423	if (err) {424		free(list);425		PE_ABORT(err);426	}427	$$ = list;428}429|430PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config431{432	struct list_head *list;433	int err;434 435	list = alloc_list();436	if (!list)437		YYNOMEM;438 439	err = parse_events_add_breakpoint(_parse_state, list,440					  $2, $4, 0, $5);441	parse_events_terms__delete($5);442	free($4);443	if (err) {444		free(list);445		PE_ABORT(err);446	}447	$$ = list;448}449|450PE_PREFIX_MEM PE_VALUE opt_event_config451{452	struct list_head *list;453	int err;454 455	list = alloc_list();456	if (!list)457		YYNOMEM;458	err = parse_events_add_breakpoint(_parse_state, list,459					  $2, NULL, 0, $3);460	parse_events_terms__delete($3);461	if (err) {462		free(list);463		PE_ABORT(err);464	}465	$$ = list;466}467 468event_legacy_tracepoint:469tracepoint_name opt_event_config470{471	struct parse_events_state *parse_state = _parse_state;472	struct parse_events_error *error = parse_state->error;473	struct list_head *list;474	int err;475 476	list = alloc_list();477	if (!list)478		YYNOMEM;479 480	err = parse_events_add_tracepoint(parse_state, list, $1.sys, $1.event,481					error, $2, &@1);482 483	parse_events_terms__delete($2);484	free($1.sys);485	free($1.event);486	if (err) {487		free(list);488		PE_ABORT(err);489	}490	$$ = list;491}492 493tracepoint_name:494PE_NAME ':' PE_NAME495{496	struct tracepoint_name tracepoint = {$1, $3};497 498	$$ = tracepoint;499}500 501event_legacy_numeric:502PE_VALUE ':' PE_VALUE opt_event_config503{504	struct list_head *list;505	int err;506 507	list = alloc_list();508	if (!list)509		YYNOMEM;510	err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,511				       /*wildcard=*/false);512	parse_events_terms__delete($4);513	if (err) {514		free(list);515		PE_ABORT(err);516	}517	$$ = list;518}519 520event_legacy_raw:521PE_RAW opt_event_config522{523	struct list_head *list;524	int err;525	u64 num;526 527	list = alloc_list();528	if (!list)529		YYNOMEM;530	errno = 0;531	num = strtoull($1 + 1, NULL, 16);532	/* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */533	if (errno)534		YYABORT;535	free($1);536	err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,537				       /*wildcard=*/false);538	parse_events_terms__delete($2);539	if (err) {540		free(list);541		PE_ABORT(err);542	}543	$$ = list;544}545 546opt_event_config:547'/' event_config '/'548{549	$$ = $2;550}551|552'/' '/'553{554	$$ = NULL;555}556|557{558	$$ = NULL;559}560 561opt_pmu_config:562'/' event_config '/'563{564	$$ = $2;565}566|567'/' '/'568{569	$$ = NULL;570}571 572start_terms: event_config573{574	struct parse_events_state *parse_state = _parse_state;575	if (parse_state->terms) {576		parse_events_terms__delete ($1);577		YYABORT;578	}579	parse_state->terms = $1;580}581 582event_config:583event_config ',' event_term584{585	struct parse_events_terms *head = $1;586	struct parse_events_term *term = $3;587 588	if (!head) {589		parse_events_term__delete(term);590		YYABORT;591	}592	list_add_tail(&term->list, &head->terms);593	$$ = $1;594}595|596event_term597{598	struct parse_events_terms *head = malloc(sizeof(*head));599	struct parse_events_term *term = $1;600 601	if (!head)602		YYNOMEM;603	parse_events_terms__init(head);604	list_add_tail(&term->list, &head->terms);605	$$ = head;606}607 608name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE609|610PE_TERM_HW611{612	$$ = $1.str;613}614 615event_term:616PE_RAW617{618	struct parse_events_term *term;619	int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,620					 strdup("raw"), $1, &@1, &@1);621 622	if (err) {623		free($1);624		PE_ABORT(err);625	}626	$$ = term;627}628|629name_or_raw '=' name_or_raw630{631	struct parse_events_term *term;632	int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);633 634	if (err) {635		free($1);636		free($3);637		PE_ABORT(err);638	}639	$$ = term;640}641|642name_or_raw '=' PE_VALUE643{644	struct parse_events_term *term;645	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,646					 $1, $3, /*novalue=*/false, &@1, &@3);647 648	if (err) {649		free($1);650		PE_ABORT(err);651	}652	$$ = term;653}654|655PE_LEGACY_CACHE656{657	struct parse_events_term *term;658	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,659					 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);660 661	if (err) {662		free($1);663		PE_ABORT(err);664	}665	$$ = term;666}667|668PE_NAME669{670	struct parse_events_term *term;671	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,672					 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);673 674	if (err) {675		free($1);676		PE_ABORT(err);677	}678	$$ = term;679}680|681PE_TERM_HW682{683	struct parse_events_term *term;684	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE,685					 $1.str, $1.num & 255, /*novalue=*/false,686					 &@1, /*loc_val=*/NULL);687 688	if (err) {689		free($1.str);690		PE_ABORT(err);691	}692	$$ = term;693}694|695PE_TERM '=' name_or_raw696{697	struct parse_events_term *term;698	int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3);699 700	if (err) {701		free($3);702		PE_ABORT(err);703	}704	$$ = term;705}706|707PE_TERM '=' PE_TERM708{709	struct parse_events_term *term;710	int err = parse_events_term__term(&term, $1, $3, &@1, &@3);711 712	if (err)713		PE_ABORT(err);714 715	$$ = term;716}717|718PE_TERM '=' PE_VALUE719{720	struct parse_events_term *term;721	int err = parse_events_term__num(&term, $1,722					 /*config=*/NULL, $3, /*novalue=*/false,723					 &@1, &@3);724 725	if (err)726		PE_ABORT(err);727 728	$$ = term;729}730|731PE_TERM732{733	struct parse_events_term *term;734	int err = parse_events_term__num(&term, $1,735					 /*config=*/NULL, /*num=*/1, /*novalue=*/true,736					 &@1, /*loc_val=*/NULL);737 738	if (err)739		PE_ABORT(err);740 741	$$ = term;742}743|744PE_DRV_CFG_TERM745{746	struct parse_events_term *term;747	char *config = strdup($1);748	int err;749 750	if (!config)751		YYNOMEM;752	err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL);753	if (err) {754		free($1);755		free(config);756		PE_ABORT(err);757	}758	$$ = term;759}760 761sep_dc: ':' |762 763sep_slash_slash_dc: '/' '/' | ':' |764 765%%766 767void parse_events_error(YYLTYPE *loc, void *_parse_state,768			void *scanner __maybe_unused,769			char const *msg __maybe_unused)770{771	struct parse_events_state *parse_state = _parse_state;772 773	if (!parse_state->error || !list_empty(&parse_state->error->list))774		return;775 776	parse_events_error__handle(parse_state->error, loc->last_column,777				   strdup("Unrecognized input"), NULL);778}779