xref: /linux/tools/perf/util/parse-events.c (revision e814fddde18fec43fa41a27ae94c09b54772697e)
1d2709c7cSDavid Howells #include <linux/hw_breakpoint.h>
28dd2a131SJiri Olsa #include <linux/err.h>
386470930SIngo Molnar #include "util.h"
46b58e7f1SUlrich Drepper #include "../perf.h"
5361c99a6SArnaldo Carvalho de Melo #include "evlist.h"
669aad6f1SArnaldo Carvalho de Melo #include "evsel.h"
74b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
886470930SIngo Molnar #include "parse-events.h"
94b6ab94eSJosh Poimboeuf #include <subcmd/exec-cmd.h>
1042f60c2dSKan Liang #include "string.h"
115aab621bSArnaldo Carvalho de Melo #include "symbol.h"
125beeded1SJason Baron #include "cache.h"
138755a8f2SArjan van de Ven #include "header.h"
1484c86ca1SWang Nan #include "bpf-loader.h"
156e81c74cSMasami Hiramatsu #include "debug.h"
16592d5a6bSJiri Olsa #include <api/fs/tracing_path.h>
17ac20de6fSZheng Yan #include "parse-events-bison.h"
1890e2b22dSJiri Olsa #define YY_EXTRA_TYPE int
1989812fc8SJiri Olsa #include "parse-events-flex.h"
205f537a26SJiri Olsa #include "pmu.h"
21b41f1cecSNamhyung Kim #include "thread_map.h"
22f30a79b0SJiri Olsa #include "cpumap.h"
23b39b8393SJiri Olsa #include "asm/bug.h"
2489812fc8SJiri Olsa 
2589812fc8SJiri Olsa #define MAX_NAME_LEN 100
2686470930SIngo Molnar 
2782ba1f2fSJiri Olsa #ifdef PARSER_DEBUG
2882ba1f2fSJiri Olsa extern int parse_events_debug;
2982ba1f2fSJiri Olsa #endif
30ac20de6fSZheng Yan int parse_events_parse(void *data, void *scanner);
31e637d177SHe Kuang static int get_config_terms(struct list_head *head_config,
32e637d177SHe Kuang 			    struct list_head *head_terms __maybe_unused);
33bcd3279fSFrederic Weisbecker 
34dcb4e102SKan Liang static struct perf_pmu_event_symbol *perf_pmu_events_list;
35dcb4e102SKan Liang /*
36dcb4e102SKan Liang  * The variable indicates the number of supported pmu event symbols.
37dcb4e102SKan Liang  * 0 means not initialized and ready to init
38dcb4e102SKan Liang  * -1 means failed to init, don't try anymore
39dcb4e102SKan Liang  * >0 is the number of supported pmu event symbols
40dcb4e102SKan Liang  */
41dcb4e102SKan Liang static int perf_pmu_events_list_num;
42dcb4e102SKan Liang 
43705750f2SYunlong Song struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
441dc12760SJiri Olsa 	[PERF_COUNT_HW_CPU_CYCLES] = {
451dc12760SJiri Olsa 		.symbol = "cpu-cycles",
461dc12760SJiri Olsa 		.alias  = "cycles",
471dc12760SJiri Olsa 	},
481dc12760SJiri Olsa 	[PERF_COUNT_HW_INSTRUCTIONS] = {
491dc12760SJiri Olsa 		.symbol = "instructions",
501dc12760SJiri Olsa 		.alias  = "",
511dc12760SJiri Olsa 	},
521dc12760SJiri Olsa 	[PERF_COUNT_HW_CACHE_REFERENCES] = {
531dc12760SJiri Olsa 		.symbol = "cache-references",
541dc12760SJiri Olsa 		.alias  = "",
551dc12760SJiri Olsa 	},
561dc12760SJiri Olsa 	[PERF_COUNT_HW_CACHE_MISSES] = {
571dc12760SJiri Olsa 		.symbol = "cache-misses",
581dc12760SJiri Olsa 		.alias  = "",
591dc12760SJiri Olsa 	},
601dc12760SJiri Olsa 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = {
611dc12760SJiri Olsa 		.symbol = "branch-instructions",
621dc12760SJiri Olsa 		.alias  = "branches",
631dc12760SJiri Olsa 	},
641dc12760SJiri Olsa 	[PERF_COUNT_HW_BRANCH_MISSES] = {
651dc12760SJiri Olsa 		.symbol = "branch-misses",
661dc12760SJiri Olsa 		.alias  = "",
671dc12760SJiri Olsa 	},
681dc12760SJiri Olsa 	[PERF_COUNT_HW_BUS_CYCLES] = {
691dc12760SJiri Olsa 		.symbol = "bus-cycles",
701dc12760SJiri Olsa 		.alias  = "",
711dc12760SJiri Olsa 	},
721dc12760SJiri Olsa 	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = {
731dc12760SJiri Olsa 		.symbol = "stalled-cycles-frontend",
741dc12760SJiri Olsa 		.alias  = "idle-cycles-frontend",
751dc12760SJiri Olsa 	},
761dc12760SJiri Olsa 	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = {
771dc12760SJiri Olsa 		.symbol = "stalled-cycles-backend",
781dc12760SJiri Olsa 		.alias  = "idle-cycles-backend",
791dc12760SJiri Olsa 	},
801dc12760SJiri Olsa 	[PERF_COUNT_HW_REF_CPU_CYCLES] = {
811dc12760SJiri Olsa 		.symbol = "ref-cycles",
821dc12760SJiri Olsa 		.alias  = "",
831dc12760SJiri Olsa 	},
841dc12760SJiri Olsa };
8586470930SIngo Molnar 
86705750f2SYunlong Song struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
871dc12760SJiri Olsa 	[PERF_COUNT_SW_CPU_CLOCK] = {
881dc12760SJiri Olsa 		.symbol = "cpu-clock",
891dc12760SJiri Olsa 		.alias  = "",
901dc12760SJiri Olsa 	},
911dc12760SJiri Olsa 	[PERF_COUNT_SW_TASK_CLOCK] = {
921dc12760SJiri Olsa 		.symbol = "task-clock",
931dc12760SJiri Olsa 		.alias  = "",
941dc12760SJiri Olsa 	},
951dc12760SJiri Olsa 	[PERF_COUNT_SW_PAGE_FAULTS] = {
961dc12760SJiri Olsa 		.symbol = "page-faults",
971dc12760SJiri Olsa 		.alias  = "faults",
981dc12760SJiri Olsa 	},
991dc12760SJiri Olsa 	[PERF_COUNT_SW_CONTEXT_SWITCHES] = {
1001dc12760SJiri Olsa 		.symbol = "context-switches",
1011dc12760SJiri Olsa 		.alias  = "cs",
1021dc12760SJiri Olsa 	},
1031dc12760SJiri Olsa 	[PERF_COUNT_SW_CPU_MIGRATIONS] = {
1041dc12760SJiri Olsa 		.symbol = "cpu-migrations",
1051dc12760SJiri Olsa 		.alias  = "migrations",
1061dc12760SJiri Olsa 	},
1071dc12760SJiri Olsa 	[PERF_COUNT_SW_PAGE_FAULTS_MIN] = {
1081dc12760SJiri Olsa 		.symbol = "minor-faults",
1091dc12760SJiri Olsa 		.alias  = "",
1101dc12760SJiri Olsa 	},
1111dc12760SJiri Olsa 	[PERF_COUNT_SW_PAGE_FAULTS_MAJ] = {
1121dc12760SJiri Olsa 		.symbol = "major-faults",
1131dc12760SJiri Olsa 		.alias  = "",
1141dc12760SJiri Olsa 	},
1151dc12760SJiri Olsa 	[PERF_COUNT_SW_ALIGNMENT_FAULTS] = {
1161dc12760SJiri Olsa 		.symbol = "alignment-faults",
1171dc12760SJiri Olsa 		.alias  = "",
1181dc12760SJiri Olsa 	},
1191dc12760SJiri Olsa 	[PERF_COUNT_SW_EMULATION_FAULTS] = {
1201dc12760SJiri Olsa 		.symbol = "emulation-faults",
1211dc12760SJiri Olsa 		.alias  = "",
1221dc12760SJiri Olsa 	},
123d22d1a2aSAdrian Hunter 	[PERF_COUNT_SW_DUMMY] = {
124d22d1a2aSAdrian Hunter 		.symbol = "dummy",
125d22d1a2aSAdrian Hunter 		.alias  = "",
126d22d1a2aSAdrian Hunter 	},
127bae9cc41SArnaldo Carvalho de Melo 	[PERF_COUNT_SW_BPF_OUTPUT] = {
128bae9cc41SArnaldo Carvalho de Melo 		.symbol = "bpf-output",
129bae9cc41SArnaldo Carvalho de Melo 		.alias  = "",
130bae9cc41SArnaldo Carvalho de Melo 	},
13186470930SIngo Molnar };
13286470930SIngo Molnar 
133cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \
134cdd6c482SIngo Molnar 	((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
13586470930SIngo Molnar 
136cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config)		__PERF_EVENT_FIELD(config, RAW)
137cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config)	__PERF_EVENT_FIELD(config, CONFIG)
138cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config)		__PERF_EVENT_FIELD(config, TYPE)
139cdd6c482SIngo Molnar #define PERF_EVENT_ID(config)		__PERF_EVENT_FIELD(config, EVENT)
14086470930SIngo Molnar 
1416b58e7f1SUlrich Drepper #define for_each_subsystem(sys_dir, sys_dirent, sys_next)	       \
142f6bdafefSJason Baron 	while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)	       \
1436b58e7f1SUlrich Drepper 	if (sys_dirent.d_type == DT_DIR &&				       \
144f6bdafefSJason Baron 	   (strcmp(sys_dirent.d_name, ".")) &&				       \
145f6bdafefSJason Baron 	   (strcmp(sys_dirent.d_name, "..")))
146f6bdafefSJason Baron 
147ae07b63fSPeter Zijlstra static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
148ae07b63fSPeter Zijlstra {
149ae07b63fSPeter Zijlstra 	char evt_path[MAXPATHLEN];
150ae07b63fSPeter Zijlstra 	int fd;
151ae07b63fSPeter Zijlstra 
152ebf294bfSArnaldo Carvalho de Melo 	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
153ae07b63fSPeter Zijlstra 			sys_dir->d_name, evt_dir->d_name);
154ae07b63fSPeter Zijlstra 	fd = open(evt_path, O_RDONLY);
155ae07b63fSPeter Zijlstra 	if (fd < 0)
156ae07b63fSPeter Zijlstra 		return -EINVAL;
157ae07b63fSPeter Zijlstra 	close(fd);
158ae07b63fSPeter Zijlstra 
159ae07b63fSPeter Zijlstra 	return 0;
160ae07b63fSPeter Zijlstra }
161ae07b63fSPeter Zijlstra 
1626b58e7f1SUlrich Drepper #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next)	       \
163f6bdafefSJason Baron 	while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
1646b58e7f1SUlrich Drepper 	if (evt_dirent.d_type == DT_DIR &&				       \
165f6bdafefSJason Baron 	   (strcmp(evt_dirent.d_name, ".")) &&				       \
166ae07b63fSPeter Zijlstra 	   (strcmp(evt_dirent.d_name, "..")) &&				       \
167ae07b63fSPeter Zijlstra 	   (!tp_event_has_id(&sys_dirent, &evt_dirent)))
168f6bdafefSJason Baron 
169270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512
170f6bdafefSJason Baron 
171f6bdafefSJason Baron 
1721ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config)
173f6bdafefSJason Baron {
1741ef2ed10SFrederic Weisbecker 	struct tracepoint_path *path = NULL;
175f6bdafefSJason Baron 	DIR *sys_dir, *evt_dir;
176f6bdafefSJason Baron 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1778aa8a7c8SStephane Eranian 	char id_buf[24];
178725b1368SEric Dumazet 	int fd;
179f6bdafefSJason Baron 	u64 id;
180f6bdafefSJason Baron 	char evt_path[MAXPATHLEN];
181725b1368SEric Dumazet 	char dir_path[MAXPATHLEN];
182f6bdafefSJason Baron 
183ebf294bfSArnaldo Carvalho de Melo 	sys_dir = opendir(tracing_events_path);
184f6bdafefSJason Baron 	if (!sys_dir)
185725b1368SEric Dumazet 		return NULL;
186f6bdafefSJason Baron 
1876b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
188725b1368SEric Dumazet 
189ebf294bfSArnaldo Carvalho de Melo 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
190725b1368SEric Dumazet 			 sys_dirent.d_name);
191725b1368SEric Dumazet 		evt_dir = opendir(dir_path);
192725b1368SEric Dumazet 		if (!evt_dir)
1936b58e7f1SUlrich Drepper 			continue;
194725b1368SEric Dumazet 
1956b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
196725b1368SEric Dumazet 
197725b1368SEric Dumazet 			snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
198f6bdafefSJason Baron 				 evt_dirent.d_name);
199725b1368SEric Dumazet 			fd = open(evt_path, O_RDONLY);
200f6bdafefSJason Baron 			if (fd < 0)
201f6bdafefSJason Baron 				continue;
202f6bdafefSJason Baron 			if (read(fd, id_buf, sizeof(id_buf)) < 0) {
203f6bdafefSJason Baron 				close(fd);
204f6bdafefSJason Baron 				continue;
205f6bdafefSJason Baron 			}
206f6bdafefSJason Baron 			close(fd);
207f6bdafefSJason Baron 			id = atoll(id_buf);
208f6bdafefSJason Baron 			if (id == config) {
209f6bdafefSJason Baron 				closedir(evt_dir);
210f6bdafefSJason Baron 				closedir(sys_dir);
21159b4caebSJulia Lawall 				path = zalloc(sizeof(*path));
2121ef2ed10SFrederic Weisbecker 				path->system = malloc(MAX_EVENT_LENGTH);
2131ef2ed10SFrederic Weisbecker 				if (!path->system) {
2141ef2ed10SFrederic Weisbecker 					free(path);
2151ef2ed10SFrederic Weisbecker 					return NULL;
2161ef2ed10SFrederic Weisbecker 				}
2171ef2ed10SFrederic Weisbecker 				path->name = malloc(MAX_EVENT_LENGTH);
2181ef2ed10SFrederic Weisbecker 				if (!path->name) {
21974cf249dSArnaldo Carvalho de Melo 					zfree(&path->system);
2201ef2ed10SFrederic Weisbecker 					free(path);
2211ef2ed10SFrederic Weisbecker 					return NULL;
2221ef2ed10SFrederic Weisbecker 				}
2231ef2ed10SFrederic Weisbecker 				strncpy(path->system, sys_dirent.d_name,
2241ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2251ef2ed10SFrederic Weisbecker 				strncpy(path->name, evt_dirent.d_name,
2261ef2ed10SFrederic Weisbecker 					MAX_EVENT_LENGTH);
2271ef2ed10SFrederic Weisbecker 				return path;
228f6bdafefSJason Baron 			}
229f6bdafefSJason Baron 		}
230f6bdafefSJason Baron 		closedir(evt_dir);
231f6bdafefSJason Baron 	}
232f6bdafefSJason Baron 
233f6bdafefSJason Baron 	closedir(sys_dir);
2341ef2ed10SFrederic Weisbecker 	return NULL;
2351ef2ed10SFrederic Weisbecker }
2361ef2ed10SFrederic Weisbecker 
237e7c93f09SNamhyung Kim struct tracepoint_path *tracepoint_name_to_path(const char *name)
238e7c93f09SNamhyung Kim {
239e7c93f09SNamhyung Kim 	struct tracepoint_path *path = zalloc(sizeof(*path));
240e7c93f09SNamhyung Kim 	char *str = strchr(name, ':');
241e7c93f09SNamhyung Kim 
242e7c93f09SNamhyung Kim 	if (path == NULL || str == NULL) {
243e7c93f09SNamhyung Kim 		free(path);
244e7c93f09SNamhyung Kim 		return NULL;
245e7c93f09SNamhyung Kim 	}
246e7c93f09SNamhyung Kim 
247e7c93f09SNamhyung Kim 	path->system = strndup(name, str - name);
248e7c93f09SNamhyung Kim 	path->name = strdup(str+1);
249e7c93f09SNamhyung Kim 
250e7c93f09SNamhyung Kim 	if (path->system == NULL || path->name == NULL) {
25174cf249dSArnaldo Carvalho de Melo 		zfree(&path->system);
25274cf249dSArnaldo Carvalho de Melo 		zfree(&path->name);
253e7c93f09SNamhyung Kim 		free(path);
254e7c93f09SNamhyung Kim 		path = NULL;
255e7c93f09SNamhyung Kim 	}
256e7c93f09SNamhyung Kim 
257e7c93f09SNamhyung Kim 	return path;
258e7c93f09SNamhyung Kim }
259e7c93f09SNamhyung Kim 
2601424dc96SDavid Ahern const char *event_type(int type)
2611424dc96SDavid Ahern {
2621424dc96SDavid Ahern 	switch (type) {
2631424dc96SDavid Ahern 	case PERF_TYPE_HARDWARE:
2641424dc96SDavid Ahern 		return "hardware";
2651424dc96SDavid Ahern 
2661424dc96SDavid Ahern 	case PERF_TYPE_SOFTWARE:
2671424dc96SDavid Ahern 		return "software";
2681424dc96SDavid Ahern 
2691424dc96SDavid Ahern 	case PERF_TYPE_TRACEPOINT:
2701424dc96SDavid Ahern 		return "tracepoint";
2711424dc96SDavid Ahern 
2721424dc96SDavid Ahern 	case PERF_TYPE_HW_CACHE:
2731424dc96SDavid Ahern 		return "hardware-cache";
2741424dc96SDavid Ahern 
2751424dc96SDavid Ahern 	default:
2761424dc96SDavid Ahern 		break;
2771424dc96SDavid Ahern 	}
2781424dc96SDavid Ahern 
2791424dc96SDavid Ahern 	return "unknown";
2801424dc96SDavid Ahern }
2811424dc96SDavid Ahern 
282*e814fdddSWang Nan static int parse_events__is_name_term(struct parse_events_term *term)
283*e814fdddSWang Nan {
284*e814fdddSWang Nan 	return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
285*e814fdddSWang Nan }
2867ae92e74SYan, Zheng 
287*e814fdddSWang Nan static char *get_config_name(struct list_head *head_terms)
288*e814fdddSWang Nan {
289*e814fdddSWang Nan 	struct parse_events_term *term;
290*e814fdddSWang Nan 
291*e814fdddSWang Nan 	if (!head_terms)
292*e814fdddSWang Nan 		return NULL;
293*e814fdddSWang Nan 
294*e814fdddSWang Nan 	list_for_each_entry(term, head_terms, list)
295*e814fdddSWang Nan 		if (parse_events__is_name_term(term))
296*e814fdddSWang Nan 			return term->val.str;
297*e814fdddSWang Nan 
298*e814fdddSWang Nan 	return NULL;
299*e814fdddSWang Nan }
3007ae92e74SYan, Zheng 
301410136f5SStephane Eranian static struct perf_evsel *
302410136f5SStephane Eranian __add_event(struct list_head *list, int *idx,
3037ae92e74SYan, Zheng 	    struct perf_event_attr *attr,
304930a2e29SJiri Olsa 	    char *name, struct cpu_map *cpus,
305930a2e29SJiri Olsa 	    struct list_head *config_terms)
30689812fc8SJiri Olsa {
30789812fc8SJiri Olsa 	struct perf_evsel *evsel;
30889812fc8SJiri Olsa 
30989812fc8SJiri Olsa 	event_attr_init(attr);
31089812fc8SJiri Olsa 
311ef503831SArnaldo Carvalho de Melo 	evsel = perf_evsel__new_idx(attr, (*idx)++);
312c5cd8ac0SDavid Ahern 	if (!evsel)
313410136f5SStephane Eranian 		return NULL;
31489812fc8SJiri Olsa 
315f30a79b0SJiri Olsa 	evsel->cpus     = cpu_map__get(cpus);
316fce4d296SAdrian Hunter 	evsel->own_cpus = cpu_map__get(cpus);
317f30a79b0SJiri Olsa 
3189db1763cSArnaldo Carvalho de Melo 	if (name)
31989812fc8SJiri Olsa 		evsel->name = strdup(name);
320930a2e29SJiri Olsa 
321930a2e29SJiri Olsa 	if (config_terms)
322930a2e29SJiri Olsa 		list_splice(config_terms, &evsel->config_terms);
323930a2e29SJiri Olsa 
324b847cbdcSJiri Olsa 	list_add_tail(&evsel->node, list);
325410136f5SStephane Eranian 	return evsel;
32689812fc8SJiri Olsa }
32789812fc8SJiri Olsa 
328c5cd8ac0SDavid Ahern static int add_event(struct list_head *list, int *idx,
329930a2e29SJiri Olsa 		     struct perf_event_attr *attr, char *name,
330930a2e29SJiri Olsa 		     struct list_head *config_terms)
3317ae92e74SYan, Zheng {
332930a2e29SJiri Olsa 	return __add_event(list, idx, attr, name, NULL, config_terms) ? 0 : -ENOMEM;
3337ae92e74SYan, Zheng }
3347ae92e74SYan, Zheng 
3350b668bc9SArnaldo Carvalho de Melo static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
33686470930SIngo Molnar {
33786470930SIngo Molnar 	int i, j;
33861c45981SPaul Mackerras 	int n, longest = -1;
33986470930SIngo Molnar 
34086470930SIngo Molnar 	for (i = 0; i < size; i++) {
3410b668bc9SArnaldo Carvalho de Melo 		for (j = 0; j < PERF_EVSEL__MAX_ALIASES && names[i][j]; j++) {
34261c45981SPaul Mackerras 			n = strlen(names[i][j]);
34389812fc8SJiri Olsa 			if (n > longest && !strncasecmp(str, names[i][j], n))
34461c45981SPaul Mackerras 				longest = n;
34561c45981SPaul Mackerras 		}
34689812fc8SJiri Olsa 		if (longest > 0)
34786470930SIngo Molnar 			return i;
34886470930SIngo Molnar 	}
34986470930SIngo Molnar 
3508953645fSIngo Molnar 	return -1;
35186470930SIngo Molnar }
35286470930SIngo Molnar 
353c5cd8ac0SDavid Ahern int parse_events_add_cache(struct list_head *list, int *idx,
35489812fc8SJiri Olsa 			   char *type, char *op_result1, char *op_result2)
35586470930SIngo Molnar {
35689812fc8SJiri Olsa 	struct perf_event_attr attr;
35789812fc8SJiri Olsa 	char name[MAX_NAME_LEN];
35861c45981SPaul Mackerras 	int cache_type = -1, cache_op = -1, cache_result = -1;
35989812fc8SJiri Olsa 	char *op_result[2] = { op_result1, op_result2 };
36089812fc8SJiri Olsa 	int i, n;
36186470930SIngo Molnar 
36286470930SIngo Molnar 	/*
36386470930SIngo Molnar 	 * No fallback - if we cannot get a clear cache type
36486470930SIngo Molnar 	 * then bail out:
36586470930SIngo Molnar 	 */
3660b668bc9SArnaldo Carvalho de Melo 	cache_type = parse_aliases(type, perf_evsel__hw_cache,
36789812fc8SJiri Olsa 				   PERF_COUNT_HW_CACHE_MAX);
36886470930SIngo Molnar 	if (cache_type == -1)
36989812fc8SJiri Olsa 		return -EINVAL;
37086470930SIngo Molnar 
37189812fc8SJiri Olsa 	n = snprintf(name, MAX_NAME_LEN, "%s", type);
37289812fc8SJiri Olsa 
37389812fc8SJiri Olsa 	for (i = 0; (i < 2) && (op_result[i]); i++) {
37489812fc8SJiri Olsa 		char *str = op_result[i];
37589812fc8SJiri Olsa 
376275ef387SJiri Olsa 		n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str);
37761c45981SPaul Mackerras 
37861c45981SPaul Mackerras 		if (cache_op == -1) {
3790b668bc9SArnaldo Carvalho de Melo 			cache_op = parse_aliases(str, perf_evsel__hw_cache_op,
38061c45981SPaul Mackerras 						 PERF_COUNT_HW_CACHE_OP_MAX);
38161c45981SPaul Mackerras 			if (cache_op >= 0) {
3820b668bc9SArnaldo Carvalho de Melo 				if (!perf_evsel__is_cache_op_valid(cache_type, cache_op))
38389812fc8SJiri Olsa 					return -EINVAL;
38461c45981SPaul Mackerras 				continue;
38561c45981SPaul Mackerras 			}
38661c45981SPaul Mackerras 		}
38761c45981SPaul Mackerras 
38861c45981SPaul Mackerras 		if (cache_result == -1) {
3890b668bc9SArnaldo Carvalho de Melo 			cache_result = parse_aliases(str, perf_evsel__hw_cache_result,
39061c45981SPaul Mackerras 						     PERF_COUNT_HW_CACHE_RESULT_MAX);
39161c45981SPaul Mackerras 			if (cache_result >= 0)
39261c45981SPaul Mackerras 				continue;
39361c45981SPaul Mackerras 		}
39461c45981SPaul Mackerras 	}
39561c45981SPaul Mackerras 
39686470930SIngo Molnar 	/*
39786470930SIngo Molnar 	 * Fall back to reads:
39886470930SIngo Molnar 	 */
3998953645fSIngo Molnar 	if (cache_op == -1)
4008953645fSIngo Molnar 		cache_op = PERF_COUNT_HW_CACHE_OP_READ;
40186470930SIngo Molnar 
40286470930SIngo Molnar 	/*
40386470930SIngo Molnar 	 * Fall back to accesses:
40486470930SIngo Molnar 	 */
40586470930SIngo Molnar 	if (cache_result == -1)
40686470930SIngo Molnar 		cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
40786470930SIngo Molnar 
40889812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
40989812fc8SJiri Olsa 	attr.config = cache_type | (cache_op << 8) | (cache_result << 16);
41089812fc8SJiri Olsa 	attr.type = PERF_TYPE_HW_CACHE;
411930a2e29SJiri Olsa 	return add_event(list, idx, &attr, name, NULL);
41286470930SIngo Molnar }
41386470930SIngo Molnar 
414272ed29aSJiri Olsa static void tracepoint_error(struct parse_events_error *e, int err,
41519658171SJiri Olsa 			     char *sys, char *name)
41619658171SJiri Olsa {
41719658171SJiri Olsa 	char help[BUFSIZ];
41819658171SJiri Olsa 
419ec183d22SAdrian Hunter 	if (!e)
420ec183d22SAdrian Hunter 		return;
421ec183d22SAdrian Hunter 
42219658171SJiri Olsa 	/*
42319658171SJiri Olsa 	 * We get error directly from syscall errno ( > 0),
42419658171SJiri Olsa 	 * or from encoded pointer's error ( < 0).
42519658171SJiri Olsa 	 */
42619658171SJiri Olsa 	err = abs(err);
42719658171SJiri Olsa 
42819658171SJiri Olsa 	switch (err) {
42919658171SJiri Olsa 	case EACCES:
430272ed29aSJiri Olsa 		e->str = strdup("can't access trace events");
43119658171SJiri Olsa 		break;
43219658171SJiri Olsa 	case ENOENT:
433272ed29aSJiri Olsa 		e->str = strdup("unknown tracepoint");
43419658171SJiri Olsa 		break;
43519658171SJiri Olsa 	default:
436272ed29aSJiri Olsa 		e->str = strdup("failed to add tracepoint");
43719658171SJiri Olsa 		break;
43819658171SJiri Olsa 	}
43919658171SJiri Olsa 
44019658171SJiri Olsa 	tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name);
441272ed29aSJiri Olsa 	e->help = strdup(help);
44219658171SJiri Olsa }
44319658171SJiri Olsa 
444c5cd8ac0SDavid Ahern static int add_tracepoint(struct list_head *list, int *idx,
445e2f9f8eaSJiri Olsa 			  char *sys_name, char *evt_name,
446272ed29aSJiri Olsa 			  struct parse_events_error *err,
447e637d177SHe Kuang 			  struct list_head *head_config)
448bcd3279fSFrederic Weisbecker {
44982fe1c29SArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
450bcd3279fSFrederic Weisbecker 
451ef503831SArnaldo Carvalho de Melo 	evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++);
45219658171SJiri Olsa 	if (IS_ERR(evsel)) {
453272ed29aSJiri Olsa 		tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name);
4548dd2a131SJiri Olsa 		return PTR_ERR(evsel);
45519658171SJiri Olsa 	}
456bcd3279fSFrederic Weisbecker 
457e637d177SHe Kuang 	if (head_config) {
458e637d177SHe Kuang 		LIST_HEAD(config_terms);
459e637d177SHe Kuang 
460e637d177SHe Kuang 		if (get_config_terms(head_config, &config_terms))
461e637d177SHe Kuang 			return -ENOMEM;
462e637d177SHe Kuang 		list_splice(&config_terms, &evsel->config_terms);
463e637d177SHe Kuang 	}
464e637d177SHe Kuang 
46582fe1c29SArnaldo Carvalho de Melo 	list_add_tail(&evsel->node, list);
46682fe1c29SArnaldo Carvalho de Melo 	return 0;
467bcd3279fSFrederic Weisbecker }
468bcd3279fSFrederic Weisbecker 
469c5cd8ac0SDavid Ahern static int add_tracepoint_multi_event(struct list_head *list, int *idx,
470e2f9f8eaSJiri Olsa 				      char *sys_name, char *evt_name,
471272ed29aSJiri Olsa 				      struct parse_events_error *err,
472e637d177SHe Kuang 				      struct list_head *head_config)
473bcd3279fSFrederic Weisbecker {
474bcd3279fSFrederic Weisbecker 	char evt_path[MAXPATHLEN];
475bcd3279fSFrederic Weisbecker 	struct dirent *evt_ent;
476bcd3279fSFrederic Weisbecker 	DIR *evt_dir;
47727bf90bfSJiri Olsa 	int ret = 0, found = 0;
478bcd3279fSFrederic Weisbecker 
479ebf294bfSArnaldo Carvalho de Melo 	snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
480bcd3279fSFrederic Weisbecker 	evt_dir = opendir(evt_path);
481bcd3279fSFrederic Weisbecker 	if (!evt_dir) {
482272ed29aSJiri Olsa 		tracepoint_error(err, errno, sys_name, evt_name);
48389812fc8SJiri Olsa 		return -1;
484bcd3279fSFrederic Weisbecker 	}
485bcd3279fSFrederic Weisbecker 
48689812fc8SJiri Olsa 	while (!ret && (evt_ent = readdir(evt_dir))) {
487bcd3279fSFrederic Weisbecker 		if (!strcmp(evt_ent->d_name, ".")
488bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "..")
489bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "enable")
490bcd3279fSFrederic Weisbecker 		    || !strcmp(evt_ent->d_name, "filter"))
491bcd3279fSFrederic Weisbecker 			continue;
492bcd3279fSFrederic Weisbecker 
49389812fc8SJiri Olsa 		if (!strglobmatch(evt_ent->d_name, evt_name))
494fb1d2edfSMasami Hiramatsu 			continue;
495fb1d2edfSMasami Hiramatsu 
49627bf90bfSJiri Olsa 		found++;
49727bf90bfSJiri Olsa 
498e637d177SHe Kuang 		ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name,
499272ed29aSJiri Olsa 				     err, head_config);
500bcd3279fSFrederic Weisbecker 	}
501bcd3279fSFrederic Weisbecker 
50227bf90bfSJiri Olsa 	if (!found) {
50327bf90bfSJiri Olsa 		tracepoint_error(err, ENOENT, sys_name, evt_name);
50427bf90bfSJiri Olsa 		ret = -1;
50527bf90bfSJiri Olsa 	}
50627bf90bfSJiri Olsa 
5070bd3f084SJiri Olsa 	closedir(evt_dir);
50889812fc8SJiri Olsa 	return ret;
509bcd3279fSFrederic Weisbecker }
510bcd3279fSFrederic Weisbecker 
511c5cd8ac0SDavid Ahern static int add_tracepoint_event(struct list_head *list, int *idx,
512e2f9f8eaSJiri Olsa 				char *sys_name, char *evt_name,
513272ed29aSJiri Olsa 				struct parse_events_error *err,
514e637d177SHe Kuang 				struct list_head *head_config)
515f35488f9SJiri Olsa {
516f35488f9SJiri Olsa 	return strpbrk(evt_name, "*?") ?
517e637d177SHe Kuang 	       add_tracepoint_multi_event(list, idx, sys_name, evt_name,
518272ed29aSJiri Olsa 					  err, head_config) :
519e637d177SHe Kuang 	       add_tracepoint(list, idx, sys_name, evt_name,
520272ed29aSJiri Olsa 			      err, head_config);
521f35488f9SJiri Olsa }
522f35488f9SJiri Olsa 
523c5cd8ac0SDavid Ahern static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
524e2f9f8eaSJiri Olsa 				    char *sys_name, char *evt_name,
525272ed29aSJiri Olsa 				    struct parse_events_error *err,
526e637d177SHe Kuang 				    struct list_head *head_config)
527f35488f9SJiri Olsa {
528f35488f9SJiri Olsa 	struct dirent *events_ent;
529f35488f9SJiri Olsa 	DIR *events_dir;
530f35488f9SJiri Olsa 	int ret = 0;
531f35488f9SJiri Olsa 
532f35488f9SJiri Olsa 	events_dir = opendir(tracing_events_path);
533f35488f9SJiri Olsa 	if (!events_dir) {
534272ed29aSJiri Olsa 		tracepoint_error(err, errno, sys_name, evt_name);
535f35488f9SJiri Olsa 		return -1;
536f35488f9SJiri Olsa 	}
537f35488f9SJiri Olsa 
538f35488f9SJiri Olsa 	while (!ret && (events_ent = readdir(events_dir))) {
539f35488f9SJiri Olsa 		if (!strcmp(events_ent->d_name, ".")
540f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "..")
541f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "enable")
542f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "header_event")
543f35488f9SJiri Olsa 		    || !strcmp(events_ent->d_name, "header_page"))
544f35488f9SJiri Olsa 			continue;
545f35488f9SJiri Olsa 
546f35488f9SJiri Olsa 		if (!strglobmatch(events_ent->d_name, sys_name))
547f35488f9SJiri Olsa 			continue;
548f35488f9SJiri Olsa 
549f35488f9SJiri Olsa 		ret = add_tracepoint_event(list, idx, events_ent->d_name,
550272ed29aSJiri Olsa 					   evt_name, err, head_config);
551f35488f9SJiri Olsa 	}
552f35488f9SJiri Olsa 
553f35488f9SJiri Olsa 	closedir(events_dir);
554f35488f9SJiri Olsa 	return ret;
555f35488f9SJiri Olsa }
556f35488f9SJiri Olsa 
5574edf30e3SWang Nan struct __add_bpf_event_param {
5584edf30e3SWang Nan 	struct parse_events_evlist *data;
5594edf30e3SWang Nan 	struct list_head *list;
5604edf30e3SWang Nan };
5614edf30e3SWang Nan 
5624edf30e3SWang Nan static int add_bpf_event(struct probe_trace_event *tev, int fd,
5634edf30e3SWang Nan 			 void *_param)
5644edf30e3SWang Nan {
5654edf30e3SWang Nan 	LIST_HEAD(new_evsels);
5664edf30e3SWang Nan 	struct __add_bpf_event_param *param = _param;
5674edf30e3SWang Nan 	struct parse_events_evlist *evlist = param->data;
5684edf30e3SWang Nan 	struct list_head *list = param->list;
5691f45b1d4SWang Nan 	struct perf_evsel *pos;
5704edf30e3SWang Nan 	int err;
5714edf30e3SWang Nan 
5724edf30e3SWang Nan 	pr_debug("add bpf event %s:%s and attach bpf program %d\n",
5734edf30e3SWang Nan 		 tev->group, tev->event, fd);
5744edf30e3SWang Nan 
5754edf30e3SWang Nan 	err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group,
5764edf30e3SWang Nan 					  tev->event, evlist->error, NULL);
5774edf30e3SWang Nan 	if (err) {
5784edf30e3SWang Nan 		struct perf_evsel *evsel, *tmp;
5794edf30e3SWang Nan 
5804edf30e3SWang Nan 		pr_debug("Failed to add BPF event %s:%s\n",
5814edf30e3SWang Nan 			 tev->group, tev->event);
5824edf30e3SWang Nan 		list_for_each_entry_safe(evsel, tmp, &new_evsels, node) {
5834edf30e3SWang Nan 			list_del(&evsel->node);
5844edf30e3SWang Nan 			perf_evsel__delete(evsel);
5854edf30e3SWang Nan 		}
5864edf30e3SWang Nan 		return err;
5874edf30e3SWang Nan 	}
5884edf30e3SWang Nan 	pr_debug("adding %s:%s\n", tev->group, tev->event);
5894edf30e3SWang Nan 
5901f45b1d4SWang Nan 	list_for_each_entry(pos, &new_evsels, node) {
5911f45b1d4SWang Nan 		pr_debug("adding %s:%s to %p\n",
5921f45b1d4SWang Nan 			 tev->group, tev->event, pos);
5931f45b1d4SWang Nan 		pos->bpf_fd = fd;
5941f45b1d4SWang Nan 	}
5954edf30e3SWang Nan 	list_splice(&new_evsels, list);
5964edf30e3SWang Nan 	return 0;
5974edf30e3SWang Nan }
5984edf30e3SWang Nan 
59984c86ca1SWang Nan int parse_events_load_bpf_obj(struct parse_events_evlist *data,
60084c86ca1SWang Nan 			      struct list_head *list,
60184c86ca1SWang Nan 			      struct bpf_object *obj)
60284c86ca1SWang Nan {
60384c86ca1SWang Nan 	int err;
60484c86ca1SWang Nan 	char errbuf[BUFSIZ];
6054edf30e3SWang Nan 	struct __add_bpf_event_param param = {data, list};
606aa3abf30SWang Nan 	static bool registered_unprobe_atexit = false;
60784c86ca1SWang Nan 
60884c86ca1SWang Nan 	if (IS_ERR(obj) || !obj) {
60984c86ca1SWang Nan 		snprintf(errbuf, sizeof(errbuf),
61084c86ca1SWang Nan 			 "Internal error: load bpf obj with NULL");
61184c86ca1SWang Nan 		err = -EINVAL;
61284c86ca1SWang Nan 		goto errout;
61384c86ca1SWang Nan 	}
61484c86ca1SWang Nan 
61584c86ca1SWang Nan 	/*
616aa3abf30SWang Nan 	 * Register atexit handler before calling bpf__probe() so
617aa3abf30SWang Nan 	 * bpf__probe() don't need to unprobe probe points its already
618aa3abf30SWang Nan 	 * created when failure.
619aa3abf30SWang Nan 	 */
620aa3abf30SWang Nan 	if (!registered_unprobe_atexit) {
621aa3abf30SWang Nan 		atexit(bpf__clear);
622aa3abf30SWang Nan 		registered_unprobe_atexit = true;
623aa3abf30SWang Nan 	}
624aa3abf30SWang Nan 
625aa3abf30SWang Nan 	err = bpf__probe(obj);
626aa3abf30SWang Nan 	if (err) {
627aa3abf30SWang Nan 		bpf__strerror_probe(obj, err, errbuf, sizeof(errbuf));
628aa3abf30SWang Nan 		goto errout;
629aa3abf30SWang Nan 	}
630aa3abf30SWang Nan 
6311e5e3ee8SWang Nan 	err = bpf__load(obj);
6321e5e3ee8SWang Nan 	if (err) {
6331e5e3ee8SWang Nan 		bpf__strerror_load(obj, err, errbuf, sizeof(errbuf));
6341e5e3ee8SWang Nan 		goto errout;
6351e5e3ee8SWang Nan 	}
6361e5e3ee8SWang Nan 
6374edf30e3SWang Nan 	err = bpf__foreach_tev(obj, add_bpf_event, &param);
6384edf30e3SWang Nan 	if (err) {
6394edf30e3SWang Nan 		snprintf(errbuf, sizeof(errbuf),
6404edf30e3SWang Nan 			 "Attach events in BPF object failed");
6414edf30e3SWang Nan 		goto errout;
6424edf30e3SWang Nan 	}
6434edf30e3SWang Nan 
6444edf30e3SWang Nan 	return 0;
64584c86ca1SWang Nan errout:
64684c86ca1SWang Nan 	data->error->help = strdup("(add -v to see detail)");
64784c86ca1SWang Nan 	data->error->str = strdup(errbuf);
64884c86ca1SWang Nan 	return err;
64984c86ca1SWang Nan }
65084c86ca1SWang Nan 
65184c86ca1SWang Nan int parse_events_load_bpf(struct parse_events_evlist *data,
65284c86ca1SWang Nan 			  struct list_head *list,
653d509db04SWang Nan 			  char *bpf_file_name,
654d509db04SWang Nan 			  bool source)
65584c86ca1SWang Nan {
65684c86ca1SWang Nan 	struct bpf_object *obj;
65784c86ca1SWang Nan 
658d509db04SWang Nan 	obj = bpf__prepare_load(bpf_file_name, source);
6596371ca3bSWang Nan 	if (IS_ERR(obj)) {
66084c86ca1SWang Nan 		char errbuf[BUFSIZ];
66184c86ca1SWang Nan 		int err;
66284c86ca1SWang Nan 
6636371ca3bSWang Nan 		err = PTR_ERR(obj);
66484c86ca1SWang Nan 
66584c86ca1SWang Nan 		if (err == -ENOTSUP)
66684c86ca1SWang Nan 			snprintf(errbuf, sizeof(errbuf),
66784c86ca1SWang Nan 				 "BPF support is not compiled");
66884c86ca1SWang Nan 		else
669d3e0ce39SWang Nan 			bpf__strerror_prepare_load(bpf_file_name,
670d3e0ce39SWang Nan 						   source,
671d3e0ce39SWang Nan 						   -err, errbuf,
672d3e0ce39SWang Nan 						   sizeof(errbuf));
67384c86ca1SWang Nan 
67484c86ca1SWang Nan 		data->error->help = strdup("(add -v to see detail)");
67584c86ca1SWang Nan 		data->error->str = strdup(errbuf);
67684c86ca1SWang Nan 		return err;
67784c86ca1SWang Nan 	}
67884c86ca1SWang Nan 
67984c86ca1SWang Nan 	return parse_events_load_bpf_obj(data, list, obj);
68084c86ca1SWang Nan }
68184c86ca1SWang Nan 
68289812fc8SJiri Olsa static int
68389812fc8SJiri Olsa parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
6841b290d67SFrederic Weisbecker {
6851b290d67SFrederic Weisbecker 	int i;
6861b290d67SFrederic Weisbecker 
6871b290d67SFrederic Weisbecker 	for (i = 0; i < 3; i++) {
68889812fc8SJiri Olsa 		if (!type || !type[i])
6891b290d67SFrederic Weisbecker 			break;
6901b290d67SFrederic Weisbecker 
6917582732fSJiri Olsa #define CHECK_SET_TYPE(bit)		\
6927582732fSJiri Olsa do {					\
6937582732fSJiri Olsa 	if (attr->bp_type & bit)	\
6947582732fSJiri Olsa 		return -EINVAL;		\
6957582732fSJiri Olsa 	else				\
6967582732fSJiri Olsa 		attr->bp_type |= bit;	\
6977582732fSJiri Olsa } while (0)
6987582732fSJiri Olsa 
6991b290d67SFrederic Weisbecker 		switch (type[i]) {
7001b290d67SFrederic Weisbecker 		case 'r':
7017582732fSJiri Olsa 			CHECK_SET_TYPE(HW_BREAKPOINT_R);
7021b290d67SFrederic Weisbecker 			break;
7031b290d67SFrederic Weisbecker 		case 'w':
7047582732fSJiri Olsa 			CHECK_SET_TYPE(HW_BREAKPOINT_W);
7051b290d67SFrederic Weisbecker 			break;
7061b290d67SFrederic Weisbecker 		case 'x':
7077582732fSJiri Olsa 			CHECK_SET_TYPE(HW_BREAKPOINT_X);
7081b290d67SFrederic Weisbecker 			break;
7091b290d67SFrederic Weisbecker 		default:
71089812fc8SJiri Olsa 			return -EINVAL;
7111b290d67SFrederic Weisbecker 		}
7121b290d67SFrederic Weisbecker 	}
71389812fc8SJiri Olsa 
7147582732fSJiri Olsa #undef CHECK_SET_TYPE
7157582732fSJiri Olsa 
7161b290d67SFrederic Weisbecker 	if (!attr->bp_type) /* Default */
7171b290d67SFrederic Weisbecker 		attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
7181b290d67SFrederic Weisbecker 
71989812fc8SJiri Olsa 	return 0;
7201b290d67SFrederic Weisbecker }
7211b290d67SFrederic Weisbecker 
722c5cd8ac0SDavid Ahern int parse_events_add_breakpoint(struct list_head *list, int *idx,
7233741eb9fSJacob Shin 				void *ptr, char *type, u64 len)
7241b290d67SFrederic Weisbecker {
72589812fc8SJiri Olsa 	struct perf_event_attr attr;
7261b290d67SFrederic Weisbecker 
72789812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
7289fafd98fSJiri Olsa 	attr.bp_addr = (unsigned long) ptr;
7291b290d67SFrederic Weisbecker 
73089812fc8SJiri Olsa 	if (parse_breakpoint_type(type, &attr))
73189812fc8SJiri Olsa 		return -EINVAL;
7321b290d67SFrederic Weisbecker 
7333741eb9fSJacob Shin 	/* Provide some defaults if len is not specified */
7343741eb9fSJacob Shin 	if (!len) {
73589812fc8SJiri Olsa 		if (attr.bp_type == HW_BREAKPOINT_X)
7363741eb9fSJacob Shin 			len = sizeof(long);
737aa59a485SFrederic Weisbecker 		else
7383741eb9fSJacob Shin 			len = HW_BREAKPOINT_LEN_4;
7393741eb9fSJacob Shin 	}
7403741eb9fSJacob Shin 
7413741eb9fSJacob Shin 	attr.bp_len = len;
742aa59a485SFrederic Weisbecker 
74389812fc8SJiri Olsa 	attr.type = PERF_TYPE_BREAKPOINT;
7444a841d65SJovi Zhang 	attr.sample_period = 1;
7451b290d67SFrederic Weisbecker 
746930a2e29SJiri Olsa 	return add_event(list, idx, &attr, NULL, NULL);
7471b290d67SFrederic Weisbecker }
7481b290d67SFrederic Weisbecker 
7493b0e371cSJiri Olsa static int check_type_val(struct parse_events_term *term,
7503b0e371cSJiri Olsa 			  struct parse_events_error *err,
7513b0e371cSJiri Olsa 			  int type)
7523b0e371cSJiri Olsa {
7533b0e371cSJiri Olsa 	if (type == term->type_val)
7543b0e371cSJiri Olsa 		return 0;
7553b0e371cSJiri Olsa 
7563b0e371cSJiri Olsa 	if (err) {
7573b0e371cSJiri Olsa 		err->idx = term->err_val;
7583b0e371cSJiri Olsa 		if (type == PARSE_EVENTS__TERM_TYPE_NUM)
7593b0e371cSJiri Olsa 			err->str = strdup("expected numeric value");
7603b0e371cSJiri Olsa 		else
7613b0e371cSJiri Olsa 			err->str = strdup("expected string value");
7623b0e371cSJiri Olsa 	}
7633b0e371cSJiri Olsa 	return -EINVAL;
7643b0e371cSJiri Olsa }
7653b0e371cSJiri Olsa 
76617cb5f84SWang Nan /*
76717cb5f84SWang Nan  * Update according to parse-events.l
76817cb5f84SWang Nan  */
76917cb5f84SWang Nan static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
77017cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_USER]			= "<sysfs term>",
77117cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CONFIG]		= "config",
77217cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CONFIG1]		= "config1",
77317cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CONFIG2]		= "config2",
77417cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_NAME]			= "name",
77517cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD]		= "period",
77617cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ]		= "freq",
77717cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE]	= "branch_type",
77817cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_TIME]			= "time",
77917cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_CALLGRAPH]		= "call-graph",
78017cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_STACKSIZE]		= "stack-size",
78117cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_NOINHERIT]		= "no-inherit",
78217cb5f84SWang Nan 	[PARSE_EVENTS__TERM_TYPE_INHERIT]		= "inherit",
78317cb5f84SWang Nan };
78417cb5f84SWang Nan 
7851669e509SWang Nan static bool config_term_shrinked;
7861669e509SWang Nan 
7871669e509SWang Nan static bool
7881669e509SWang Nan config_term_avail(int term_type, struct parse_events_error *err)
7891669e509SWang Nan {
7901669e509SWang Nan 	if (term_type < 0 || term_type >= __PARSE_EVENTS__TERM_TYPE_NR) {
7911669e509SWang Nan 		err->str = strdup("Invalid term_type");
7921669e509SWang Nan 		return false;
7931669e509SWang Nan 	}
7941669e509SWang Nan 	if (!config_term_shrinked)
7951669e509SWang Nan 		return true;
7961669e509SWang Nan 
7971669e509SWang Nan 	switch (term_type) {
7981669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_CONFIG:
7991669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_CONFIG1:
8001669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_CONFIG2:
8011669e509SWang Nan 	case PARSE_EVENTS__TERM_TYPE_NAME:
8021669e509SWang Nan 		return true;
8031669e509SWang Nan 	default:
8041669e509SWang Nan 		if (!err)
8051669e509SWang Nan 			return false;
8061669e509SWang Nan 
8071669e509SWang Nan 		/* term_type is validated so indexing is safe */
8081669e509SWang Nan 		if (asprintf(&err->str, "'%s' is not usable in 'perf stat'",
8091669e509SWang Nan 			     config_term_names[term_type]) < 0)
8101669e509SWang Nan 			err->str = NULL;
8111669e509SWang Nan 		return false;
8121669e509SWang Nan 	}
8131669e509SWang Nan }
8141669e509SWang Nan 
8151669e509SWang Nan void parse_events__shrink_config_terms(void)
8161669e509SWang Nan {
8171669e509SWang Nan 	config_term_shrinked = true;
8181669e509SWang Nan }
8191669e509SWang Nan 
8200b8891a8SHe Kuang typedef int config_term_func_t(struct perf_event_attr *attr,
8210b8891a8SHe Kuang 			       struct parse_events_term *term,
8220b8891a8SHe Kuang 			       struct parse_events_error *err);
8230b8891a8SHe Kuang 
8240b8891a8SHe Kuang static int config_term_common(struct perf_event_attr *attr,
8253b0e371cSJiri Olsa 			      struct parse_events_term *term,
8263b0e371cSJiri Olsa 			      struct parse_events_error *err)
8278f707d84SJiri Olsa {
82816fa7e82SJiri Olsa #define CHECK_TYPE_VAL(type)						   \
82916fa7e82SJiri Olsa do {									   \
8303b0e371cSJiri Olsa 	if (check_type_val(term, err, PARSE_EVENTS__TERM_TYPE_ ## type)) \
83116fa7e82SJiri Olsa 		return -EINVAL;						   \
83216fa7e82SJiri Olsa } while (0)
83316fa7e82SJiri Olsa 
83416fa7e82SJiri Olsa 	switch (term->type_term) {
8358f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG:
83616fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
8378f707d84SJiri Olsa 		attr->config = term->val.num;
8388f707d84SJiri Olsa 		break;
8398f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG1:
84016fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
8418f707d84SJiri Olsa 		attr->config1 = term->val.num;
8428f707d84SJiri Olsa 		break;
8438f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_CONFIG2:
84416fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
8458f707d84SJiri Olsa 		attr->config2 = term->val.num;
8468f707d84SJiri Olsa 		break;
8478f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
84816fa7e82SJiri Olsa 		CHECK_TYPE_VAL(NUM);
8498f707d84SJiri Olsa 		break;
85009af2a55SNamhyung Kim 	case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ:
85109af2a55SNamhyung Kim 		CHECK_TYPE_VAL(NUM);
85209af2a55SNamhyung Kim 		break;
8538f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
8548f707d84SJiri Olsa 		/*
8558f707d84SJiri Olsa 		 * TODO uncomment when the field is available
8568f707d84SJiri Olsa 		 * attr->branch_sample_type = term->val.num;
8578f707d84SJiri Olsa 		 */
8588f707d84SJiri Olsa 		break;
85932067712SKan Liang 	case PARSE_EVENTS__TERM_TYPE_TIME:
86032067712SKan Liang 		CHECK_TYPE_VAL(NUM);
86132067712SKan Liang 		if (term->val.num > 1) {
86232067712SKan Liang 			err->str = strdup("expected 0 or 1");
86332067712SKan Liang 			err->idx = term->err_val;
86432067712SKan Liang 			return -EINVAL;
86532067712SKan Liang 		}
86632067712SKan Liang 		break;
867d457c963SKan Liang 	case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
868d457c963SKan Liang 		CHECK_TYPE_VAL(STR);
869d457c963SKan Liang 		break;
870d457c963SKan Liang 	case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
871d457c963SKan Liang 		CHECK_TYPE_VAL(NUM);
872d457c963SKan Liang 		break;
873374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_INHERIT:
874374ce938SWang Nan 		CHECK_TYPE_VAL(NUM);
875374ce938SWang Nan 		break;
876374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
877374ce938SWang Nan 		CHECK_TYPE_VAL(NUM);
878374ce938SWang Nan 		break;
8796b5fc39bSJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_NAME:
8806b5fc39bSJiri Olsa 		CHECK_TYPE_VAL(STR);
8816b5fc39bSJiri Olsa 		break;
8828f707d84SJiri Olsa 	default:
883ffeb883eSHe Kuang 		err->str = strdup("unknown term");
884ffeb883eSHe Kuang 		err->idx = term->err_term;
885ffeb883eSHe Kuang 		err->help = parse_events_formats_error_string(NULL);
8868f707d84SJiri Olsa 		return -EINVAL;
8878f707d84SJiri Olsa 	}
88816fa7e82SJiri Olsa 
8891669e509SWang Nan 	/*
8901669e509SWang Nan 	 * Check term availbility after basic checking so
8911669e509SWang Nan 	 * PARSE_EVENTS__TERM_TYPE_USER can be found and filtered.
8921669e509SWang Nan 	 *
8931669e509SWang Nan 	 * If check availbility at the entry of this function,
8941669e509SWang Nan 	 * user will see "'<sysfs term>' is not usable in 'perf stat'"
8951669e509SWang Nan 	 * if an invalid config term is provided for legacy events
8961669e509SWang Nan 	 * (for example, instructions/badterm/...), which is confusing.
8971669e509SWang Nan 	 */
8981669e509SWang Nan 	if (!config_term_avail(term->type_term, err))
8991669e509SWang Nan 		return -EINVAL;
9008f707d84SJiri Olsa 	return 0;
90116fa7e82SJiri Olsa #undef CHECK_TYPE_VAL
9028f707d84SJiri Olsa }
9038f707d84SJiri Olsa 
9040b8891a8SHe Kuang static int config_term_pmu(struct perf_event_attr *attr,
9050b8891a8SHe Kuang 			   struct parse_events_term *term,
9060b8891a8SHe Kuang 			   struct parse_events_error *err)
9070b8891a8SHe Kuang {
9080b8891a8SHe Kuang 	if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER)
9090b8891a8SHe Kuang 		/*
9100b8891a8SHe Kuang 		 * Always succeed for sysfs terms, as we dont know
9110b8891a8SHe Kuang 		 * at this point what type they need to have.
9120b8891a8SHe Kuang 		 */
9130b8891a8SHe Kuang 		return 0;
9140b8891a8SHe Kuang 	else
9150b8891a8SHe Kuang 		return config_term_common(attr, term, err);
9160b8891a8SHe Kuang }
9170b8891a8SHe Kuang 
918e637d177SHe Kuang static int config_term_tracepoint(struct perf_event_attr *attr,
919e637d177SHe Kuang 				  struct parse_events_term *term,
920e637d177SHe Kuang 				  struct parse_events_error *err)
921e637d177SHe Kuang {
922e637d177SHe Kuang 	switch (term->type_term) {
923e637d177SHe Kuang 	case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
924e637d177SHe Kuang 	case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
925374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_INHERIT:
926374ce938SWang Nan 	case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
927e637d177SHe Kuang 		return config_term_common(attr, term, err);
928e637d177SHe Kuang 	default:
929e637d177SHe Kuang 		if (err) {
930e637d177SHe Kuang 			err->idx = term->err_term;
931e637d177SHe Kuang 			err->str = strdup("unknown term");
932e637d177SHe Kuang 			err->help = strdup("valid terms: call-graph,stack-size\n");
933e637d177SHe Kuang 		}
934e637d177SHe Kuang 		return -EINVAL;
935e637d177SHe Kuang 	}
936e637d177SHe Kuang 
937e637d177SHe Kuang 	return 0;
938e637d177SHe Kuang }
939e637d177SHe Kuang 
9408f707d84SJiri Olsa static int config_attr(struct perf_event_attr *attr,
9413b0e371cSJiri Olsa 		       struct list_head *head,
9420b8891a8SHe Kuang 		       struct parse_events_error *err,
9430b8891a8SHe Kuang 		       config_term_func_t config_term)
9448f707d84SJiri Olsa {
9456cee6cd3SArnaldo Carvalho de Melo 	struct parse_events_term *term;
9468f707d84SJiri Olsa 
9478f707d84SJiri Olsa 	list_for_each_entry(term, head, list)
9483b0e371cSJiri Olsa 		if (config_term(attr, term, err))
9498f707d84SJiri Olsa 			return -EINVAL;
9508f707d84SJiri Olsa 
9518f707d84SJiri Olsa 	return 0;
9528f707d84SJiri Olsa }
9538f707d84SJiri Olsa 
954930a2e29SJiri Olsa static int get_config_terms(struct list_head *head_config,
955930a2e29SJiri Olsa 			    struct list_head *head_terms __maybe_unused)
956930a2e29SJiri Olsa {
957930a2e29SJiri Olsa #define ADD_CONFIG_TERM(__type, __name, __val)			\
958930a2e29SJiri Olsa do {								\
959930a2e29SJiri Olsa 	struct perf_evsel_config_term *__t;			\
960930a2e29SJiri Olsa 								\
961930a2e29SJiri Olsa 	__t = zalloc(sizeof(*__t));				\
962930a2e29SJiri Olsa 	if (!__t)						\
963930a2e29SJiri Olsa 		return -ENOMEM;					\
964930a2e29SJiri Olsa 								\
965930a2e29SJiri Olsa 	INIT_LIST_HEAD(&__t->list);				\
966930a2e29SJiri Olsa 	__t->type       = PERF_EVSEL__CONFIG_TERM_ ## __type;	\
967930a2e29SJiri Olsa 	__t->val.__name = __val;				\
968930a2e29SJiri Olsa 	list_add_tail(&__t->list, head_terms);			\
969930a2e29SJiri Olsa } while (0)
970930a2e29SJiri Olsa 
971930a2e29SJiri Olsa 	struct parse_events_term *term;
972930a2e29SJiri Olsa 
973930a2e29SJiri Olsa 	list_for_each_entry(term, head_config, list) {
974930a2e29SJiri Olsa 		switch (term->type_term) {
975ee4c7588SJiri Olsa 		case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
976ee4c7588SJiri Olsa 			ADD_CONFIG_TERM(PERIOD, period, term->val.num);
97732067712SKan Liang 			break;
97809af2a55SNamhyung Kim 		case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ:
97909af2a55SNamhyung Kim 			ADD_CONFIG_TERM(FREQ, freq, term->val.num);
98009af2a55SNamhyung Kim 			break;
98132067712SKan Liang 		case PARSE_EVENTS__TERM_TYPE_TIME:
98232067712SKan Liang 			ADD_CONFIG_TERM(TIME, time, term->val.num);
98332067712SKan Liang 			break;
984d457c963SKan Liang 		case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
985d457c963SKan Liang 			ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str);
986d457c963SKan Liang 			break;
987d457c963SKan Liang 		case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
988d457c963SKan Liang 			ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num);
989d457c963SKan Liang 			break;
990374ce938SWang Nan 		case PARSE_EVENTS__TERM_TYPE_INHERIT:
991374ce938SWang Nan 			ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 1 : 0);
992374ce938SWang Nan 			break;
993374ce938SWang Nan 		case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
994374ce938SWang Nan 			ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1);
995374ce938SWang Nan 			break;
996930a2e29SJiri Olsa 		default:
997930a2e29SJiri Olsa 			break;
998930a2e29SJiri Olsa 		}
999930a2e29SJiri Olsa 	}
1000930a2e29SJiri Olsa #undef ADD_EVSEL_CONFIG
1001930a2e29SJiri Olsa 	return 0;
1002930a2e29SJiri Olsa }
1003930a2e29SJiri Olsa 
1004e637d177SHe Kuang int parse_events_add_tracepoint(struct list_head *list, int *idx,
1005e637d177SHe Kuang 				char *sys, char *event,
1006272ed29aSJiri Olsa 				struct parse_events_error *err,
1007e637d177SHe Kuang 				struct list_head *head_config)
1008e637d177SHe Kuang {
1009e637d177SHe Kuang 	if (head_config) {
1010e637d177SHe Kuang 		struct perf_event_attr attr;
1011e637d177SHe Kuang 
1012272ed29aSJiri Olsa 		if (config_attr(&attr, head_config, err,
1013e637d177SHe Kuang 				config_term_tracepoint))
1014e637d177SHe Kuang 			return -EINVAL;
1015e637d177SHe Kuang 	}
1016e637d177SHe Kuang 
1017e637d177SHe Kuang 	if (strpbrk(sys, "*?"))
1018e637d177SHe Kuang 		return add_tracepoint_multi_sys(list, idx, sys, event,
1019272ed29aSJiri Olsa 						err, head_config);
1020e637d177SHe Kuang 	else
1021e637d177SHe Kuang 		return add_tracepoint_event(list, idx, sys, event,
1022272ed29aSJiri Olsa 					    err, head_config);
1023e637d177SHe Kuang }
1024e637d177SHe Kuang 
102587d650beSJiri Olsa int parse_events_add_numeric(struct parse_events_evlist *data,
102687d650beSJiri Olsa 			     struct list_head *list,
1027b527bab5SRobert Richter 			     u32 type, u64 config,
10288f707d84SJiri Olsa 			     struct list_head *head_config)
102974d5b588SJaswinder Singh Rajput {
103089812fc8SJiri Olsa 	struct perf_event_attr attr;
1031930a2e29SJiri Olsa 	LIST_HEAD(config_terms);
103274d5b588SJaswinder Singh Rajput 
103389812fc8SJiri Olsa 	memset(&attr, 0, sizeof(attr));
103489812fc8SJiri Olsa 	attr.type = type;
103589812fc8SJiri Olsa 	attr.config = config;
10368f707d84SJiri Olsa 
1037930a2e29SJiri Olsa 	if (head_config) {
10380b8891a8SHe Kuang 		if (config_attr(&attr, head_config, data->error,
10390b8891a8SHe Kuang 				config_term_common))
10408f707d84SJiri Olsa 			return -EINVAL;
10418f707d84SJiri Olsa 
1042930a2e29SJiri Olsa 		if (get_config_terms(head_config, &config_terms))
1043930a2e29SJiri Olsa 			return -ENOMEM;
1044930a2e29SJiri Olsa 	}
1045930a2e29SJiri Olsa 
1046930a2e29SJiri Olsa 	return add_event(list, &data->idx, &attr, NULL, &config_terms);
1047b908debdSIngo Molnar }
1048b908debdSIngo Molnar 
104936adec85SJiri Olsa int parse_events_add_pmu(struct parse_events_evlist *data,
105036adec85SJiri Olsa 			 struct list_head *list, char *name,
105136adec85SJiri Olsa 			 struct list_head *head_config)
10525f537a26SJiri Olsa {
10535f537a26SJiri Olsa 	struct perf_event_attr attr;
105446441bdcSMatt Fleming 	struct perf_pmu_info info;
10555f537a26SJiri Olsa 	struct perf_pmu *pmu;
1056410136f5SStephane Eranian 	struct perf_evsel *evsel;
1057930a2e29SJiri Olsa 	LIST_HEAD(config_terms);
10585f537a26SJiri Olsa 
10595f537a26SJiri Olsa 	pmu = perf_pmu__find(name);
10605f537a26SJiri Olsa 	if (!pmu)
10615f537a26SJiri Olsa 		return -EINVAL;
10625f537a26SJiri Olsa 
1063dc0a6202SAdrian Hunter 	if (pmu->default_config) {
1064dc0a6202SAdrian Hunter 		memcpy(&attr, pmu->default_config,
1065dc0a6202SAdrian Hunter 		       sizeof(struct perf_event_attr));
1066dc0a6202SAdrian Hunter 	} else {
10675f537a26SJiri Olsa 		memset(&attr, 0, sizeof(attr));
1068dc0a6202SAdrian Hunter 	}
10695f537a26SJiri Olsa 
1070ad962273SAdrian Hunter 	if (!head_config) {
1071ad962273SAdrian Hunter 		attr.type = pmu->type;
1072930a2e29SJiri Olsa 		evsel = __add_event(list, &data->idx, &attr, NULL, pmu->cpus, NULL);
1073ad962273SAdrian Hunter 		return evsel ? 0 : -ENOMEM;
1074ad962273SAdrian Hunter 	}
1075ad962273SAdrian Hunter 
107646441bdcSMatt Fleming 	if (perf_pmu__check_alias(pmu, head_config, &info))
1077a6146d50SZheng Yan 		return -EINVAL;
1078a6146d50SZheng Yan 
10795f537a26SJiri Olsa 	/*
10805f537a26SJiri Olsa 	 * Configure hardcoded terms first, no need to check
10815f537a26SJiri Olsa 	 * return value when called with fail == 0 ;)
10825f537a26SJiri Olsa 	 */
10830b8891a8SHe Kuang 	if (config_attr(&attr, head_config, data->error, config_term_pmu))
1084c056ba6aSJiri Olsa 		return -EINVAL;
10855f537a26SJiri Olsa 
1086930a2e29SJiri Olsa 	if (get_config_terms(head_config, &config_terms))
1087930a2e29SJiri Olsa 		return -ENOMEM;
1088930a2e29SJiri Olsa 
1089e64b020bSJiri Olsa 	if (perf_pmu__config(pmu, &attr, head_config, data->error))
10905f537a26SJiri Olsa 		return -EINVAL;
10915f537a26SJiri Olsa 
109236adec85SJiri Olsa 	evsel = __add_event(list, &data->idx, &attr,
1093*e814fdddSWang Nan 			    get_config_name(head_config), pmu->cpus,
1094930a2e29SJiri Olsa 			    &config_terms);
1095410136f5SStephane Eranian 	if (evsel) {
109646441bdcSMatt Fleming 		evsel->unit = info.unit;
109746441bdcSMatt Fleming 		evsel->scale = info.scale;
1098044330c1SMatt Fleming 		evsel->per_pkg = info.per_pkg;
10991d9e446bSJiri Olsa 		evsel->snapshot = info.snapshot;
1100410136f5SStephane Eranian 	}
1101410136f5SStephane Eranian 
1102410136f5SStephane Eranian 	return evsel ? 0 : -ENOMEM;
11035f537a26SJiri Olsa }
11045f537a26SJiri Olsa 
11056a4bb04cSJiri Olsa int parse_events__modifier_group(struct list_head *list,
11066a4bb04cSJiri Olsa 				 char *event_mod)
110789efb029SJiri Olsa {
11086a4bb04cSJiri Olsa 	return parse_events__modifier_event(list, event_mod, true);
11096a4bb04cSJiri Olsa }
11106a4bb04cSJiri Olsa 
111163dab225SArnaldo Carvalho de Melo void parse_events__set_leader(char *name, struct list_head *list)
11126a4bb04cSJiri Olsa {
11136a4bb04cSJiri Olsa 	struct perf_evsel *leader;
11146a4bb04cSJiri Olsa 
1115854f7363SWang Nan 	if (list_empty(list)) {
1116854f7363SWang Nan 		WARN_ONCE(true, "WARNING: failed to set leader: empty list");
1117854f7363SWang Nan 		return;
1118854f7363SWang Nan 	}
1119854f7363SWang Nan 
112063dab225SArnaldo Carvalho de Melo 	__perf_evlist__set_leader(list);
112163dab225SArnaldo Carvalho de Melo 	leader = list_entry(list->next, struct perf_evsel, node);
11226a4bb04cSJiri Olsa 	leader->group_name = name ? strdup(name) : NULL;
112389efb029SJiri Olsa }
112489efb029SJiri Olsa 
1125c5cd8ac0SDavid Ahern /* list_event is assumed to point to malloc'ed memory */
11265d7be90eSJiri Olsa void parse_events_update_lists(struct list_head *list_event,
11275d7be90eSJiri Olsa 			       struct list_head *list_all)
11285d7be90eSJiri Olsa {
11295d7be90eSJiri Olsa 	/*
11305d7be90eSJiri Olsa 	 * Called for single event definition. Update the
113189efb029SJiri Olsa 	 * 'all event' list, and reinit the 'single event'
11325d7be90eSJiri Olsa 	 * list, for next event definition.
11335d7be90eSJiri Olsa 	 */
11345d7be90eSJiri Olsa 	list_splice_tail(list_event, list_all);
1135b847cbdcSJiri Olsa 	free(list_event);
11365d7be90eSJiri Olsa }
11375d7be90eSJiri Olsa 
1138f5b1135bSJiri Olsa struct event_modifier {
1139f5b1135bSJiri Olsa 	int eu;
1140f5b1135bSJiri Olsa 	int ek;
1141f5b1135bSJiri Olsa 	int eh;
1142f5b1135bSJiri Olsa 	int eH;
1143f5b1135bSJiri Olsa 	int eG;
1144a1e12da4SJiri Olsa 	int eI;
1145f5b1135bSJiri Olsa 	int precise;
11467f94af7aSJiri Olsa 	int precise_max;
1147f5b1135bSJiri Olsa 	int exclude_GH;
11483c176311SJiri Olsa 	int sample_read;
1149e9a7c414SMichael Ellerman 	int pinned;
1150f5b1135bSJiri Olsa };
115161c45981SPaul Mackerras 
1152f5b1135bSJiri Olsa static int get_event_modifier(struct event_modifier *mod, char *str,
1153f5b1135bSJiri Olsa 			       struct perf_evsel *evsel)
1154f5b1135bSJiri Olsa {
1155f5b1135bSJiri Olsa 	int eu = evsel ? evsel->attr.exclude_user : 0;
1156f5b1135bSJiri Olsa 	int ek = evsel ? evsel->attr.exclude_kernel : 0;
1157f5b1135bSJiri Olsa 	int eh = evsel ? evsel->attr.exclude_hv : 0;
1158f5b1135bSJiri Olsa 	int eH = evsel ? evsel->attr.exclude_host : 0;
1159f5b1135bSJiri Olsa 	int eG = evsel ? evsel->attr.exclude_guest : 0;
1160a1e12da4SJiri Olsa 	int eI = evsel ? evsel->attr.exclude_idle : 0;
1161f5b1135bSJiri Olsa 	int precise = evsel ? evsel->attr.precise_ip : 0;
11627f94af7aSJiri Olsa 	int precise_max = 0;
11633c176311SJiri Olsa 	int sample_read = 0;
1164e9a7c414SMichael Ellerman 	int pinned = evsel ? evsel->attr.pinned : 0;
1165f5b1135bSJiri Olsa 
1166f5b1135bSJiri Olsa 	int exclude = eu | ek | eh;
1167f5b1135bSJiri Olsa 	int exclude_GH = evsel ? evsel->exclude_GH : 0;
1168f5b1135bSJiri Olsa 
1169f5b1135bSJiri Olsa 	memset(mod, 0, sizeof(*mod));
1170ceb53fbfSIngo Molnar 
117161c45981SPaul Mackerras 	while (*str) {
1172ab608344SPeter Zijlstra 		if (*str == 'u') {
1173ab608344SPeter Zijlstra 			if (!exclude)
1174ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
117561c45981SPaul Mackerras 			eu = 0;
1176ab608344SPeter Zijlstra 		} else if (*str == 'k') {
1177ab608344SPeter Zijlstra 			if (!exclude)
1178ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
117961c45981SPaul Mackerras 			ek = 0;
1180ab608344SPeter Zijlstra 		} else if (*str == 'h') {
1181ab608344SPeter Zijlstra 			if (!exclude)
1182ab608344SPeter Zijlstra 				exclude = eu = ek = eh = 1;
118361c45981SPaul Mackerras 			eh = 0;
118499320cc8SJoerg Roedel 		} else if (*str == 'G') {
118599320cc8SJoerg Roedel 			if (!exclude_GH)
118699320cc8SJoerg Roedel 				exclude_GH = eG = eH = 1;
118799320cc8SJoerg Roedel 			eG = 0;
118899320cc8SJoerg Roedel 		} else if (*str == 'H') {
118999320cc8SJoerg Roedel 			if (!exclude_GH)
119099320cc8SJoerg Roedel 				exclude_GH = eG = eH = 1;
119199320cc8SJoerg Roedel 			eH = 0;
1192a1e12da4SJiri Olsa 		} else if (*str == 'I') {
1193a1e12da4SJiri Olsa 			eI = 1;
1194ab608344SPeter Zijlstra 		} else if (*str == 'p') {
1195ab608344SPeter Zijlstra 			precise++;
11961342798cSDavid Ahern 			/* use of precise requires exclude_guest */
11971342798cSDavid Ahern 			if (!exclude_GH)
11981342798cSDavid Ahern 				eG = 1;
11997f94af7aSJiri Olsa 		} else if (*str == 'P') {
12007f94af7aSJiri Olsa 			precise_max = 1;
12013c176311SJiri Olsa 		} else if (*str == 'S') {
12023c176311SJiri Olsa 			sample_read = 1;
1203e9a7c414SMichael Ellerman 		} else if (*str == 'D') {
1204e9a7c414SMichael Ellerman 			pinned = 1;
1205ab608344SPeter Zijlstra 		} else
120661c45981SPaul Mackerras 			break;
1207ab608344SPeter Zijlstra 
120861c45981SPaul Mackerras 		++str;
120961c45981SPaul Mackerras 	}
121074d5b588SJaswinder Singh Rajput 
121186470930SIngo Molnar 	/*
121289812fc8SJiri Olsa 	 * precise ip:
121389812fc8SJiri Olsa 	 *
121489812fc8SJiri Olsa 	 *  0 - SAMPLE_IP can have arbitrary skid
121589812fc8SJiri Olsa 	 *  1 - SAMPLE_IP must have constant skid
121689812fc8SJiri Olsa 	 *  2 - SAMPLE_IP requested to have 0 skid
121789812fc8SJiri Olsa 	 *  3 - SAMPLE_IP must have 0 skid
121889812fc8SJiri Olsa 	 *
121989812fc8SJiri Olsa 	 *  See also PERF_RECORD_MISC_EXACT_IP
122086470930SIngo Molnar 	 */
122189812fc8SJiri Olsa 	if (precise > 3)
122289812fc8SJiri Olsa 		return -EINVAL;
122386470930SIngo Molnar 
1224f5b1135bSJiri Olsa 	mod->eu = eu;
1225f5b1135bSJiri Olsa 	mod->ek = ek;
1226f5b1135bSJiri Olsa 	mod->eh = eh;
1227f5b1135bSJiri Olsa 	mod->eH = eH;
1228f5b1135bSJiri Olsa 	mod->eG = eG;
1229a1e12da4SJiri Olsa 	mod->eI = eI;
1230f5b1135bSJiri Olsa 	mod->precise = precise;
12317f94af7aSJiri Olsa 	mod->precise_max = precise_max;
1232f5b1135bSJiri Olsa 	mod->exclude_GH = exclude_GH;
12333c176311SJiri Olsa 	mod->sample_read = sample_read;
1234e9a7c414SMichael Ellerman 	mod->pinned = pinned;
1235e9a7c414SMichael Ellerman 
1236f5b1135bSJiri Olsa 	return 0;
1237f5b1135bSJiri Olsa }
1238f5b1135bSJiri Olsa 
1239534123f4SJiri Olsa /*
1240534123f4SJiri Olsa  * Basic modifier sanity check to validate it contains only one
1241534123f4SJiri Olsa  * instance of any modifier (apart from 'p') present.
1242534123f4SJiri Olsa  */
1243534123f4SJiri Olsa static int check_modifier(char *str)
1244534123f4SJiri Olsa {
1245534123f4SJiri Olsa 	char *p = str;
1246534123f4SJiri Olsa 
1247534123f4SJiri Olsa 	/* The sizeof includes 0 byte as well. */
12487f94af7aSJiri Olsa 	if (strlen(str) > (sizeof("ukhGHpppPSDI") - 1))
1249534123f4SJiri Olsa 		return -1;
1250534123f4SJiri Olsa 
1251534123f4SJiri Olsa 	while (*p) {
1252534123f4SJiri Olsa 		if (*p != 'p' && strchr(p + 1, *p))
1253534123f4SJiri Olsa 			return -1;
1254534123f4SJiri Olsa 		p++;
1255534123f4SJiri Olsa 	}
1256534123f4SJiri Olsa 
1257534123f4SJiri Olsa 	return 0;
1258534123f4SJiri Olsa }
1259534123f4SJiri Olsa 
1260f5b1135bSJiri Olsa int parse_events__modifier_event(struct list_head *list, char *str, bool add)
1261f5b1135bSJiri Olsa {
1262f5b1135bSJiri Olsa 	struct perf_evsel *evsel;
1263f5b1135bSJiri Olsa 	struct event_modifier mod;
1264f5b1135bSJiri Olsa 
1265f5b1135bSJiri Olsa 	if (str == NULL)
1266f5b1135bSJiri Olsa 		return 0;
1267f5b1135bSJiri Olsa 
1268534123f4SJiri Olsa 	if (check_modifier(str))
1269534123f4SJiri Olsa 		return -EINVAL;
1270534123f4SJiri Olsa 
1271f5b1135bSJiri Olsa 	if (!add && get_event_modifier(&mod, str, NULL))
1272f5b1135bSJiri Olsa 		return -EINVAL;
1273f5b1135bSJiri Olsa 
12740050f7aaSArnaldo Carvalho de Melo 	__evlist__for_each(list, evsel) {
1275f5b1135bSJiri Olsa 		if (add && get_event_modifier(&mod, str, evsel))
1276f5b1135bSJiri Olsa 			return -EINVAL;
1277f5b1135bSJiri Olsa 
1278f5b1135bSJiri Olsa 		evsel->attr.exclude_user   = mod.eu;
1279f5b1135bSJiri Olsa 		evsel->attr.exclude_kernel = mod.ek;
1280f5b1135bSJiri Olsa 		evsel->attr.exclude_hv     = mod.eh;
1281f5b1135bSJiri Olsa 		evsel->attr.precise_ip     = mod.precise;
1282f5b1135bSJiri Olsa 		evsel->attr.exclude_host   = mod.eH;
1283f5b1135bSJiri Olsa 		evsel->attr.exclude_guest  = mod.eG;
1284a1e12da4SJiri Olsa 		evsel->attr.exclude_idle   = mod.eI;
1285f5b1135bSJiri Olsa 		evsel->exclude_GH          = mod.exclude_GH;
12863c176311SJiri Olsa 		evsel->sample_read         = mod.sample_read;
12877f94af7aSJiri Olsa 		evsel->precise_max         = mod.precise_max;
1288e9a7c414SMichael Ellerman 
1289e9a7c414SMichael Ellerman 		if (perf_evsel__is_group_leader(evsel))
1290e9a7c414SMichael Ellerman 			evsel->attr.pinned = mod.pinned;
1291ceb53fbfSIngo Molnar 	}
129286470930SIngo Molnar 
129389812fc8SJiri Olsa 	return 0;
129486470930SIngo Molnar }
129586470930SIngo Molnar 
1296ac2ba9f3SRobert Richter int parse_events_name(struct list_head *list, char *name)
1297ac2ba9f3SRobert Richter {
1298ac2ba9f3SRobert Richter 	struct perf_evsel *evsel;
1299ac2ba9f3SRobert Richter 
13000050f7aaSArnaldo Carvalho de Melo 	__evlist__for_each(list, evsel) {
1301ac2ba9f3SRobert Richter 		if (!evsel->name)
1302ac2ba9f3SRobert Richter 			evsel->name = strdup(name);
1303ac2ba9f3SRobert Richter 	}
1304ac2ba9f3SRobert Richter 
1305ac2ba9f3SRobert Richter 	return 0;
1306ac2ba9f3SRobert Richter }
1307ac2ba9f3SRobert Richter 
1308dcb4e102SKan Liang static int
1309dcb4e102SKan Liang comp_pmu(const void *p1, const void *p2)
1310dcb4e102SKan Liang {
1311dcb4e102SKan Liang 	struct perf_pmu_event_symbol *pmu1 = (struct perf_pmu_event_symbol *) p1;
1312dcb4e102SKan Liang 	struct perf_pmu_event_symbol *pmu2 = (struct perf_pmu_event_symbol *) p2;
1313dcb4e102SKan Liang 
1314dcb4e102SKan Liang 	return strcmp(pmu1->symbol, pmu2->symbol);
1315dcb4e102SKan Liang }
1316dcb4e102SKan Liang 
1317dcb4e102SKan Liang static void perf_pmu__parse_cleanup(void)
1318dcb4e102SKan Liang {
1319dcb4e102SKan Liang 	if (perf_pmu_events_list_num > 0) {
1320dcb4e102SKan Liang 		struct perf_pmu_event_symbol *p;
1321dcb4e102SKan Liang 		int i;
1322dcb4e102SKan Liang 
1323dcb4e102SKan Liang 		for (i = 0; i < perf_pmu_events_list_num; i++) {
1324dcb4e102SKan Liang 			p = perf_pmu_events_list + i;
1325dcb4e102SKan Liang 			free(p->symbol);
1326dcb4e102SKan Liang 		}
1327dcb4e102SKan Liang 		free(perf_pmu_events_list);
1328dcb4e102SKan Liang 		perf_pmu_events_list = NULL;
1329dcb4e102SKan Liang 		perf_pmu_events_list_num = 0;
1330dcb4e102SKan Liang 	}
1331dcb4e102SKan Liang }
1332dcb4e102SKan Liang 
1333dcb4e102SKan Liang #define SET_SYMBOL(str, stype)		\
1334dcb4e102SKan Liang do {					\
1335dcb4e102SKan Liang 	p->symbol = str;		\
1336dcb4e102SKan Liang 	if (!p->symbol)			\
1337dcb4e102SKan Liang 		goto err;		\
1338dcb4e102SKan Liang 	p->type = stype;		\
1339dcb4e102SKan Liang } while (0)
1340dcb4e102SKan Liang 
1341dcb4e102SKan Liang /*
1342dcb4e102SKan Liang  * Read the pmu events list from sysfs
1343dcb4e102SKan Liang  * Save it into perf_pmu_events_list
1344dcb4e102SKan Liang  */
1345dcb4e102SKan Liang static void perf_pmu__parse_init(void)
1346dcb4e102SKan Liang {
1347dcb4e102SKan Liang 
1348dcb4e102SKan Liang 	struct perf_pmu *pmu = NULL;
1349dcb4e102SKan Liang 	struct perf_pmu_alias *alias;
1350dcb4e102SKan Liang 	int len = 0;
1351dcb4e102SKan Liang 
1352dcb4e102SKan Liang 	pmu = perf_pmu__find("cpu");
1353dcb4e102SKan Liang 	if ((pmu == NULL) || list_empty(&pmu->aliases)) {
1354dcb4e102SKan Liang 		perf_pmu_events_list_num = -1;
1355dcb4e102SKan Liang 		return;
1356dcb4e102SKan Liang 	}
1357dcb4e102SKan Liang 	list_for_each_entry(alias, &pmu->aliases, list) {
1358dcb4e102SKan Liang 		if (strchr(alias->name, '-'))
1359dcb4e102SKan Liang 			len++;
1360dcb4e102SKan Liang 		len++;
1361dcb4e102SKan Liang 	}
1362dcb4e102SKan Liang 	perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len);
1363dcb4e102SKan Liang 	if (!perf_pmu_events_list)
1364dcb4e102SKan Liang 		return;
1365dcb4e102SKan Liang 	perf_pmu_events_list_num = len;
1366dcb4e102SKan Liang 
1367dcb4e102SKan Liang 	len = 0;
1368dcb4e102SKan Liang 	list_for_each_entry(alias, &pmu->aliases, list) {
1369dcb4e102SKan Liang 		struct perf_pmu_event_symbol *p = perf_pmu_events_list + len;
1370dcb4e102SKan Liang 		char *tmp = strchr(alias->name, '-');
1371dcb4e102SKan Liang 
1372dcb4e102SKan Liang 		if (tmp != NULL) {
1373dcb4e102SKan Liang 			SET_SYMBOL(strndup(alias->name, tmp - alias->name),
1374dcb4e102SKan Liang 					PMU_EVENT_SYMBOL_PREFIX);
1375dcb4e102SKan Liang 			p++;
1376dcb4e102SKan Liang 			SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX);
1377dcb4e102SKan Liang 			len += 2;
1378dcb4e102SKan Liang 		} else {
1379dcb4e102SKan Liang 			SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL);
1380dcb4e102SKan Liang 			len++;
1381dcb4e102SKan Liang 		}
1382dcb4e102SKan Liang 	}
1383dcb4e102SKan Liang 	qsort(perf_pmu_events_list, len,
1384dcb4e102SKan Liang 		sizeof(struct perf_pmu_event_symbol), comp_pmu);
1385dcb4e102SKan Liang 
1386dcb4e102SKan Liang 	return;
1387dcb4e102SKan Liang err:
1388dcb4e102SKan Liang 	perf_pmu__parse_cleanup();
1389dcb4e102SKan Liang }
1390dcb4e102SKan Liang 
1391dcb4e102SKan Liang enum perf_pmu_event_symbol_type
1392dcb4e102SKan Liang perf_pmu__parse_check(const char *name)
1393dcb4e102SKan Liang {
1394dcb4e102SKan Liang 	struct perf_pmu_event_symbol p, *r;
1395dcb4e102SKan Liang 
1396dcb4e102SKan Liang 	/* scan kernel pmu events from sysfs if needed */
1397dcb4e102SKan Liang 	if (perf_pmu_events_list_num == 0)
1398dcb4e102SKan Liang 		perf_pmu__parse_init();
1399dcb4e102SKan Liang 	/*
1400dcb4e102SKan Liang 	 * name "cpu" could be prefix of cpu-cycles or cpu// events.
1401dcb4e102SKan Liang 	 * cpu-cycles has been handled by hardcode.
1402dcb4e102SKan Liang 	 * So it must be cpu// events, not kernel pmu event.
1403dcb4e102SKan Liang 	 */
1404dcb4e102SKan Liang 	if ((perf_pmu_events_list_num <= 0) || !strcmp(name, "cpu"))
1405dcb4e102SKan Liang 		return PMU_EVENT_SYMBOL_ERR;
1406dcb4e102SKan Liang 
1407dcb4e102SKan Liang 	p.symbol = strdup(name);
1408dcb4e102SKan Liang 	r = bsearch(&p, perf_pmu_events_list,
1409dcb4e102SKan Liang 			(size_t) perf_pmu_events_list_num,
1410dcb4e102SKan Liang 			sizeof(struct perf_pmu_event_symbol), comp_pmu);
1411dcb4e102SKan Liang 	free(p.symbol);
1412dcb4e102SKan Liang 	return r ? r->type : PMU_EVENT_SYMBOL_ERR;
1413dcb4e102SKan Liang }
1414dcb4e102SKan Liang 
141590e2b22dSJiri Olsa static int parse_events__scanner(const char *str, void *data, int start_token)
1416ac20de6fSZheng Yan {
1417ac20de6fSZheng Yan 	YY_BUFFER_STATE buffer;
1418ac20de6fSZheng Yan 	void *scanner;
1419ac20de6fSZheng Yan 	int ret;
1420ac20de6fSZheng Yan 
142190e2b22dSJiri Olsa 	ret = parse_events_lex_init_extra(start_token, &scanner);
1422ac20de6fSZheng Yan 	if (ret)
1423ac20de6fSZheng Yan 		return ret;
1424ac20de6fSZheng Yan 
1425ac20de6fSZheng Yan 	buffer = parse_events__scan_string(str, scanner);
1426ac20de6fSZheng Yan 
1427ac20de6fSZheng Yan #ifdef PARSER_DEBUG
1428ac20de6fSZheng Yan 	parse_events_debug = 1;
1429ac20de6fSZheng Yan #endif
1430ac20de6fSZheng Yan 	ret = parse_events_parse(data, scanner);
1431ac20de6fSZheng Yan 
1432ac20de6fSZheng Yan 	parse_events__flush_buffer(buffer, scanner);
1433ac20de6fSZheng Yan 	parse_events__delete_buffer(buffer, scanner);
1434ac20de6fSZheng Yan 	parse_events_lex_destroy(scanner);
1435ac20de6fSZheng Yan 	return ret;
1436ac20de6fSZheng Yan }
1437ac20de6fSZheng Yan 
143890e2b22dSJiri Olsa /*
143990e2b22dSJiri Olsa  * parse event config string, return a list of event terms.
144090e2b22dSJiri Olsa  */
144190e2b22dSJiri Olsa int parse_events_terms(struct list_head *terms, const char *str)
144290e2b22dSJiri Olsa {
144323b6339bSArnaldo Carvalho de Melo 	struct parse_events_terms data = {
144490e2b22dSJiri Olsa 		.terms = NULL,
144590e2b22dSJiri Olsa 	};
144690e2b22dSJiri Olsa 	int ret;
144790e2b22dSJiri Olsa 
144890e2b22dSJiri Olsa 	ret = parse_events__scanner(str, &data, PE_START_TERMS);
144990e2b22dSJiri Olsa 	if (!ret) {
145090e2b22dSJiri Olsa 		list_splice(data.terms, terms);
145174cf249dSArnaldo Carvalho de Melo 		zfree(&data.terms);
145290e2b22dSJiri Olsa 		return 0;
145390e2b22dSJiri Olsa 	}
145490e2b22dSJiri Olsa 
14552146afc6SArnaldo Carvalho de Melo 	parse_events_terms__delete(data.terms);
145690e2b22dSJiri Olsa 	return ret;
145790e2b22dSJiri Olsa }
145890e2b22dSJiri Olsa 
1459b39b8393SJiri Olsa int parse_events(struct perf_evlist *evlist, const char *str,
1460b39b8393SJiri Olsa 		 struct parse_events_error *err)
146186470930SIngo Molnar {
146223b6339bSArnaldo Carvalho de Melo 	struct parse_events_evlist data = {
146346010ab2SJiri Olsa 		.list  = LIST_HEAD_INIT(data.list),
146446010ab2SJiri Olsa 		.idx   = evlist->nr_entries,
1465b39b8393SJiri Olsa 		.error = err,
146646010ab2SJiri Olsa 	};
146746010ab2SJiri Olsa 	int ret;
146886470930SIngo Molnar 
146990e2b22dSJiri Olsa 	ret = parse_events__scanner(str, &data, PE_START_EVENTS);
1470dcb4e102SKan Liang 	perf_pmu__parse_cleanup();
147189812fc8SJiri Olsa 	if (!ret) {
147215bfd2ccSWang Nan 		struct perf_evsel *last;
147315bfd2ccSWang Nan 
1474854f7363SWang Nan 		if (list_empty(&data.list)) {
1475854f7363SWang Nan 			WARN_ONCE(true, "WARNING: event parser found nothing");
1476854f7363SWang Nan 			return -1;
1477854f7363SWang Nan 		}
1478854f7363SWang Nan 
1479f114d6efSAdrian Hunter 		perf_evlist__splice_list_tail(evlist, &data.list);
148097f63e4aSNamhyung Kim 		evlist->nr_groups += data.nr_groups;
148115bfd2ccSWang Nan 		last = perf_evlist__last(evlist);
148215bfd2ccSWang Nan 		last->cmdline_group_boundary = true;
148315bfd2ccSWang Nan 
148486470930SIngo Molnar 		return 0;
148586470930SIngo Molnar 	}
148686470930SIngo Molnar 
14875d7be90eSJiri Olsa 	/*
14885d7be90eSJiri Olsa 	 * There are 2 users - builtin-record and builtin-test objects.
14895d7be90eSJiri Olsa 	 * Both call perf_evlist__delete in case of error, so we dont
14905d7be90eSJiri Olsa 	 * need to bother.
14915d7be90eSJiri Olsa 	 */
149289812fc8SJiri Olsa 	return ret;
149389812fc8SJiri Olsa }
149489812fc8SJiri Olsa 
1495b39b8393SJiri Olsa #define MAX_WIDTH 1000
1496b39b8393SJiri Olsa static int get_term_width(void)
1497b39b8393SJiri Olsa {
1498b39b8393SJiri Olsa 	struct winsize ws;
1499b39b8393SJiri Olsa 
1500b39b8393SJiri Olsa 	get_term_dimensions(&ws);
1501b39b8393SJiri Olsa 	return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col;
1502b39b8393SJiri Olsa }
1503b39b8393SJiri Olsa 
1504b39b8393SJiri Olsa static void parse_events_print_error(struct parse_events_error *err,
1505b39b8393SJiri Olsa 				     const char *event)
1506b39b8393SJiri Olsa {
1507b39b8393SJiri Olsa 	const char *str = "invalid or unsupported event: ";
1508b39b8393SJiri Olsa 	char _buf[MAX_WIDTH];
1509b39b8393SJiri Olsa 	char *buf = (char *) event;
1510b39b8393SJiri Olsa 	int idx = 0;
1511b39b8393SJiri Olsa 
1512b39b8393SJiri Olsa 	if (err->str) {
1513b39b8393SJiri Olsa 		/* -2 for extra '' in the final fprintf */
1514b39b8393SJiri Olsa 		int width       = get_term_width() - 2;
1515b39b8393SJiri Olsa 		int len_event   = strlen(event);
1516b39b8393SJiri Olsa 		int len_str, max_len, cut = 0;
1517b39b8393SJiri Olsa 
1518b39b8393SJiri Olsa 		/*
1519b39b8393SJiri Olsa 		 * Maximum error index indent, we will cut
1520b39b8393SJiri Olsa 		 * the event string if it's bigger.
1521b39b8393SJiri Olsa 		 */
1522141b2d31SAdrian Hunter 		int max_err_idx = 13;
1523b39b8393SJiri Olsa 
1524b39b8393SJiri Olsa 		/*
1525b39b8393SJiri Olsa 		 * Let's be specific with the message when
1526b39b8393SJiri Olsa 		 * we have the precise error.
1527b39b8393SJiri Olsa 		 */
1528b39b8393SJiri Olsa 		str     = "event syntax error: ";
1529b39b8393SJiri Olsa 		len_str = strlen(str);
1530b39b8393SJiri Olsa 		max_len = width - len_str;
1531b39b8393SJiri Olsa 
1532b39b8393SJiri Olsa 		buf = _buf;
1533b39b8393SJiri Olsa 
1534b39b8393SJiri Olsa 		/* We're cutting from the beggining. */
1535b39b8393SJiri Olsa 		if (err->idx > max_err_idx)
1536b39b8393SJiri Olsa 			cut = err->idx - max_err_idx;
1537b39b8393SJiri Olsa 
1538b39b8393SJiri Olsa 		strncpy(buf, event + cut, max_len);
1539b39b8393SJiri Olsa 
1540b39b8393SJiri Olsa 		/* Mark cut parts with '..' on both sides. */
1541b39b8393SJiri Olsa 		if (cut)
1542b39b8393SJiri Olsa 			buf[0] = buf[1] = '.';
1543b39b8393SJiri Olsa 
1544b39b8393SJiri Olsa 		if ((len_event - cut) > max_len) {
1545b39b8393SJiri Olsa 			buf[max_len - 1] = buf[max_len - 2] = '.';
1546b39b8393SJiri Olsa 			buf[max_len] = 0;
1547b39b8393SJiri Olsa 		}
1548b39b8393SJiri Olsa 
1549b39b8393SJiri Olsa 		idx = len_str + err->idx - cut;
1550b39b8393SJiri Olsa 	}
1551b39b8393SJiri Olsa 
1552b39b8393SJiri Olsa 	fprintf(stderr, "%s'%s'\n", str, buf);
1553b39b8393SJiri Olsa 	if (idx) {
1554b39b8393SJiri Olsa 		fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err->str);
1555b39b8393SJiri Olsa 		if (err->help)
1556b39b8393SJiri Olsa 			fprintf(stderr, "\n%s\n", err->help);
1557b39b8393SJiri Olsa 		free(err->str);
1558b39b8393SJiri Olsa 		free(err->help);
1559b39b8393SJiri Olsa 	}
1560b39b8393SJiri Olsa 
1561b39b8393SJiri Olsa 	fprintf(stderr, "Run 'perf list' for a list of valid events\n");
1562b39b8393SJiri Olsa }
1563b39b8393SJiri Olsa 
1564b39b8393SJiri Olsa #undef MAX_WIDTH
1565b39b8393SJiri Olsa 
1566f120f9d5SJiri Olsa int parse_events_option(const struct option *opt, const char *str,
15671d037ca1SIrina Tirdea 			int unset __maybe_unused)
1568f120f9d5SJiri Olsa {
1569f120f9d5SJiri Olsa 	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
1570b39b8393SJiri Olsa 	struct parse_events_error err = { .idx = 0, };
1571b39b8393SJiri Olsa 	int ret = parse_events(evlist, str, &err);
15729175ce1fSAndi Kleen 
1573b39b8393SJiri Olsa 	if (ret)
1574b39b8393SJiri Olsa 		parse_events_print_error(&err, str);
1575b39b8393SJiri Olsa 
15769175ce1fSAndi Kleen 	return ret;
1577f120f9d5SJiri Olsa }
1578f120f9d5SJiri Olsa 
15794ba1faa1SWang Nan static int
15804ba1faa1SWang Nan foreach_evsel_in_last_glob(struct perf_evlist *evlist,
15814ba1faa1SWang Nan 			   int (*func)(struct perf_evsel *evsel,
15824ba1faa1SWang Nan 				       const void *arg),
15834ba1faa1SWang Nan 			   const void *arg)
1584c171b552SLi Zefan {
158569aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *last = NULL;
15864ba1faa1SWang Nan 	int err;
1587c171b552SLi Zefan 
1588854f7363SWang Nan 	/*
1589854f7363SWang Nan 	 * Don't return when list_empty, give func a chance to report
1590854f7363SWang Nan 	 * error when it found last == NULL.
1591854f7363SWang Nan 	 *
1592854f7363SWang Nan 	 * So no need to WARN here, let *func do this.
1593854f7363SWang Nan 	 */
1594361c99a6SArnaldo Carvalho de Melo 	if (evlist->nr_entries > 0)
15950c21f736SArnaldo Carvalho de Melo 		last = perf_evlist__last(evlist);
159669aad6f1SArnaldo Carvalho de Melo 
159715bfd2ccSWang Nan 	do {
15984ba1faa1SWang Nan 		err = (*func)(last, arg);
15994ba1faa1SWang Nan 		if (err)
1600c171b552SLi Zefan 			return -1;
16014ba1faa1SWang Nan 		if (!last)
16024ba1faa1SWang Nan 			return 0;
1603c171b552SLi Zefan 
160415bfd2ccSWang Nan 		if (last->node.prev == &evlist->entries)
160515bfd2ccSWang Nan 			return 0;
160615bfd2ccSWang Nan 		last = list_entry(last->node.prev, struct perf_evsel, node);
160715bfd2ccSWang Nan 	} while (!last->cmdline_group_boundary);
160815bfd2ccSWang Nan 
1609c171b552SLi Zefan 	return 0;
1610c171b552SLi Zefan }
1611c171b552SLi Zefan 
16124ba1faa1SWang Nan static int set_filter(struct perf_evsel *evsel, const void *arg)
16134ba1faa1SWang Nan {
16144ba1faa1SWang Nan 	const char *str = arg;
16154ba1faa1SWang Nan 
16164ba1faa1SWang Nan 	if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) {
16174ba1faa1SWang Nan 		fprintf(stderr,
16184ba1faa1SWang Nan 			"--filter option should follow a -e tracepoint option\n");
16194ba1faa1SWang Nan 		return -1;
16204ba1faa1SWang Nan 	}
16214ba1faa1SWang Nan 
16224ba1faa1SWang Nan 	if (perf_evsel__append_filter(evsel, "&&", str) < 0) {
16234ba1faa1SWang Nan 		fprintf(stderr,
16244ba1faa1SWang Nan 			"not enough memory to hold filter string\n");
16254ba1faa1SWang Nan 		return -1;
16264ba1faa1SWang Nan 	}
16274ba1faa1SWang Nan 
16284ba1faa1SWang Nan 	return 0;
16294ba1faa1SWang Nan }
16304ba1faa1SWang Nan 
16314ba1faa1SWang Nan int parse_filter(const struct option *opt, const char *str,
16324ba1faa1SWang Nan 		 int unset __maybe_unused)
16334ba1faa1SWang Nan {
16344ba1faa1SWang Nan 	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
16354ba1faa1SWang Nan 
16364ba1faa1SWang Nan 	return foreach_evsel_in_last_glob(evlist, set_filter,
16374ba1faa1SWang Nan 					  (const void *)str);
16384ba1faa1SWang Nan }
16394ba1faa1SWang Nan 
16404ba1faa1SWang Nan static int add_exclude_perf_filter(struct perf_evsel *evsel,
16414ba1faa1SWang Nan 				   const void *arg __maybe_unused)
16424ba1faa1SWang Nan {
16434ba1faa1SWang Nan 	char new_filter[64];
16444ba1faa1SWang Nan 
16454ba1faa1SWang Nan 	if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) {
16464ba1faa1SWang Nan 		fprintf(stderr,
16474ba1faa1SWang Nan 			"--exclude-perf option should follow a -e tracepoint option\n");
16484ba1faa1SWang Nan 		return -1;
16494ba1faa1SWang Nan 	}
16504ba1faa1SWang Nan 
16514ba1faa1SWang Nan 	snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid());
16524ba1faa1SWang Nan 
16534ba1faa1SWang Nan 	if (perf_evsel__append_filter(evsel, "&&", new_filter) < 0) {
16544ba1faa1SWang Nan 		fprintf(stderr,
16554ba1faa1SWang Nan 			"not enough memory to hold filter string\n");
16564ba1faa1SWang Nan 		return -1;
16574ba1faa1SWang Nan 	}
16584ba1faa1SWang Nan 
16594ba1faa1SWang Nan 	return 0;
16604ba1faa1SWang Nan }
16614ba1faa1SWang Nan 
16624ba1faa1SWang Nan int exclude_perf(const struct option *opt,
16634ba1faa1SWang Nan 		 const char *arg __maybe_unused,
16644ba1faa1SWang Nan 		 int unset __maybe_unused)
16654ba1faa1SWang Nan {
16664ba1faa1SWang Nan 	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
16674ba1faa1SWang Nan 
16684ba1faa1SWang Nan 	return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter,
16694ba1faa1SWang Nan 					  NULL);
16704ba1faa1SWang Nan }
16714ba1faa1SWang Nan 
167286470930SIngo Molnar static const char * const event_type_descriptors[] = {
167386470930SIngo Molnar 	"Hardware event",
167486470930SIngo Molnar 	"Software event",
167586470930SIngo Molnar 	"Tracepoint event",
167686470930SIngo Molnar 	"Hardware cache event",
167741bdcb23SLiming Wang 	"Raw hardware event descriptor",
167841bdcb23SLiming Wang 	"Hardware breakpoint",
167986470930SIngo Molnar };
168086470930SIngo Molnar 
1681ab0e4800SYunlong Song static int cmp_string(const void *a, const void *b)
1682ab0e4800SYunlong Song {
1683ab0e4800SYunlong Song 	const char * const *as = a;
1684ab0e4800SYunlong Song 	const char * const *bs = b;
1685ab0e4800SYunlong Song 
1686ab0e4800SYunlong Song 	return strcmp(*as, *bs);
1687ab0e4800SYunlong Song }
1688ab0e4800SYunlong Song 
168986470930SIngo Molnar /*
1690f6bdafefSJason Baron  * Print the events from <debugfs_mount_point>/tracing/events
1691f6bdafefSJason Baron  */
1692f6bdafefSJason Baron 
1693a3277d2dSFrederic Weisbecker void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1694a3277d2dSFrederic Weisbecker 			     bool name_only)
1695f6bdafefSJason Baron {
1696f6bdafefSJason Baron 	DIR *sys_dir, *evt_dir;
1697f6bdafefSJason Baron 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1698f6bdafefSJason Baron 	char evt_path[MAXPATHLEN];
1699725b1368SEric Dumazet 	char dir_path[MAXPATHLEN];
1700ab0e4800SYunlong Song 	char **evt_list = NULL;
1701ab0e4800SYunlong Song 	unsigned int evt_i = 0, evt_num = 0;
1702ab0e4800SYunlong Song 	bool evt_num_known = false;
1703f6bdafefSJason Baron 
1704ab0e4800SYunlong Song restart:
1705ebf294bfSArnaldo Carvalho de Melo 	sys_dir = opendir(tracing_events_path);
1706f6bdafefSJason Baron 	if (!sys_dir)
1707725b1368SEric Dumazet 		return;
1708f6bdafefSJason Baron 
1709ab0e4800SYunlong Song 	if (evt_num_known) {
1710ab0e4800SYunlong Song 		evt_list = zalloc(sizeof(char *) * evt_num);
1711ab0e4800SYunlong Song 		if (!evt_list)
1712ab0e4800SYunlong Song 			goto out_close_sys_dir;
1713ab0e4800SYunlong Song 	}
1714ab0e4800SYunlong Song 
17156b58e7f1SUlrich Drepper 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
1716668b8788SArnaldo Carvalho de Melo 		if (subsys_glob != NULL &&
1717668b8788SArnaldo Carvalho de Melo 		    !strglobmatch(sys_dirent.d_name, subsys_glob))
1718668b8788SArnaldo Carvalho de Melo 			continue;
1719725b1368SEric Dumazet 
1720ebf294bfSArnaldo Carvalho de Melo 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
1721725b1368SEric Dumazet 			 sys_dirent.d_name);
1722725b1368SEric Dumazet 		evt_dir = opendir(dir_path);
1723725b1368SEric Dumazet 		if (!evt_dir)
17246b58e7f1SUlrich Drepper 			continue;
1725725b1368SEric Dumazet 
17266b58e7f1SUlrich Drepper 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
1727668b8788SArnaldo Carvalho de Melo 			if (event_glob != NULL &&
1728668b8788SArnaldo Carvalho de Melo 			    !strglobmatch(evt_dirent.d_name, event_glob))
1729668b8788SArnaldo Carvalho de Melo 				continue;
1730668b8788SArnaldo Carvalho de Melo 
1731ab0e4800SYunlong Song 			if (!evt_num_known) {
1732ab0e4800SYunlong Song 				evt_num++;
1733a3277d2dSFrederic Weisbecker 				continue;
1734a3277d2dSFrederic Weisbecker 			}
1735a3277d2dSFrederic Weisbecker 
1736f6bdafefSJason Baron 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
1737f6bdafefSJason Baron 				 sys_dirent.d_name, evt_dirent.d_name);
1738ab0e4800SYunlong Song 
1739ab0e4800SYunlong Song 			evt_list[evt_i] = strdup(evt_path);
1740ab0e4800SYunlong Song 			if (evt_list[evt_i] == NULL)
1741ab0e4800SYunlong Song 				goto out_close_evt_dir;
1742ab0e4800SYunlong Song 			evt_i++;
1743f6bdafefSJason Baron 		}
1744f6bdafefSJason Baron 		closedir(evt_dir);
1745f6bdafefSJason Baron 	}
1746f6bdafefSJason Baron 	closedir(sys_dir);
1747ab0e4800SYunlong Song 
1748ab0e4800SYunlong Song 	if (!evt_num_known) {
1749ab0e4800SYunlong Song 		evt_num_known = true;
1750ab0e4800SYunlong Song 		goto restart;
1751ab0e4800SYunlong Song 	}
1752ab0e4800SYunlong Song 	qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1753ab0e4800SYunlong Song 	evt_i = 0;
1754ab0e4800SYunlong Song 	while (evt_i < evt_num) {
1755ab0e4800SYunlong Song 		if (name_only) {
1756ab0e4800SYunlong Song 			printf("%s ", evt_list[evt_i++]);
1757ab0e4800SYunlong Song 			continue;
1758ab0e4800SYunlong Song 		}
1759ab0e4800SYunlong Song 		printf("  %-50s [%s]\n", evt_list[evt_i++],
1760ab0e4800SYunlong Song 				event_type_descriptors[PERF_TYPE_TRACEPOINT]);
1761ab0e4800SYunlong Song 	}
1762dfc431cbSArnaldo Carvalho de Melo 	if (evt_num && pager_in_use())
1763ab0e4800SYunlong Song 		printf("\n");
1764ab0e4800SYunlong Song 
1765ab0e4800SYunlong Song out_free:
1766ab0e4800SYunlong Song 	evt_num = evt_i;
1767ab0e4800SYunlong Song 	for (evt_i = 0; evt_i < evt_num; evt_i++)
1768ab0e4800SYunlong Song 		zfree(&evt_list[evt_i]);
1769ab0e4800SYunlong Song 	zfree(&evt_list);
1770ab0e4800SYunlong Song 	return;
1771ab0e4800SYunlong Song 
1772ab0e4800SYunlong Song out_close_evt_dir:
1773ab0e4800SYunlong Song 	closedir(evt_dir);
1774ab0e4800SYunlong Song out_close_sys_dir:
1775ab0e4800SYunlong Song 	closedir(sys_dir);
1776ab0e4800SYunlong Song 
1777ab0e4800SYunlong Song 	printf("FATAL: not enough memory to print %s\n",
1778ab0e4800SYunlong Song 			event_type_descriptors[PERF_TYPE_TRACEPOINT]);
1779ab0e4800SYunlong Song 	if (evt_list)
1780ab0e4800SYunlong Song 		goto out_free;
1781f6bdafefSJason Baron }
1782f6bdafefSJason Baron 
1783f6bdafefSJason Baron /*
178420c457b8SThomas Renninger  * Check whether event is in <debugfs_mount_point>/tracing/events
178520c457b8SThomas Renninger  */
178620c457b8SThomas Renninger 
178720c457b8SThomas Renninger int is_valid_tracepoint(const char *event_string)
178820c457b8SThomas Renninger {
178920c457b8SThomas Renninger 	DIR *sys_dir, *evt_dir;
179020c457b8SThomas Renninger 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
179120c457b8SThomas Renninger 	char evt_path[MAXPATHLEN];
179220c457b8SThomas Renninger 	char dir_path[MAXPATHLEN];
179320c457b8SThomas Renninger 
1794ebf294bfSArnaldo Carvalho de Melo 	sys_dir = opendir(tracing_events_path);
179520c457b8SThomas Renninger 	if (!sys_dir)
179620c457b8SThomas Renninger 		return 0;
179720c457b8SThomas Renninger 
179820c457b8SThomas Renninger 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
179920c457b8SThomas Renninger 
1800ebf294bfSArnaldo Carvalho de Melo 		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
180120c457b8SThomas Renninger 			 sys_dirent.d_name);
180220c457b8SThomas Renninger 		evt_dir = opendir(dir_path);
180320c457b8SThomas Renninger 		if (!evt_dir)
180420c457b8SThomas Renninger 			continue;
180520c457b8SThomas Renninger 
180620c457b8SThomas Renninger 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
180720c457b8SThomas Renninger 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
180820c457b8SThomas Renninger 				 sys_dirent.d_name, evt_dirent.d_name);
180920c457b8SThomas Renninger 			if (!strcmp(evt_path, event_string)) {
181020c457b8SThomas Renninger 				closedir(evt_dir);
181120c457b8SThomas Renninger 				closedir(sys_dir);
181220c457b8SThomas Renninger 				return 1;
181320c457b8SThomas Renninger 			}
181420c457b8SThomas Renninger 		}
181520c457b8SThomas Renninger 		closedir(evt_dir);
181620c457b8SThomas Renninger 	}
181720c457b8SThomas Renninger 	closedir(sys_dir);
181820c457b8SThomas Renninger 	return 0;
181920c457b8SThomas Renninger }
182020c457b8SThomas Renninger 
1821b41f1cecSNamhyung Kim static bool is_event_supported(u8 type, unsigned config)
1822b41f1cecSNamhyung Kim {
1823b41f1cecSNamhyung Kim 	bool ret = true;
182488fee52eSVince Weaver 	int open_return;
1825b41f1cecSNamhyung Kim 	struct perf_evsel *evsel;
1826b41f1cecSNamhyung Kim 	struct perf_event_attr attr = {
1827b41f1cecSNamhyung Kim 		.type = type,
1828b41f1cecSNamhyung Kim 		.config = config,
1829b41f1cecSNamhyung Kim 		.disabled = 1,
1830b41f1cecSNamhyung Kim 	};
1831b41f1cecSNamhyung Kim 	struct {
1832b41f1cecSNamhyung Kim 		struct thread_map map;
1833b41f1cecSNamhyung Kim 		int threads[1];
1834b41f1cecSNamhyung Kim 	} tmap = {
1835b41f1cecSNamhyung Kim 		.map.nr	 = 1,
1836b41f1cecSNamhyung Kim 		.threads = { 0 },
1837b41f1cecSNamhyung Kim 	};
1838b41f1cecSNamhyung Kim 
1839ef503831SArnaldo Carvalho de Melo 	evsel = perf_evsel__new(&attr);
1840b41f1cecSNamhyung Kim 	if (evsel) {
184188fee52eSVince Weaver 		open_return = perf_evsel__open(evsel, NULL, &tmap.map);
184288fee52eSVince Weaver 		ret = open_return >= 0;
184388fee52eSVince Weaver 
184488fee52eSVince Weaver 		if (open_return == -EACCES) {
184588fee52eSVince Weaver 			/*
184688fee52eSVince Weaver 			 * This happens if the paranoid value
184788fee52eSVince Weaver 			 * /proc/sys/kernel/perf_event_paranoid is set to 2
184888fee52eSVince Weaver 			 * Re-run with exclude_kernel set; we don't do that
184988fee52eSVince Weaver 			 * by default as some ARM machines do not support it.
185088fee52eSVince Weaver 			 *
185188fee52eSVince Weaver 			 */
185288fee52eSVince Weaver 			evsel->attr.exclude_kernel = 1;
1853b41f1cecSNamhyung Kim 			ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
185488fee52eSVince Weaver 		}
1855b41f1cecSNamhyung Kim 		perf_evsel__delete(evsel);
1856b41f1cecSNamhyung Kim 	}
1857b41f1cecSNamhyung Kim 
1858b41f1cecSNamhyung Kim 	return ret;
1859b41f1cecSNamhyung Kim }
1860b41f1cecSNamhyung Kim 
1861a3277d2dSFrederic Weisbecker int print_hwcache_events(const char *event_glob, bool name_only)
1862668b8788SArnaldo Carvalho de Melo {
1863ab0e4800SYunlong Song 	unsigned int type, op, i, evt_i = 0, evt_num = 0;
18640b668bc9SArnaldo Carvalho de Melo 	char name[64];
1865ab0e4800SYunlong Song 	char **evt_list = NULL;
1866ab0e4800SYunlong Song 	bool evt_num_known = false;
1867ab0e4800SYunlong Song 
1868ab0e4800SYunlong Song restart:
1869ab0e4800SYunlong Song 	if (evt_num_known) {
1870ab0e4800SYunlong Song 		evt_list = zalloc(sizeof(char *) * evt_num);
1871ab0e4800SYunlong Song 		if (!evt_list)
1872ab0e4800SYunlong Song 			goto out_enomem;
1873ab0e4800SYunlong Song 	}
1874668b8788SArnaldo Carvalho de Melo 
1875668b8788SArnaldo Carvalho de Melo 	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
1876668b8788SArnaldo Carvalho de Melo 		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
1877668b8788SArnaldo Carvalho de Melo 			/* skip invalid cache type */
18780b668bc9SArnaldo Carvalho de Melo 			if (!perf_evsel__is_cache_op_valid(type, op))
1879668b8788SArnaldo Carvalho de Melo 				continue;
1880668b8788SArnaldo Carvalho de Melo 
1881668b8788SArnaldo Carvalho de Melo 			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
18820b668bc9SArnaldo Carvalho de Melo 				__perf_evsel__hw_cache_type_op_res_name(type, op, i,
18830b668bc9SArnaldo Carvalho de Melo 									name, sizeof(name));
1884947b4ad1SIngo Molnar 				if (event_glob != NULL && !strglobmatch(name, event_glob))
1885668b8788SArnaldo Carvalho de Melo 					continue;
1886668b8788SArnaldo Carvalho de Melo 
1887b41f1cecSNamhyung Kim 				if (!is_event_supported(PERF_TYPE_HW_CACHE,
1888b41f1cecSNamhyung Kim 							type | (op << 8) | (i << 16)))
1889b41f1cecSNamhyung Kim 					continue;
1890b41f1cecSNamhyung Kim 
1891ab0e4800SYunlong Song 				if (!evt_num_known) {
1892ab0e4800SYunlong Song 					evt_num++;
1893ab0e4800SYunlong Song 					continue;
1894ab0e4800SYunlong Song 				}
1895ab0e4800SYunlong Song 
1896ab0e4800SYunlong Song 				evt_list[evt_i] = strdup(name);
1897ab0e4800SYunlong Song 				if (evt_list[evt_i] == NULL)
1898ab0e4800SYunlong Song 					goto out_enomem;
1899ab0e4800SYunlong Song 				evt_i++;
1900668b8788SArnaldo Carvalho de Melo 			}
1901668b8788SArnaldo Carvalho de Melo 		}
1902668b8788SArnaldo Carvalho de Melo 	}
1903668b8788SArnaldo Carvalho de Melo 
1904ab0e4800SYunlong Song 	if (!evt_num_known) {
1905ab0e4800SYunlong Song 		evt_num_known = true;
1906ab0e4800SYunlong Song 		goto restart;
1907ab0e4800SYunlong Song 	}
1908ab0e4800SYunlong Song 	qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1909ab0e4800SYunlong Song 	evt_i = 0;
1910ab0e4800SYunlong Song 	while (evt_i < evt_num) {
1911ab0e4800SYunlong Song 		if (name_only) {
1912ab0e4800SYunlong Song 			printf("%s ", evt_list[evt_i++]);
1913ab0e4800SYunlong Song 			continue;
1914ab0e4800SYunlong Song 		}
1915ab0e4800SYunlong Song 		printf("  %-50s [%s]\n", evt_list[evt_i++],
1916ab0e4800SYunlong Song 				event_type_descriptors[PERF_TYPE_HW_CACHE]);
1917ab0e4800SYunlong Song 	}
1918dfc431cbSArnaldo Carvalho de Melo 	if (evt_num && pager_in_use())
1919dc098b35SAndi Kleen 		printf("\n");
1920ab0e4800SYunlong Song 
1921ab0e4800SYunlong Song out_free:
1922ab0e4800SYunlong Song 	evt_num = evt_i;
1923ab0e4800SYunlong Song 	for (evt_i = 0; evt_i < evt_num; evt_i++)
1924ab0e4800SYunlong Song 		zfree(&evt_list[evt_i]);
1925ab0e4800SYunlong Song 	zfree(&evt_list);
1926ab0e4800SYunlong Song 	return evt_num;
1927ab0e4800SYunlong Song 
1928ab0e4800SYunlong Song out_enomem:
1929ab0e4800SYunlong Song 	printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
1930ab0e4800SYunlong Song 	if (evt_list)
1931ab0e4800SYunlong Song 		goto out_free;
1932ab0e4800SYunlong Song 	return evt_num;
1933668b8788SArnaldo Carvalho de Melo }
1934668b8788SArnaldo Carvalho de Melo 
1935705750f2SYunlong Song void print_symbol_events(const char *event_glob, unsigned type,
1936a3277d2dSFrederic Weisbecker 				struct event_symbol *syms, unsigned max,
1937a3277d2dSFrederic Weisbecker 				bool name_only)
193886470930SIngo Molnar {
1939ab0e4800SYunlong Song 	unsigned int i, evt_i = 0, evt_num = 0;
1940947b4ad1SIngo Molnar 	char name[MAX_NAME_LEN];
1941ab0e4800SYunlong Song 	char **evt_list = NULL;
1942ab0e4800SYunlong Song 	bool evt_num_known = false;
1943ab0e4800SYunlong Song 
1944ab0e4800SYunlong Song restart:
1945ab0e4800SYunlong Song 	if (evt_num_known) {
1946ab0e4800SYunlong Song 		evt_list = zalloc(sizeof(char *) * evt_num);
1947ab0e4800SYunlong Song 		if (!evt_list)
1948ab0e4800SYunlong Song 			goto out_enomem;
1949ab0e4800SYunlong Song 		syms -= max;
1950ab0e4800SYunlong Song 	}
195186470930SIngo Molnar 
19521dc12760SJiri Olsa 	for (i = 0; i < max; i++, syms++) {
1953668b8788SArnaldo Carvalho de Melo 
1954e37df6c7SArnaldo Carvalho de Melo 		if (event_glob != NULL && syms->symbol != NULL &&
1955668b8788SArnaldo Carvalho de Melo 		    !(strglobmatch(syms->symbol, event_glob) ||
1956668b8788SArnaldo Carvalho de Melo 		      (syms->alias && strglobmatch(syms->alias, event_glob))))
1957668b8788SArnaldo Carvalho de Melo 			continue;
195886470930SIngo Molnar 
1959b41f1cecSNamhyung Kim 		if (!is_event_supported(type, i))
1960b41f1cecSNamhyung Kim 			continue;
1961b41f1cecSNamhyung Kim 
1962ab0e4800SYunlong Song 		if (!evt_num_known) {
1963ab0e4800SYunlong Song 			evt_num++;
1964a3277d2dSFrederic Weisbecker 			continue;
1965a3277d2dSFrederic Weisbecker 		}
1966a3277d2dSFrederic Weisbecker 
1967ab0e4800SYunlong Song 		if (!name_only && strlen(syms->alias))
1968947b4ad1SIngo Molnar 			snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
196974d5b588SJaswinder Singh Rajput 		else
1970947b4ad1SIngo Molnar 			strncpy(name, syms->symbol, MAX_NAME_LEN);
197186470930SIngo Molnar 
1972ab0e4800SYunlong Song 		evt_list[evt_i] = strdup(name);
1973ab0e4800SYunlong Song 		if (evt_list[evt_i] == NULL)
1974ab0e4800SYunlong Song 			goto out_enomem;
1975ab0e4800SYunlong Song 		evt_i++;
197686470930SIngo Molnar 	}
197786470930SIngo Molnar 
1978ab0e4800SYunlong Song 	if (!evt_num_known) {
1979ab0e4800SYunlong Song 		evt_num_known = true;
1980ab0e4800SYunlong Song 		goto restart;
1981ab0e4800SYunlong Song 	}
1982ab0e4800SYunlong Song 	qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1983ab0e4800SYunlong Song 	evt_i = 0;
1984ab0e4800SYunlong Song 	while (evt_i < evt_num) {
1985ab0e4800SYunlong Song 		if (name_only) {
1986ab0e4800SYunlong Song 			printf("%s ", evt_list[evt_i++]);
1987ab0e4800SYunlong Song 			continue;
1988ab0e4800SYunlong Song 		}
1989ab0e4800SYunlong Song 		printf("  %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
1990ab0e4800SYunlong Song 	}
1991dfc431cbSArnaldo Carvalho de Melo 	if (evt_num && pager_in_use())
1992689d3018SMarti Raudsepp 		printf("\n");
1993ab0e4800SYunlong Song 
1994ab0e4800SYunlong Song out_free:
1995ab0e4800SYunlong Song 	evt_num = evt_i;
1996ab0e4800SYunlong Song 	for (evt_i = 0; evt_i < evt_num; evt_i++)
1997ab0e4800SYunlong Song 		zfree(&evt_list[evt_i]);
1998ab0e4800SYunlong Song 	zfree(&evt_list);
1999ab0e4800SYunlong Song 	return;
2000ab0e4800SYunlong Song 
2001ab0e4800SYunlong Song out_enomem:
2002ab0e4800SYunlong Song 	printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
2003ab0e4800SYunlong Song 	if (evt_list)
2004ab0e4800SYunlong Song 		goto out_free;
2005668b8788SArnaldo Carvalho de Melo }
20061dc12760SJiri Olsa 
20071dc12760SJiri Olsa /*
20081dc12760SJiri Olsa  * Print the help text for the event symbols:
20091dc12760SJiri Olsa  */
2010a3277d2dSFrederic Weisbecker void print_events(const char *event_glob, bool name_only)
20111dc12760SJiri Olsa {
20121dc12760SJiri Olsa 	print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
2013a3277d2dSFrederic Weisbecker 			    event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
20141dc12760SJiri Olsa 
20151dc12760SJiri Olsa 	print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
2016a3277d2dSFrederic Weisbecker 			    event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
20171dc12760SJiri Olsa 
2018a3277d2dSFrederic Weisbecker 	print_hwcache_events(event_glob, name_only);
201973c24cb8SJaswinder Singh Rajput 
2020dc098b35SAndi Kleen 	print_pmu_events(event_glob, name_only);
2021dc098b35SAndi Kleen 
2022668b8788SArnaldo Carvalho de Melo 	if (event_glob != NULL)
2023668b8788SArnaldo Carvalho de Melo 		return;
202473c24cb8SJaswinder Singh Rajput 
2025a3277d2dSFrederic Weisbecker 	if (!name_only) {
2026947b4ad1SIngo Molnar 		printf("  %-50s [%s]\n",
20275f537a26SJiri Olsa 		       "rNNN",
20281cf4a063SArnaldo Carvalho de Melo 		       event_type_descriptors[PERF_TYPE_RAW]);
20295f537a26SJiri Olsa 		printf("  %-50s [%s]\n",
20305f537a26SJiri Olsa 		       "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
20315f537a26SJiri Olsa 		       event_type_descriptors[PERF_TYPE_RAW]);
2032dfc431cbSArnaldo Carvalho de Melo 		if (pager_in_use())
2033dfc431cbSArnaldo Carvalho de Melo 			printf("   (see 'man perf-list' on how to encode it)\n\n");
203486470930SIngo Molnar 
2035947b4ad1SIngo Molnar 		printf("  %-50s [%s]\n",
20363741eb9fSJacob Shin 		       "mem:<addr>[/len][:access]",
203741bdcb23SLiming Wang 			event_type_descriptors[PERF_TYPE_BREAKPOINT]);
2038dfc431cbSArnaldo Carvalho de Melo 		if (pager_in_use())
20391b290d67SFrederic Weisbecker 			printf("\n");
2040a3277d2dSFrederic Weisbecker 	}
20411b290d67SFrederic Weisbecker 
2042a3277d2dSFrederic Weisbecker 	print_tracepoint_events(NULL, NULL, name_only);
204386470930SIngo Molnar }
20448f707d84SJiri Olsa 
20456cee6cd3SArnaldo Carvalho de Melo int parse_events__is_hardcoded_term(struct parse_events_term *term)
20468f707d84SJiri Olsa {
204716fa7e82SJiri Olsa 	return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
20488f707d84SJiri Olsa }
20498f707d84SJiri Olsa 
20506cee6cd3SArnaldo Carvalho de Melo static int new_term(struct parse_events_term **_term, int type_val,
205116fa7e82SJiri Olsa 		    int type_term, char *config,
2052cecf3a2eSJiri Olsa 		    char *str, u64 num, int err_term, int err_val)
20538f707d84SJiri Olsa {
20546cee6cd3SArnaldo Carvalho de Melo 	struct parse_events_term *term;
20558f707d84SJiri Olsa 
20568f707d84SJiri Olsa 	term = zalloc(sizeof(*term));
20578f707d84SJiri Olsa 	if (!term)
20588f707d84SJiri Olsa 		return -ENOMEM;
20598f707d84SJiri Olsa 
20608f707d84SJiri Olsa 	INIT_LIST_HEAD(&term->list);
206116fa7e82SJiri Olsa 	term->type_val  = type_val;
206216fa7e82SJiri Olsa 	term->type_term = type_term;
20638f707d84SJiri Olsa 	term->config = config;
2064cecf3a2eSJiri Olsa 	term->err_term = err_term;
2065cecf3a2eSJiri Olsa 	term->err_val  = err_val;
20668f707d84SJiri Olsa 
206716fa7e82SJiri Olsa 	switch (type_val) {
20688f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_NUM:
20698f707d84SJiri Olsa 		term->val.num = num;
20708f707d84SJiri Olsa 		break;
20718f707d84SJiri Olsa 	case PARSE_EVENTS__TERM_TYPE_STR:
20728f707d84SJiri Olsa 		term->val.str = str;
20738f707d84SJiri Olsa 		break;
20748f707d84SJiri Olsa 	default:
20754be8be6bSAdrian Hunter 		free(term);
20768f707d84SJiri Olsa 		return -EINVAL;
20778f707d84SJiri Olsa 	}
20788f707d84SJiri Olsa 
20798f707d84SJiri Olsa 	*_term = term;
20808f707d84SJiri Olsa 	return 0;
20818f707d84SJiri Olsa }
20828f707d84SJiri Olsa 
20836cee6cd3SArnaldo Carvalho de Melo int parse_events_term__num(struct parse_events_term **term,
2084cecf3a2eSJiri Olsa 			   int type_term, char *config, u64 num,
2085bb78ce7dSAdrian Hunter 			   void *loc_term_, void *loc_val_)
208616fa7e82SJiri Olsa {
2087bb78ce7dSAdrian Hunter 	YYLTYPE *loc_term = loc_term_;
2088bb78ce7dSAdrian Hunter 	YYLTYPE *loc_val = loc_val_;
2089bb78ce7dSAdrian Hunter 
209016fa7e82SJiri Olsa 	return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
2091cecf3a2eSJiri Olsa 			config, NULL, num,
2092cecf3a2eSJiri Olsa 			loc_term ? loc_term->first_column : 0,
2093cecf3a2eSJiri Olsa 			loc_val ? loc_val->first_column : 0);
209416fa7e82SJiri Olsa }
209516fa7e82SJiri Olsa 
20966cee6cd3SArnaldo Carvalho de Melo int parse_events_term__str(struct parse_events_term **term,
2097cecf3a2eSJiri Olsa 			   int type_term, char *config, char *str,
2098bb78ce7dSAdrian Hunter 			   void *loc_term_, void *loc_val_)
209916fa7e82SJiri Olsa {
2100bb78ce7dSAdrian Hunter 	YYLTYPE *loc_term = loc_term_;
2101bb78ce7dSAdrian Hunter 	YYLTYPE *loc_val = loc_val_;
2102bb78ce7dSAdrian Hunter 
210316fa7e82SJiri Olsa 	return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term,
2104cecf3a2eSJiri Olsa 			config, str, 0,
2105cecf3a2eSJiri Olsa 			loc_term ? loc_term->first_column : 0,
2106cecf3a2eSJiri Olsa 			loc_val ? loc_val->first_column : 0);
210716fa7e82SJiri Olsa }
210816fa7e82SJiri Olsa 
21096cee6cd3SArnaldo Carvalho de Melo int parse_events_term__sym_hw(struct parse_events_term **term,
21101d33d6dcSJiri Olsa 			      char *config, unsigned idx)
21111d33d6dcSJiri Olsa {
21121d33d6dcSJiri Olsa 	struct event_symbol *sym;
21131d33d6dcSJiri Olsa 
21141d33d6dcSJiri Olsa 	BUG_ON(idx >= PERF_COUNT_HW_MAX);
21151d33d6dcSJiri Olsa 	sym = &event_symbols_hw[idx];
21161d33d6dcSJiri Olsa 
21171d33d6dcSJiri Olsa 	if (config)
21181d33d6dcSJiri Olsa 		return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
21191d33d6dcSJiri Olsa 				PARSE_EVENTS__TERM_TYPE_USER, config,
2120cecf3a2eSJiri Olsa 				(char *) sym->symbol, 0, 0, 0);
21211d33d6dcSJiri Olsa 	else
21221d33d6dcSJiri Olsa 		return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
21231d33d6dcSJiri Olsa 				PARSE_EVENTS__TERM_TYPE_USER,
2124cecf3a2eSJiri Olsa 				(char *) "event", (char *) sym->symbol,
2125cecf3a2eSJiri Olsa 				0, 0, 0);
21261d33d6dcSJiri Olsa }
21271d33d6dcSJiri Olsa 
21286cee6cd3SArnaldo Carvalho de Melo int parse_events_term__clone(struct parse_events_term **new,
21296cee6cd3SArnaldo Carvalho de Melo 			     struct parse_events_term *term)
2130a6146d50SZheng Yan {
2131a6146d50SZheng Yan 	return new_term(new, term->type_val, term->type_term, term->config,
2132cecf3a2eSJiri Olsa 			term->val.str, term->val.num,
2133cecf3a2eSJiri Olsa 			term->err_term, term->err_val);
2134a6146d50SZheng Yan }
2135a6146d50SZheng Yan 
2136fc0a2c1dSArnaldo Carvalho de Melo void parse_events_terms__purge(struct list_head *terms)
21378f707d84SJiri Olsa {
21386cee6cd3SArnaldo Carvalho de Melo 	struct parse_events_term *term, *h;
21398f707d84SJiri Olsa 
2140a8adfcebSWang Nan 	list_for_each_entry_safe(term, h, terms, list) {
2141a8adfcebSWang Nan 		list_del_init(&term->list);
21428f707d84SJiri Olsa 		free(term);
21438f707d84SJiri Olsa 	}
2144a8adfcebSWang Nan }
2145b39b8393SJiri Olsa 
21462146afc6SArnaldo Carvalho de Melo void parse_events_terms__delete(struct list_head *terms)
2147fc0a2c1dSArnaldo Carvalho de Melo {
21482146afc6SArnaldo Carvalho de Melo 	if (!terms)
21492146afc6SArnaldo Carvalho de Melo 		return;
2150fc0a2c1dSArnaldo Carvalho de Melo 	parse_events_terms__purge(terms);
2151d20a5f2bSWang Nan 	free(terms);
2152fc0a2c1dSArnaldo Carvalho de Melo }
2153fc0a2c1dSArnaldo Carvalho de Melo 
2154b39b8393SJiri Olsa void parse_events_evlist_error(struct parse_events_evlist *data,
2155b39b8393SJiri Olsa 			       int idx, const char *str)
2156b39b8393SJiri Olsa {
2157b39b8393SJiri Olsa 	struct parse_events_error *err = data->error;
2158b39b8393SJiri Olsa 
2159a6ced2beSAdrian Hunter 	if (!err)
2160a6ced2beSAdrian Hunter 		return;
2161b39b8393SJiri Olsa 	err->idx = idx;
2162b39b8393SJiri Olsa 	err->str = strdup(str);
2163b39b8393SJiri Olsa 	WARN_ONCE(!err->str, "WARNING: failed to allocate error string");
2164b39b8393SJiri Olsa }
2165ffeb883eSHe Kuang 
216617cb5f84SWang Nan static void config_terms_list(char *buf, size_t buf_sz)
216717cb5f84SWang Nan {
216817cb5f84SWang Nan 	int i;
216917cb5f84SWang Nan 	bool first = true;
217017cb5f84SWang Nan 
217117cb5f84SWang Nan 	buf[0] = '\0';
217217cb5f84SWang Nan 	for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) {
217317cb5f84SWang Nan 		const char *name = config_term_names[i];
217417cb5f84SWang Nan 
21751669e509SWang Nan 		if (!config_term_avail(i, NULL))
21761669e509SWang Nan 			continue;
217717cb5f84SWang Nan 		if (!name)
217817cb5f84SWang Nan 			continue;
217917cb5f84SWang Nan 		if (name[0] == '<')
218017cb5f84SWang Nan 			continue;
218117cb5f84SWang Nan 
218217cb5f84SWang Nan 		if (strlen(buf) + strlen(name) + 2 >= buf_sz)
218317cb5f84SWang Nan 			return;
218417cb5f84SWang Nan 
218517cb5f84SWang Nan 		if (!first)
218617cb5f84SWang Nan 			strcat(buf, ",");
218717cb5f84SWang Nan 		else
218817cb5f84SWang Nan 			first = false;
218917cb5f84SWang Nan 		strcat(buf, name);
219017cb5f84SWang Nan 	}
219117cb5f84SWang Nan }
219217cb5f84SWang Nan 
2193ffeb883eSHe Kuang /*
2194ffeb883eSHe Kuang  * Return string contains valid config terms of an event.
2195ffeb883eSHe Kuang  * @additional_terms: For terms such as PMU sysfs terms.
2196ffeb883eSHe Kuang  */
2197ffeb883eSHe Kuang char *parse_events_formats_error_string(char *additional_terms)
2198ffeb883eSHe Kuang {
2199ffeb883eSHe Kuang 	char *str;
220017cb5f84SWang Nan 	/* "branch_type" is the longest name */
220117cb5f84SWang Nan 	char static_terms[__PARSE_EVENTS__TERM_TYPE_NR *
220217cb5f84SWang Nan 			  (sizeof("branch_type") - 1)];
2203ffeb883eSHe Kuang 
220417cb5f84SWang Nan 	config_terms_list(static_terms, sizeof(static_terms));
2205ffeb883eSHe Kuang 	/* valid terms */
2206ffeb883eSHe Kuang 	if (additional_terms) {
220726dee028SWang Nan 		if (asprintf(&str, "valid terms: %s,%s",
220826dee028SWang Nan 			     additional_terms, static_terms) < 0)
2209ffeb883eSHe Kuang 			goto fail;
2210ffeb883eSHe Kuang 	} else {
221126dee028SWang Nan 		if (asprintf(&str, "valid terms: %s", static_terms) < 0)
2212ffeb883eSHe Kuang 			goto fail;
2213ffeb883eSHe Kuang 	}
2214ffeb883eSHe Kuang 	return str;
2215ffeb883eSHe Kuang 
2216ffeb883eSHe Kuang fail:
2217ffeb883eSHe Kuang 	return NULL;
2218ffeb883eSHe Kuang }
2219