1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*
2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * probe-event.c : perf-probe definition to probe_events format converter
3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Written by Masami Hiramatsu <mhiramat@redhat.com>
5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * This program is free software; you can redistribute it and/or modify
7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * it under the terms of the GNU General Public License as published by
8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * the Free Software Foundation; either version 2 of the License, or
9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * (at your option) any later version.
10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * This program is distributed in the hope that it will be useful,
12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * but WITHOUT ANY WARRANTY; without even the implied warranty of
13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * GNU General Public License for more details.
15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * You should have received a copy of the GNU General Public License
17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * along with this program; if not, write to the Free Software
18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */
21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define _GNU_SOURCE
23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/utsname.h>
24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/types.h>
25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/stat.h>
26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <fcntl.h>
27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <errno.h>
28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdio.h>
29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <unistd.h>
30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdlib.h>
31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <string.h>
32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdarg.h>
33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <limits.h>
34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <elf.h>
35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#undef _GNU_SOURCE
37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "util.h"
38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "event.h"
39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "string.h"
40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "strlist.h"
41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "debug.h"
42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "cache.h"
43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "color.h"
44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "symbol.h"
45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "thread.h"
46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "debugfs.h"
47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "trace-event.h"	/* For __unused */
48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "probe-event.h"
49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "probe-finder.h"
50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define MAX_CMDLEN 256
52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define MAX_PROBE_ARGS 128
53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define PERFPROBE_GROUP "probe"
54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengbool probe_event_dry_run;	/* Dry run flag */
56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define semantic_error(msg ...) pr_err("Semantic error :" msg)
58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* If there is no space to write, returns -E2BIG. */
60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int e_snprintf(char *str, size_t size, const char *format, ...)
61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	__attribute__((format(printf, 3, 4)));
62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int e_snprintf(char *str, size_t size, const char *format, ...)
64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret;
66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_list ap;
67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_start(ap, format);
68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = vsnprintf(str, size, format, ap);
69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	va_end(ap);
70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret >= (int)size)
71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = -E2BIG;
72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic char *synthesize_perf_probe_point(struct perf_probe_point *pp);
76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct machine machine;
77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Initialize symbol maps and path of vmlinux/modules */
79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int init_vmlinux(void)
80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret;
82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	symbol_conf.sort_by_name = true;
84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (symbol_conf.vmlinux_name == NULL)
85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		symbol_conf.try_vmlinux_path = true;
86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else
87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = symbol__init();
89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0) {
90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Failed to init symbol map.\n");
91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto out;
92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = machine__init(&machine, "", HOST_KERNEL_ID);
95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto out;
97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (machine__create_kernel_maps(&machine) < 0) {
99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("machine__create_kernel_maps() failed.\n");
100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto out;
101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout:
103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Failed to init vmlinux path.\n");
105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct symbol *__find_kernel_function_by_name(const char *name,
109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						     struct map **mapp)
110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return machine__find_kernel_function_by_name(&machine, name, mapp,
112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						     NULL);
113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct map *kernel_get_module_map(const char *module)
116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct rb_node *nd;
118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct map_groups *grp = &machine.kmaps;
119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!module)
121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		module = "kernel";
122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) {
124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		struct map *pos = rb_entry(nd, struct map, rb_node);
125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (strncmp(pos->dso->short_name + 1, module,
126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			    pos->dso->short_name_len - 2) == 0) {
127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return pos;
128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return NULL;
131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct dso *kernel_get_module_dso(const char *module)
134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct dso *dso;
136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct map *map;
137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *vmlinux_name;
138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (module) {
140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		list_for_each_entry(dso, &machine.kernel_dsos, node) {
141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (strncmp(dso->short_name + 1, module,
142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				    dso->short_name_len - 2) == 0)
143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				goto found;
144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Failed to find module %s.\n", module);
146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return NULL;
147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	map = machine.vmlinux_maps[MAP__FUNCTION];
150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	dso = map->dso;
151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	vmlinux_name = symbol_conf.vmlinux_name;
153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (vmlinux_name) {
154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0)
155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return NULL;
156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} else {
157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_debug("Failed to load kernel map.\n");
159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return NULL;
160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengfound:
163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return dso;
164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengconst char *kernel_get_module_path(const char *module)
167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct dso *dso = kernel_get_module_dso(module);
169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return (dso) ? dso->long_name : NULL;
170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#ifdef DWARF_SUPPORT
173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int open_vmlinux(const char *module)
174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *path = kernel_get_module_path(module);
176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!path) {
177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_err("Failed to find path of %s module.\n",
178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		       module ?: "kernel");
179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOENT;
180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("Try to open %s\n", path);
182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return open(path, O_RDONLY);
183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*
186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Convert trace point to probe point with debuginfo
187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Currently only handles kprobes.
188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */
189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					struct perf_probe_point *pp)
191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct symbol *sym;
193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct map *map;
194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	u64 addr;
195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret = -ENOENT;
196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	sym = __find_kernel_function_by_name(tp->symbol, &map);
198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (sym) {
199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		addr = map->unmap_ip(map, sym->start + tp->offset);
200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 tp->offset, addr);
202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = find_perf_probe_point((unsigned long)addr, pp);
203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret <= 0) {
205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Failed to find corresponding probes from "
206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 "debuginfo. Use kprobe event information.\n");
207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pp->function = strdup(tp->symbol);
208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pp->function == NULL)
209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ENOMEM;
210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pp->offset = tp->offset;
211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pp->retprobe = tp->retprobe;
213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Try to find perf_probe_event with debuginfo */
218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int try_to_find_probe_trace_events(struct perf_probe_event *pev,
219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					   struct probe_trace_event **tevs,
220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					   int max_tevs, const char *module)
221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	bool need_dwarf = perf_probe_event_need_dwarf(pev);
223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int fd, ntevs;
224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fd = open_vmlinux(module);
226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (fd < 0) {
227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (need_dwarf) {
228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_warning("Failed to open debuginfo file.\n");
229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return fd;
230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Could not open vmlinux. Try to use symbols.\n");
232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return 0;
233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Searching trace events corresponding to probe event */
236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs);
237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ntevs > 0) {	/* Succeeded to find trace events */
239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("find %d probe_trace_events.\n", ntevs);
240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ntevs;
241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ntevs == 0)	{	/* No error but failed to find probe point. */
244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Probe point '%s' not found.\n",
245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			   synthesize_perf_probe_point(&pev->point));
246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOENT;
247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Error path : ntevs < 0 */
249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ntevs == -EBADF) {
251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Warning: No dwarf info found in the vmlinux - "
252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			"please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!need_dwarf) {
254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_debug("Trying to use symbols.\n");
255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return 0;
256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ntevs;
259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*
262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Find a src file from a DWARF tag path. Prepend optional source path prefix
263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * and chop off leading directories that do not exist. Result is passed back as
264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * a newly allocated path on success.
265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Return 0 if file was found and readable, -errno otherwise.
266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */
267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int get_real_path(const char *raw_path, const char *comp_dir,
268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 char **new_path)
269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *prefix = symbol_conf.source_prefix;
271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!prefix) {
273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (raw_path[0] != '/' && comp_dir)
274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			/* If not an absolute path, try to use comp_dir */
275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			prefix = comp_dir;
276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else {
277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (access(raw_path, R_OK) == 0) {
278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				*new_path = strdup(raw_path);
279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return 0;
280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else
281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return -errno;
282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	*new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!*new_path)
287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (;;) {
290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		sprintf(*new_path, "%s/%s", prefix, raw_path);
291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (access(*new_path, R_OK) == 0)
293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return 0;
294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!symbol_conf.source_prefix)
296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			/* In case of searching comp_dir, don't retry */
297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -errno;
298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		switch (errno) {
300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case ENAMETOOLONG:
301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case ENOENT:
302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case EROFS:
303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case EFAULT:
304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			raw_path = strchr(++raw_path, '/');
305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (!raw_path) {
306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				free(*new_path);
307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				*new_path = NULL;
308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return -ENOENT;
309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			continue;
311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		default:
313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			free(*new_path);
314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			*new_path = NULL;
315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -errno;
316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define LINEBUF_SIZE 256
321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define NR_ADDITIONAL_LINES 2
322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char buf[LINEBUF_SIZE];
326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *color = show_num ? "" : PERF_COLOR_BLUE;
327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *prefix = NULL;
328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	do {
330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto error;
332e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (skip)
333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			continue;
334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!prefix) {
335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			prefix = show_num ? "%7d  " : "         ";
336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			color_fprintf(stdout, color, prefix, l);
337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		color_fprintf(stdout, color, "%s", buf);
339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} while (strchr(buf, '\n') == NULL);
341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
342e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 1;
343e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror:
344e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ferror(fp)) {
345e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("File read error: %s\n", strerror(errno));
346e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -1;
347e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
348e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
349e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
350e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
351e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
352e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
353e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int rv = __show_one_line(fp, l, skip, show_num);
354e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (rv == 0) {
355e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Source file is shorter than expected.\n");
356e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		rv = -1;
357e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
358e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return rv;
359e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
360e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
361e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define show_one_line_with_num(f,l)	_show_one_line(f,l,false,true)
362e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define show_one_line(f,l)		_show_one_line(f,l,false,false)
363e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define skip_one_line(f,l)		_show_one_line(f,l,true,false)
364e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define show_one_line_or_eof(f,l)	__show_one_line(f,l,false,false)
365e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
366e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*
367e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Show line-range always requires debuginfo to find source file and
368e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * line number.
369e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */
370e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_line_range(struct line_range *lr, const char *module)
371e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
372e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int l = 1;
373e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct line_node *ln;
374e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	FILE *fp;
375e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int fd, ret;
376e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *tmp;
377e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
378e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Search a line range */
379e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = init_vmlinux();
380e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
381e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
382e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
383e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fd = open_vmlinux(module);
384e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (fd < 0) {
385e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Failed to open debuginfo file.\n");
386e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return fd;
387e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
388e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
389e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = find_line_range(fd, lr);
390e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret == 0) {
391e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Specified source line is not found.\n");
392e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOENT;
393e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} else if (ret < 0) {
394e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Debuginfo analysis failed. (%d)\n", ret);
395e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
396e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
397e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
398e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Convert source file path */
399e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tmp = lr->path;
400e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = get_real_path(tmp, lr->comp_dir, &lr->path);
401e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(tmp);	/* Free old path */
402e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0) {
403e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Failed to find source file. (%d)\n", ret);
404e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
405e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
406e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
407e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	setup_pager();
408e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
409e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (lr->function)
410e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path,
411e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			lr->start - lr->offset);
412e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else
413e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
414e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
415e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fp = fopen(lr->path, "r");
416e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (fp == NULL) {
417e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Failed to open %s: %s\n", lr->path,
418e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			   strerror(errno));
419e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -errno;
420e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
421e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Skip to starting line number */
422e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (l < lr->start) {
423e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = skip_one_line(fp, l++);
424e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
425e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto end;
426e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
427e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
428e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	list_for_each_entry(ln, &lr->line_list, list) {
429e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		for (; ln->line > l; l++) {
430e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = show_one_line(fp, l - lr->offset);
431e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (ret < 0)
432e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				goto end;
433e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
434e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = show_one_line_with_num(fp, l++ - lr->offset);
435e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
436e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto end;
437e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
438e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
439e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (lr->end == INT_MAX)
440e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		lr->end = l + NR_ADDITIONAL_LINES;
441e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (l <= lr->end) {
442e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = show_one_line_or_eof(fp, l++ - lr->offset);
443e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret <= 0)
444e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
445e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
446e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengend:
447e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fclose(fp);
448e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
449e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
450e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
451e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int show_available_vars_at(int fd, struct perf_probe_event *pev,
452e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				  int max_vls, struct strfilter *_filter,
453e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				  bool externs)
454e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
455e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *buf;
456e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret, i, nvars;
457e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct str_node *node;
458e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct variable_list *vls = NULL, *vl;
459e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *var;
460e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
461e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	buf = synthesize_perf_probe_point(&pev->point);
462e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!buf)
463e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
464e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("Searching variables at %s\n", buf);
465e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
466e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = find_available_vars_at(fd, pev, &vls, max_vls, externs);
467e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret <= 0) {
468e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_err("Failed to find variables at %s (%d)\n", buf, ret);
469e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto end;
470e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
471e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Some variables are found */
472e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fprintf(stdout, "Available variables at %s\n", buf);
473e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < ret; i++) {
474e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		vl = &vls[i];
475e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/*
476e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 * A probe point might be converted to
477e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 * several trace points.
478e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 */
479e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
480e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			vl->point.offset);
481e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(vl->point.symbol);
482e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		nvars = 0;
483e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (vl->vars) {
484e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			strlist__for_each(node, vl->vars) {
485e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				var = strchr(node->s, '\t') + 1;
486e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				if (strfilter__compare(_filter, var)) {
487e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					fprintf(stdout, "\t\t%s\n", node->s);
488e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					nvars++;
489e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				}
490e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
491e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			strlist__delete(vl->vars);
492e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
493e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (nvars == 0)
494e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			fprintf(stdout, "\t\t(No matched variables)\n");
495e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
496e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(vls);
497e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengend:
498e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(buf);
499e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
500e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
501e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
502e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Show available variables on given probe point */
503e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_available_vars(struct perf_probe_event *pevs, int npevs,
504e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			int max_vls, const char *module,
505e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			struct strfilter *_filter, bool externs)
506e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
507e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i, fd, ret = 0;
508e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
509e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = init_vmlinux();
510e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
511e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
512e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
513e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	setup_pager();
514e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
515e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < npevs && ret >= 0; i++) {
516e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		fd = open_vmlinux(module);
517e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (fd < 0) {
518e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_warning("Failed to open debug information file.\n");
519e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = fd;
520e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
521e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
522e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
523e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					     externs);
524e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
525e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
526e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
527e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
528e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#else	/* !DWARF_SUPPORT */
529e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
530e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
531e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					struct perf_probe_point *pp)
532e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
533e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct symbol *sym;
534e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
535e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	sym = __find_kernel_function_by_name(tp->symbol, NULL);
536e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!sym) {
537e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_err("Failed to find symbol %s in kernel.\n", tp->symbol);
538e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOENT;
539e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
540e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pp->function = strdup(tp->symbol);
541e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->function == NULL)
542e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
543e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pp->offset = tp->offset;
544e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pp->retprobe = tp->retprobe;
545e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
546e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
547e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
548e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
549e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int try_to_find_probe_trace_events(struct perf_probe_event *pev,
550e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				struct probe_trace_event **tevs __unused,
551e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				int max_tevs __unused, const char *mod __unused)
552e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
553e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (perf_probe_event_need_dwarf(pev)) {
554e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Debuginfo-analysis is not supported.\n");
555e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOSYS;
556e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
557e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
558e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
559e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
560e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_line_range(struct line_range *lr __unused, const char *module __unused)
561e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
562e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_warning("Debuginfo-analysis is not supported.\n");
563e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return -ENOSYS;
564e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
565e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
566e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_available_vars(struct perf_probe_event *pevs __unused,
567e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			int npevs __unused, int max_vls __unused,
568e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			const char *module __unused,
569e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			struct strfilter *filter __unused,
570e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			bool externs __unused)
571e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
572e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_warning("Debuginfo-analysis is not supported.\n");
573e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return -ENOSYS;
574e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
575e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif
576e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
577e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_line_num(char **ptr, int *val, const char *what)
578e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
579e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *start = *ptr;
580e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
581e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	errno = 0;
582e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	*val = strtol(*ptr, ptr, 0);
583e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (errno || *ptr == start) {
584e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		semantic_error("'%s' is not a valid number.\n", what);
585e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
586e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
587e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
588e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
589e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
590e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*
591e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Stuff 'lr' according to the line range described by 'arg'.
592e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * The line range syntax is described by:
593e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
594e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *         SRC[:SLN[+NUM|-ELN]]
595e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *         FNC[@SRC][:SLN[+NUM|-ELN]]
596e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */
597e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint parse_line_range_desc(const char *arg, struct line_range *lr)
598e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
599e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *range, *file, *name = strdup(arg);
600e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int err;
601e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
602e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!name)
603e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
604e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
605e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	lr->start = 0;
606e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	lr->end = INT_MAX;
607e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
608e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	range = strchr(name, ':');
609e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (range) {
610e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		*range++ = '\0';
611e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
612e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		err = parse_line_num(&range, &lr->start, "start line");
613e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (err)
614e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto err;
615e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
616e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (*range == '+' || *range == '-') {
617e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			const char c = *range++;
618e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
619e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			err = parse_line_num(&range, &lr->end, "end line");
620e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (err)
621e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				goto err;
622e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
623e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (c == '+') {
624e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				lr->end += lr->start;
625e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				/*
626e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 * Adjust the number of lines here.
627e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 * If the number of lines == 1, the
628e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 * the end of line should be equal to
629e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 * the start of line.
630e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 */
631e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				lr->end--;
632e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
633e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
634e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
635e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Line range is %d to %d\n", lr->start, lr->end);
636e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
637e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		err = -EINVAL;
638e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (lr->start > lr->end) {
639e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			semantic_error("Start line must be smaller"
640e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				       " than end line.\n");
641e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto err;
642e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
643e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (*range != '\0') {
644e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			semantic_error("Tailing with invalid str '%s'.\n", range);
645e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto err;
646e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
647e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
648e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
649e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	file = strchr(name, '@');
650e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (file) {
651e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		*file = '\0';
652e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		lr->file = strdup(++file);
653e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (lr->file == NULL) {
654e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			err = -ENOMEM;
655e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto err;
656e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
657e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		lr->function = name;
658e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} else if (strchr(name, '.'))
659e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		lr->file = name;
660e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else
661e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		lr->function = name;
662e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
663e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
664e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerr:
665e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(name);
666e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return err;
667e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
668e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
669e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Check the name is good for event/group */
670e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic bool check_event_name(const char *name)
671e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
672e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!isalpha(*name) && *name != '_')
673e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return false;
674e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (*++name != '\0') {
675e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!isalpha(*name) && !isdigit(*name) && *name != '_')
676e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return false;
677e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
678e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return true;
679e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
680e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
681e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Parse probepoint definition. */
682e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
683e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
684e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct perf_probe_point *pp = &pev->point;
685e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *ptr, *tmp;
686e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char c, nc = 0;
687e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/*
688e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * <Syntax>
689e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * perf probe [EVENT=]SRC[:LN|;PTN]
690e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
691e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 *
692e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 * TODO:Group name support
693e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 */
694e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
695e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ptr = strpbrk(arg, ";=@+%");
696e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ptr && *ptr == '=') {	/* Event name */
697e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		*ptr = '\0';
698e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		tmp = ptr + 1;
699e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (strchr(arg, ':')) {
700e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			semantic_error("Group name is not supported yet.\n");
701e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ENOTSUP;
702e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
703e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!check_event_name(arg)) {
704e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			semantic_error("%s is bad for event name -it must "
705e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				       "follow C symbol-naming rule.\n", arg);
706e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -EINVAL;
707e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
708e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pev->event = strdup(arg);
709e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pev->event == NULL)
710e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ENOMEM;
711e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pev->group = NULL;
712e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		arg = tmp;
713e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
714e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
715e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ptr = strpbrk(arg, ";:+@%");
716e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ptr) {
717e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		nc = *ptr;
718e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		*ptr++ = '\0';
719e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
720e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
721e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tmp = strdup(arg);
722e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (tmp == NULL)
723e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
724e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
725e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Check arg is function or file and copy it */
726e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (strchr(tmp, '.'))	/* File */
727e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pp->file = tmp;
728e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else			/* Function */
729e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pp->function = tmp;
730e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
731e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Parse other options */
732e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (ptr) {
733e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		arg = ptr;
734e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		c = nc;
735e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (c == ';') {	/* Lazy pattern must be the last part */
736e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pp->lazy_line = strdup(arg);
737e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (pp->lazy_line == NULL)
738e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return -ENOMEM;
739e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
740e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
741e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ptr = strpbrk(arg, ";:+@%");
742e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ptr) {
743e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			nc = *ptr;
744e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			*ptr++ = '\0';
745e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
746e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		switch (c) {
747e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case ':':	/* Line number */
748e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pp->line = strtoul(arg, &tmp, 0);
749e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (*tmp != '\0') {
750e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				semantic_error("There is non-digit char"
751e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					       " in line number.\n");
752e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return -EINVAL;
753e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
754e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
755e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case '+':	/* Byte offset from a symbol */
756e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pp->offset = strtoul(arg, &tmp, 0);
757e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (*tmp != '\0') {
758e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				semantic_error("There is non-digit character"
759e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						" in offset.\n");
760e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return -EINVAL;
761e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
762e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
763e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case '@':	/* File name */
764e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (pp->file) {
765e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				semantic_error("SRC@SRC is not allowed.\n");
766e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return -EINVAL;
767e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
768e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pp->file = strdup(arg);
769e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (pp->file == NULL)
770e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return -ENOMEM;
771e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
772e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		case '%':	/* Probe places */
773e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (strcmp(arg, "return") == 0) {
774e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				pp->retprobe = 1;
775e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else {	/* Others not supported yet */
776e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				semantic_error("%%%s is not supported.\n", arg);
777e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return -ENOTSUP;
778e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
779e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
780e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		default:	/* Buggy case */
781e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_err("This program has a bug at %s:%d.\n",
782e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				__FILE__, __LINE__);
783e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ENOTSUP;
784e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
785e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
786e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
787e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
788e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Exclusion check */
789e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->lazy_line && pp->line) {
790e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		semantic_error("Lazy pattern can't be used with"
791e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			       " line number.\n");
792e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
793e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
794e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
795e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->lazy_line && pp->offset) {
796e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		semantic_error("Lazy pattern can't be used with offset.\n");
797e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
798e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
799e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
800e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->line && pp->offset) {
801e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		semantic_error("Offset can't be used with line number.\n");
802e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
803e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
804e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
805e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
806e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		semantic_error("File always requires line number or "
807e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			       "lazy pattern.\n");
808e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
809e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
810e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
811e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->offset && !pp->function) {
812e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		semantic_error("Offset requires an entry function.\n");
813e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
814e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
815e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
816e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->retprobe && !pp->function) {
817e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		semantic_error("Return probe requires an entry function.\n");
818e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
819e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
820e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
821e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
822e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		semantic_error("Offset/Line/Lazy pattern can't be used with "
823e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			       "return probe.\n");
824e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
825e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
826e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
827e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
828e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
829e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 pp->lazy_line);
830e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
831e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
832e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
833e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Parse perf-probe event argument */
834e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
835e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
836e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *tmp, *goodname;
837e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct perf_probe_arg_field **fieldp;
838e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
839e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("parsing arg: %s into ", str);
840e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
841e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tmp = strchr(str, '=');
842e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (tmp) {
843e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		arg->name = strndup(str, tmp - str);
844e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (arg->name == NULL)
845e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ENOMEM;
846e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("name:%s ", arg->name);
847e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		str = tmp + 1;
848e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
849e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
850e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tmp = strchr(str, ':');
851e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (tmp) {	/* Type setting */
852e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		*tmp = '\0';
853e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		arg->type = strdup(tmp + 1);
854e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (arg->type == NULL)
855e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ENOMEM;
856e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("type:%s ", arg->type);
857e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
858e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
859e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tmp = strpbrk(str, "-.[");
860e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!is_c_varname(str) || !tmp) {
861e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* A variable, register, symbol or special value */
862e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		arg->var = strdup(str);
863e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (arg->var == NULL)
864e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ENOMEM;
865e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("%s\n", arg->var);
866e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return 0;
867e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
868e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
869e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Structure fields or array element */
870e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	arg->var = strndup(str, tmp - str);
871e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (arg->var == NULL)
872e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
873e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	goodname = arg->var;
874e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("%s, ", arg->var);
875e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fieldp = &arg->field;
876e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
877e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	do {
878e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		*fieldp = zalloc(sizeof(struct perf_probe_arg_field));
879e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (*fieldp == NULL)
880e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ENOMEM;
881e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (*tmp == '[') {	/* Array */
882e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			str = tmp;
883e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			(*fieldp)->index = strtol(str + 1, &tmp, 0);
884e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			(*fieldp)->ref = true;
885e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (*tmp != ']' || tmp == str + 1) {
886e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				semantic_error("Array index must be a"
887e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						" number.\n");
888e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return -EINVAL;
889e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
890e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			tmp++;
891e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (*tmp == '\0')
892e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				tmp = NULL;
893e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else {		/* Structure */
894e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (*tmp == '.') {
895e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				str = tmp + 1;
896e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				(*fieldp)->ref = false;
897e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else if (tmp[1] == '>') {
898e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				str = tmp + 2;
899e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				(*fieldp)->ref = true;
900e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else {
901e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				semantic_error("Argument parse error: %s\n",
902e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					       str);
903e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return -EINVAL;
904e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
905e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			tmp = strpbrk(str, "-.[");
906e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
907e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (tmp) {
908e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			(*fieldp)->name = strndup(str, tmp - str);
909e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if ((*fieldp)->name == NULL)
910e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				return -ENOMEM;
911e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (*str != '[')
912e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				goodname = (*fieldp)->name;
913e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
914e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			fieldp = &(*fieldp)->next;
915e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
916e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} while (tmp);
917e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	(*fieldp)->name = strdup(str);
918e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if ((*fieldp)->name == NULL)
919e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
920e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (*str != '[')
921e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goodname = (*fieldp)->name;
922e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
923e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
924e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* If no name is specified, set the last field name (not array index)*/
925e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!arg->name) {
926e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		arg->name = strdup(goodname);
927e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (arg->name == NULL)
928e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return -ENOMEM;
929e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
930e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
931e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
932e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
933e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Parse perf-probe event command */
934e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
935e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
936e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char **argv;
937e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int argc, i, ret = 0;
938e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
939e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	argv = argv_split(cmd, &argc);
940e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!argv) {
941e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Failed to split arguments.\n");
942e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
943e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
944e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (argc - 1 > MAX_PROBE_ARGS) {
945e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		semantic_error("Too many probe arguments (%d).\n", argc - 1);
946e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = -ERANGE;
947e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto out;
948e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
949e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Parse probe point */
950e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = parse_perf_probe_point(argv[0], pev);
951e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
952e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto out;
953e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
954e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Copy arguments and ensure return probe has no C argument */
955e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pev->nargs = argc - 1;
956e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
957e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pev->args == NULL) {
958e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = -ENOMEM;
959e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto out;
960e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
961e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < pev->nargs && ret >= 0; i++) {
962e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
963e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret >= 0 &&
964e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    is_c_varname(pev->args[i].var) && pev->point.retprobe) {
965e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			semantic_error("You can't specify local variable for"
966e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				       " kretprobe.\n");
967e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = -EINVAL;
968e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
969e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
970e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout:
971e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	argv_free(argv);
972e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
973e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
974e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
975e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
976e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Return true if this perf_probe_event requires debuginfo */
977e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengbool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
978e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
979e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i;
980e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
981e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pev->point.file || pev->point.line || pev->point.lazy_line)
982e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return true;
983e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
984e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < pev->nargs; i++)
985e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (is_c_varname(pev->args[i].var))
986e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return true;
987e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
988e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return false;
989e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
990e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
991e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Parse probe_events event into struct probe_point */
992e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int parse_probe_trace_command(const char *cmd,
993e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					struct probe_trace_event *tev)
994e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
995e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct probe_trace_point *tp = &tev->point;
996e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char pr;
997e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *p;
998e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret, i, argc;
999e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char **argv;
1000e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1001e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("Parsing probe_events: %s\n", cmd);
1002e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	argv = argv_split(cmd, &argc);
1003e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!argv) {
1004e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Failed to split arguments.\n");
1005e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
1006e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1007e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (argc < 2) {
1008e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		semantic_error("Too few probe arguments.\n");
1009e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = -ERANGE;
1010e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto out;
1011e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1012e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1013e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Scan event and group name. */
1014e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
1015e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		     &pr, (float *)(void *)&tev->group,
1016e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		     (float *)(void *)&tev->event);
1017e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret != 3) {
1018e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		semantic_error("Failed to parse event name: %s\n", argv[0]);
1019e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = -EINVAL;
1020e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto out;
1021e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1022e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
1023e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1024e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tp->retprobe = (pr == 'r');
1025e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1026e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Scan function name and offset */
1027e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol,
1028e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		     &tp->offset);
1029e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret == 1)
1030e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		tp->offset = 0;
1031e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1032e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tev->nargs = argc - 2;
1033e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1034e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (tev->args == NULL) {
1035e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = -ENOMEM;
1036e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto out;
1037e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1038e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < tev->nargs; i++) {
1039e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		p = strchr(argv[i + 2], '=');
1040e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (p)	/* We don't need which register is assigned. */
1041e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			*p++ = '\0';
1042e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
1043e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p = argv[i + 2];
1044e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		tev->args[i].name = strdup(argv[i + 2]);
1045e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* TODO: parse regs and offset */
1046e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		tev->args[i].value = strdup(p);
1047e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (tev->args[i].name == NULL || tev->args[i].value == NULL) {
1048e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = -ENOMEM;
1049e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto out;
1050e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1051e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1052e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = 0;
1053e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout:
1054e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	argv_free(argv);
1055e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1056e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1057e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1058e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Compose only probe arg */
1059e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
1060e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1061e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct perf_probe_arg_field *field = pa->field;
1062e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret;
1063e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *tmp = buf;
1064e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1065e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pa->name && pa->var)
1066e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
1067e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else
1068e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
1069e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret <= 0)
1070e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto error;
1071e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tmp += ret;
1072e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	len -= ret;
1073e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1074e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (field) {
1075e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (field->name[0] == '[')
1076e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = e_snprintf(tmp, len, "%s", field->name);
1077e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
1078e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = e_snprintf(tmp, len, "%s%s",
1079e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					 field->ref ? "->" : ".", field->name);
1080e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret <= 0)
1081e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto error;
1082e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		tmp += ret;
1083e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		len -= ret;
1084e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		field = field->next;
1085e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1086e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1087e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pa->type) {
1088e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(tmp, len, ":%s", pa->type);
1089e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret <= 0)
1090e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto error;
1091e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		tmp += ret;
1092e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		len -= ret;
1093e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1094e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1095e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return tmp - buf;
1096e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror:
1097e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("Failed to synthesize perf probe argument: %s\n",
1098e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 strerror(-ret));
1099e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Compose only probe point (not argument) */
1103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *buf, *tmp;
1106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char offs[32] = "", line[32] = "", file[32] = "";
1107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret, len;
1108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	buf = zalloc(MAX_CMDLEN);
1110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (buf == NULL) {
1111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = -ENOMEM;
1112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto error;
1113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->offset) {
1115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(offs, 32, "+%lu", pp->offset);
1116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret <= 0)
1117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto error;
1118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->line) {
1120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(line, 32, ":%d", pp->line);
1121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret <= 0)
1122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto error;
1123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->file) {
1125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		tmp = pp->file;
1126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		len = strlen(tmp);
1127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (len > 30) {
1128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			tmp = strchr(pp->file + len - 30, '/');
1129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			tmp = tmp ? tmp + 1 : pp->file + len - 30;
1130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(file, 32, "@%s", tmp);
1132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret <= 0)
1133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto error;
1134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->function)
1137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
1138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 offs, pp->retprobe ? "%return" : "", line,
1139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 file);
1140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else
1141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
1142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret <= 0)
1143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto error;
1144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return buf;
1146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror:
1147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("Failed to synthesize perf probe point: %s\n",
1148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 strerror(-ret));
1149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (buf)
1150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(buf);
1151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return NULL;
1152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#if 0
1155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengchar *synthesize_perf_probe_command(struct perf_probe_event *pev)
1156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *buf;
1158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i, len, ret;
1159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	buf = synthesize_perf_probe_point(&pev->point);
1161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!buf)
1162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return NULL;
1163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	len = strlen(buf);
1165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < pev->nargs; i++) {
1166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
1167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 pev->args[i].name);
1168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret <= 0) {
1169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			free(buf);
1170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return NULL;
1171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		len += ret;
1173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return buf;
1176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif
1178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
1180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					     char **buf, size_t *buflen,
1181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					     int depth)
1182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret;
1184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ref->next) {
1185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
1186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng							 buflen, depth + 1);
1187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (depth < 0)
1188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto out;
1189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
1192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
1193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		depth = ret;
1194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else {
1195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		*buf += ret;
1196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		*buflen -= ret;
1197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout:
1199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return depth;
1200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
1204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				       char *buf, size_t buflen)
1205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct probe_trace_arg_ref *ref = arg->ref;
1207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret, depth = 0;
1208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *tmp = buf;
1209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Argument name or separator */
1211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (arg->name)
1212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(buf, buflen, " %s=", arg->name);
1213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else
1214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(buf, buflen, " ");
1215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
1216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
1217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	buf += ret;
1218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	buflen -= ret;
1219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Special case: @XXX */
1221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (arg->value[0] == '@' && arg->ref)
1222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ref = ref->next;
1223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Dereferencing arguments */
1225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ref) {
1226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		depth = __synthesize_probe_trace_arg_ref(ref, &buf,
1227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng							  &buflen, 1);
1228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (depth < 0)
1229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return depth;
1230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Print argument value */
1233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (arg->value[0] == '@' && arg->ref)
1234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(buf, buflen, "%s%+ld", arg->value,
1235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 arg->ref->offset);
1236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else
1237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(buf, buflen, "%s", arg->value);
1238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
1239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
1240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	buf += ret;
1241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	buflen -= ret;
1242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Closing */
1244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (depth--) {
1245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(buf, buflen, ")");
1246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
1247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return ret;
1248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		buf += ret;
1249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		buflen -= ret;
1250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Print argument type */
1252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (arg->type) {
1253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(buf, buflen, ":%s", arg->type);
1254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret <= 0)
1255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return ret;
1256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		buf += ret;
1257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return buf - tmp;
1260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengchar *synthesize_probe_trace_command(struct probe_trace_event *tev)
1263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct probe_trace_point *tp = &tev->point;
1265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *buf;
1266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i, len, ret;
1267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	buf = zalloc(MAX_CMDLEN);
1269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (buf == NULL)
1270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return NULL;
1271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu",
1273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 tp->retprobe ? 'r' : 'p',
1274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 tev->group, tev->event,
1275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 tp->symbol, tp->offset);
1276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (len <= 0)
1277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto error;
1278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < tev->nargs; i++) {
1280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,
1281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						  MAX_CMDLEN - len);
1282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret <= 0)
1283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto error;
1284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		len += ret;
1285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return buf;
1288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror:
1289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(buf);
1290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return NULL;
1291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int convert_to_perf_probe_event(struct probe_trace_event *tev,
1294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				       struct perf_probe_event *pev)
1295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char buf[64] = "";
1297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i, ret;
1298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Convert event/group name */
1300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pev->event = strdup(tev->event);
1301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pev->group = strdup(tev->group);
1302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pev->event == NULL || pev->group == NULL)
1303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
1304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Convert trace_point to probe_point */
1306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point);
1307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
1308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
1309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Convert trace_arg to probe_arg */
1311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pev->nargs = tev->nargs;
1312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
1313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pev->args == NULL)
1314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
1315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < tev->nargs && ret >= 0; i++) {
1316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (tev->args[i].name)
1317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pev->args[i].name = strdup(tev->args[i].name);
1318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else {
1319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = synthesize_probe_trace_arg(&tev->args[i],
1320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng							  buf, 64);
1321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pev->args[i].name = strdup(buf);
1322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pev->args[i].name == NULL && ret >= 0)
1324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = -ENOMEM;
1325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
1328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		clear_perf_probe_event(pev);
1329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1332e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid clear_perf_probe_event(struct perf_probe_event *pev)
1334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct perf_probe_point *pp = &pev->point;
1336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct perf_probe_arg_field *field, *next;
1337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i;
1338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pev->event)
1340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(pev->event);
1341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pev->group)
1342e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(pev->group);
1343e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->file)
1344e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(pp->file);
1345e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->function)
1346e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(pp->function);
1347e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pp->lazy_line)
1348e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(pp->lazy_line);
1349e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < pev->nargs; i++) {
1350e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pev->args[i].name)
1351e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			free(pev->args[i].name);
1352e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pev->args[i].var)
1353e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			free(pev->args[i].var);
1354e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pev->args[i].type)
1355e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			free(pev->args[i].type);
1356e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		field = pev->args[i].field;
1357e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		while (field) {
1358e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			next = field->next;
1359e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (field->name)
1360e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				free(field->name);
1361e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			free(field);
1362e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			field = next;
1363e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1364e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1365e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pev->args)
1366e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(pev->args);
1367e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	memset(pev, 0, sizeof(*pev));
1368e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1369e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1370e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void clear_probe_trace_event(struct probe_trace_event *tev)
1371e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1372e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct probe_trace_arg_ref *ref, *next;
1373e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i;
1374e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1375e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (tev->event)
1376e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(tev->event);
1377e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (tev->group)
1378e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(tev->group);
1379e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (tev->point.symbol)
1380e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(tev->point.symbol);
1381e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < tev->nargs; i++) {
1382e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (tev->args[i].name)
1383e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			free(tev->args[i].name);
1384e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (tev->args[i].value)
1385e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			free(tev->args[i].value);
1386e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (tev->args[i].type)
1387e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			free(tev->args[i].type);
1388e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ref = tev->args[i].ref;
1389e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		while (ref) {
1390e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			next = ref->next;
1391e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			free(ref);
1392e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ref = next;
1393e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1394e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1395e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (tev->args)
1396e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(tev->args);
1397e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	memset(tev, 0, sizeof(*tev));
1398e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1399e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1400e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int open_kprobe_events(bool readwrite)
1401e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1402e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char buf[PATH_MAX];
1403e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *__debugfs;
1404e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret;
1405e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1406e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	__debugfs = debugfs_find_mountpoint();
1407e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (__debugfs == NULL) {
1408e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Debugfs is not mounted.\n");
1409e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOENT;
1410e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1411e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1412e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs);
1413e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret >= 0) {
1414e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Opening %s write=%d\n", buf, readwrite);
1415e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (readwrite && !probe_event_dry_run)
1416e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = open(buf, O_RDWR, O_APPEND);
1417e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
1418e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = open(buf, O_RDONLY, 0);
1419e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1420e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1421e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0) {
1422e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (errno == ENOENT)
1423e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_warning("kprobe_events file does not exist - please"
1424e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				 " rebuild kernel with CONFIG_KPROBE_EVENT.\n");
1425e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
1426e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_warning("Failed to open kprobe_events file: %s\n",
1427e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				   strerror(errno));
1428e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1429e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1430e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1431e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1432e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Get raw string list of current kprobe_events */
1433e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct strlist *get_probe_trace_command_rawlist(int fd)
1434e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1435e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret, idx;
1436e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	FILE *fp;
1437e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char buf[MAX_CMDLEN];
1438e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *p;
1439e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct strlist *sl;
1440e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1441e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	sl = strlist__new(true, NULL);
1442e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1443e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fp = fdopen(dup(fd), "r");
1444e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	while (!feof(fp)) {
1445e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		p = fgets(buf, MAX_CMDLEN, fp);
1446e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!p)
1447e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
1448e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1449e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		idx = strlen(p) - 1;
1450e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (p[idx] == '\n')
1451e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			p[idx] = '\0';
1452e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = strlist__add(sl, buf);
1453e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0) {
1454e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_debug("strlist__add failed: %s\n", strerror(-ret));
1455e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			strlist__delete(sl);
1456e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return NULL;
1457e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1458e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1459e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fclose(fp);
1460e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1461e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return sl;
1462e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1463e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1464e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Show an event */
1465e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int show_perf_probe_event(struct perf_probe_event *pev)
1466e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1467e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i, ret;
1468e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char buf[128];
1469e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *place;
1470e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1471e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Synthesize only event probe point */
1472e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	place = synthesize_perf_probe_point(&pev->point);
1473e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!place)
1474e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
1475e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1476e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event);
1477e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
1478e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
1479e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1480e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	printf("  %-20s (on %s", buf, place);
1481e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1482e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pev->nargs > 0) {
1483e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printf(" with");
1484e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		for (i = 0; i < pev->nargs; i++) {
1485e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = synthesize_perf_probe_arg(&pev->args[i],
1486e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng							buf, 128);
1487e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (ret < 0)
1488e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				break;
1489e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			printf(" %s", buf);
1490e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1491e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1492e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	printf(")\n");
1493e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(place);
1494e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1495e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1496e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1497e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* List up current perf-probe events */
1498e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_perf_probe_events(void)
1499e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1500e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int fd, ret;
1501e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct probe_trace_event tev;
1502e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct perf_probe_event pev;
1503e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct strlist *rawlist;
1504e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct str_node *ent;
1505e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1506e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	setup_pager();
1507e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = init_vmlinux();
1508e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
1509e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
1510e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1511e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	memset(&tev, 0, sizeof(tev));
1512e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	memset(&pev, 0, sizeof(pev));
1513e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1514e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fd = open_kprobe_events(false);
1515e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (fd < 0)
1516e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return fd;
1517e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1518e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	rawlist = get_probe_trace_command_rawlist(fd);
1519e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	close(fd);
1520e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!rawlist)
1521e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOENT;
1522e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1523e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	strlist__for_each(ent, rawlist) {
1524e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = parse_probe_trace_command(ent->s, &tev);
1525e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret >= 0) {
1526e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = convert_to_perf_probe_event(&tev, &pev);
1527e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (ret >= 0)
1528e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				ret = show_perf_probe_event(&pev);
1529e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1530e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		clear_perf_probe_event(&pev);
1531e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		clear_probe_trace_event(&tev);
1532e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
1533e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
1534e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1535e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	strlist__delete(rawlist);
1536e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1537e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1538e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1539e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1540e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* Get current perf-probe event names */
1541e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct strlist *get_probe_trace_event_names(int fd, bool include_group)
1542e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1543e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char buf[128];
1544e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct strlist *sl, *rawlist;
1545e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct str_node *ent;
1546e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct probe_trace_event tev;
1547e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret = 0;
1548e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1549e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	memset(&tev, 0, sizeof(tev));
1550e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	rawlist = get_probe_trace_command_rawlist(fd);
1551e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	sl = strlist__new(true, NULL);
1552e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	strlist__for_each(ent, rawlist) {
1553e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = parse_probe_trace_command(ent->s, &tev);
1554e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
1555e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
1556e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (include_group) {
1557e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = e_snprintf(buf, 128, "%s:%s", tev.group,
1558e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					tev.event);
1559e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (ret >= 0)
1560e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				ret = strlist__add(sl, buf);
1561e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else
1562e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = strlist__add(sl, tev.event);
1563e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		clear_probe_trace_event(&tev);
1564e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
1565e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
1566e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1567e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	strlist__delete(rawlist);
1568e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1569e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0) {
1570e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		strlist__delete(sl);
1571e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return NULL;
1572e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1573e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return sl;
1574e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1575e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1576e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int write_probe_trace_event(int fd, struct probe_trace_event *tev)
1577e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1578e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret = 0;
1579e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *buf = synthesize_probe_trace_command(tev);
1580e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1581e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!buf) {
1582e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Failed to synthesize probe trace event.\n");
1583e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
1584e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1585e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1586e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("Writing event: %s\n", buf);
1587e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!probe_event_dry_run) {
1588e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = write(fd, buf, strlen(buf));
1589e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret <= 0)
1590e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_warning("Failed to write event: %s\n",
1591e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				   strerror(errno));
1592e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1593e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(buf);
1594e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1595e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1596e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1597e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int get_new_event_name(char *buf, size_t len, const char *base,
1598e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			      struct strlist *namelist, bool allow_suffix)
1599e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1600e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i, ret;
1601e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1602e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Try no suffix */
1603e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = e_snprintf(buf, len, "%s", base);
1604e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0) {
1605e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("snprintf() failed: %s\n", strerror(-ret));
1606e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
1607e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1608e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!strlist__has_entry(namelist, buf))
1609e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return 0;
1610e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1611e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!allow_suffix) {
1612e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Error: event \"%s\" already exists. "
1613e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			   "(Use -f to force duplicates.)\n", base);
1614e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EEXIST;
1615e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1616e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1617e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Try to add suffix */
1618e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 1; i < MAX_EVENT_INDEX; i++) {
1619e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = e_snprintf(buf, len, "%s_%d", base, i);
1620e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0) {
1621e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			pr_debug("snprintf() failed: %s\n", strerror(-ret));
1622e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			return ret;
1623e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1624e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!strlist__has_entry(namelist, buf))
1625e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
1626e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1627e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (i == MAX_EVENT_INDEX) {
1628e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Too many events are on the same function.\n");
1629e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = -ERANGE;
1630e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1631e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1632e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1633e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1634e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1635e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __add_probe_trace_events(struct perf_probe_event *pev,
1636e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				     struct probe_trace_event *tevs,
1637e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				     int ntevs, bool allow_suffix)
1638e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1639e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i, fd, ret;
1640e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct probe_trace_event *tev = NULL;
1641e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char buf[64];
1642e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *event, *group;
1643e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct strlist *namelist;
1644e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1645e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fd = open_kprobe_events(true);
1646e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (fd < 0)
1647e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return fd;
1648e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Get current event names */
1649e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	namelist = get_probe_trace_event_names(fd, false);
1650e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!namelist) {
1651e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Failed to get current event list.\n");
1652e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EIO;
1653e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1654e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1655e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = 0;
1656e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":");
1657e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < ntevs; i++) {
1658e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		tev = &tevs[i];
1659e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pev->event)
1660e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			event = pev->event;
1661e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
1662e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (pev->point.function)
1663e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				event = pev->point.function;
1664e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			else
1665e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				event = tev->point.symbol;
1666e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (pev->group)
1667e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			group = pev->group;
1668e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else
1669e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			group = PERFPROBE_GROUP;
1670e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1671e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* Get an unused new event name */
1672e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = get_new_event_name(buf, 64, event,
1673e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					 namelist, allow_suffix);
1674e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
1675e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
1676e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		event = buf;
1677e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1678e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		tev->event = strdup(event);
1679e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		tev->group = strdup(group);
1680e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (tev->event == NULL || tev->group == NULL) {
1681e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = -ENOMEM;
1682e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
1683e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1684e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = write_probe_trace_event(fd, tev);
1685e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
1686e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
1687e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* Add added event name to namelist */
1688e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		strlist__add(namelist, event);
1689e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1690e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* Trick here - save current event/group */
1691e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		event = pev->event;
1692e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		group = pev->group;
1693e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pev->event = tev->event;
1694e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pev->group = tev->group;
1695e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		show_perf_probe_event(pev);
1696e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* Trick here - restore current event/group */
1697e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pev->event = (char *)event;
1698e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pev->group = (char *)group;
1699e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1700e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/*
1701e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 * Probes after the first probe which comes from same
1702e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 * user input are always allowed to add suffix, because
1703e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 * there might be several addresses corresponding to
1704e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 * one code line.
1705e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		 */
1706e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		allow_suffix = true;
1707e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1708e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1709e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret >= 0) {
1710e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* Show how to use the event. */
1711e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printf("\nYou can now use it on all perf tools, such as:\n\n");
1712e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
1713e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 tev->event);
1714e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1715e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1716e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	strlist__delete(namelist);
1717e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	close(fd);
1718e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1719e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1720e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1721e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int convert_to_probe_trace_events(struct perf_probe_event *pev,
1722e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					  struct probe_trace_event **tevs,
1723e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					  int max_tevs, const char *module)
1724e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1725e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct symbol *sym;
1726e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret = 0, i;
1727e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct probe_trace_event *tev;
1728e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1729e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Convert perf_probe_event with debuginfo */
1730e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module);
1731e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret != 0)
1732e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
1733e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1734e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Allocate trace event buffer */
1735e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tev = *tevs = zalloc(sizeof(struct probe_trace_event));
1736e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (tev == NULL)
1737e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
1738e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1739e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Copy parameters */
1740e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tev->point.symbol = strdup(pev->point.function);
1741e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (tev->point.symbol == NULL) {
1742e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = -ENOMEM;
1743e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto error;
1744e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1745e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tev->point.offset = pev->point.offset;
1746e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tev->point.retprobe = pev->point.retprobe;
1747e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	tev->nargs = pev->nargs;
1748e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (tev->nargs) {
1749e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		tev->args = zalloc(sizeof(struct probe_trace_arg)
1750e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				   * tev->nargs);
1751e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (tev->args == NULL) {
1752e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = -ENOMEM;
1753e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto error;
1754e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1755e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		for (i = 0; i < tev->nargs; i++) {
1756e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (pev->args[i].name) {
1757e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				tev->args[i].name = strdup(pev->args[i].name);
1758e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				if (tev->args[i].name == NULL) {
1759e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					ret = -ENOMEM;
1760e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					goto error;
1761e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				}
1762e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
1763e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			tev->args[i].value = strdup(pev->args[i].var);
1764e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (tev->args[i].value == NULL) {
1765e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				ret = -ENOMEM;
1766e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				goto error;
1767e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
1768e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (pev->args[i].type) {
1769e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				tev->args[i].type = strdup(pev->args[i].type);
1770e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				if (tev->args[i].type == NULL) {
1771e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					ret = -ENOMEM;
1772e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					goto error;
1773e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				}
1774e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
1775e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1776e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1777e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1778e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Currently just checking function name from symbol map */
1779e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	sym = __find_kernel_function_by_name(tev->point.symbol, NULL);
1780e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!sym) {
1781e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_warning("Kernel symbol \'%s\' not found.\n",
1782e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			   tev->point.symbol);
1783e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = -ENOENT;
1784e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto error;
1785e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1786e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1787e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 1;
1788e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror:
1789e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	clear_probe_trace_event(tev);
1790e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(tev);
1791e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	*tevs = NULL;
1792e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1793e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1794e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1795e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct __event_package {
1796e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct perf_probe_event		*pev;
1797e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct probe_trace_event	*tevs;
1798e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int				ntevs;
1799e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
1800e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1801e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
1802e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			  int max_tevs, const char *module, bool force_add)
1803e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1804e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i, j, ret;
1805e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct __event_package *pkgs;
1806e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1807e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pkgs = zalloc(sizeof(struct __event_package) * npevs);
1808e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (pkgs == NULL)
1809e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -ENOMEM;
1810e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1811e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Init vmlinux path */
1812e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = init_vmlinux();
1813e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0) {
1814e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(pkgs);
1815e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
1816e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1817e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1818e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Loop 1: convert all events */
1819e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < npevs; i++) {
1820e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pkgs[i].pev = &pevs[i];
1821e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* Convert with or without debuginfo */
1822e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret  = convert_to_probe_trace_events(pkgs[i].pev,
1823e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						     &pkgs[i].tevs,
1824e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						     max_tevs,
1825e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						     module);
1826e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
1827e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			goto end;
1828e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pkgs[i].ntevs = ret;
1829e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1830e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1831e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Loop 2: add all events */
1832e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < npevs; i++) {
1833e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
1834e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						pkgs[i].ntevs, force_add);
1835e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
1836e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
1837e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1838e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengend:
1839e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Loop 3: cleanup and free trace events  */
1840e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; i < npevs; i++) {
1841e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		for (j = 0; j < pkgs[i].ntevs; j++)
1842e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			clear_probe_trace_event(&pkgs[i].tevs[j]);
1843e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(pkgs[i].tevs);
1844e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1845e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(pkgs);
1846e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1847e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1848e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1849e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1850e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __del_trace_probe_event(int fd, struct str_node *ent)
1851e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1852e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *p;
1853e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char buf[128];
1854e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret;
1855e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1856e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Convert from perf-probe event to trace-probe event */
1857e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = e_snprintf(buf, 128, "-:%s", ent->s);
1858e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
1859e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto error;
1860e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1861e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	p = strchr(buf + 2, ':');
1862e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!p) {
1863e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Internal error: %s should have ':' but not.\n",
1864e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			 ent->s);
1865e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = -ENOTSUP;
1866e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto error;
1867e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1868e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	*p = '/';
1869e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1870e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_debug("Writing event: %s\n", buf);
1871e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = write(fd, buf, strlen(buf));
1872e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
1873e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		goto error;
1874e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1875e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	printf("Remove event: %s\n", ent->s);
1876e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
1877e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengerror:
1878e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	pr_warning("Failed to delete event: %s\n", strerror(-ret));
1879e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1880e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1881e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1882e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int del_trace_probe_event(int fd, const char *group,
1883e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				  const char *event, struct strlist *namelist)
1884e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1885e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char buf[128];
1886e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct str_node *ent, *n;
1887e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int found = 0, ret = 0;
1888e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1889e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = e_snprintf(buf, 128, "%s:%s", group, event);
1890e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0) {
1891e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_err("Failed to copy event.\n");
1892e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
1893e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1894e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1895e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (strpbrk(buf, "*?")) { /* Glob-exp */
1896e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		strlist__for_each_safe(ent, n, namelist)
1897e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (strglobmatch(ent->s, buf)) {
1898e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				found++;
1899e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				ret = __del_trace_probe_event(fd, ent);
1900e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				if (ret < 0)
1901e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					break;
1902e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				strlist__remove(namelist, ent);
1903e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
1904e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} else {
1905e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ent = strlist__find(namelist, buf);
1906e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ent) {
1907e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			found++;
1908e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = __del_trace_probe_event(fd, ent);
1909e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (ret >= 0)
1910e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				strlist__remove(namelist, ent);
1911e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1912e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1913e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (found == 0 && ret >= 0)
1914e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_info("Info: Event \"%s\" does not exist.\n", buf);
1915e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1916e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1917e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1918e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1919e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint del_perf_probe_events(struct strlist *dellist)
1920e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1921e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int fd, ret = 0;
1922e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *group, *event;
1923e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	char *p, *str;
1924e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct str_node *ent;
1925e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct strlist *namelist;
1926e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1927e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fd = open_kprobe_events(true);
1928e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (fd < 0)
1929e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return fd;
1930e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1931e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* Get current event names */
1932e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	namelist = get_probe_trace_event_names(fd, true);
1933e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (namelist == NULL)
1934e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
1935e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1936e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	strlist__for_each(ent, dellist) {
1937e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		str = strdup(ent->s);
1938e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (str == NULL) {
1939e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			ret = -ENOMEM;
1940e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
1941e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1942e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Parsing: %s\n", str);
1943e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		p = strchr(str, ':');
1944e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (p) {
1945e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			group = str;
1946e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			*p = '\0';
1947e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			event = p + 1;
1948e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else {
1949e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			group = "*";
1950e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			event = str;
1951e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
1952e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_debug("Group: %s, Event: %s\n", group, event);
1953e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		ret = del_trace_probe_event(fd, group, event, namelist);
1954e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		free(str);
1955e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (ret < 0)
1956e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
1957e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1958e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	strlist__delete(namelist);
1959e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	close(fd);
1960e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1961e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return ret;
1962e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1963e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* TODO: don't use a global variable for filter ... */
1964e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct strfilter *available_func_filter;
1965e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1966e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*
1967e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * If a symbol corresponds to a function with global binding and
1968e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * matches filter return 0. For all others return 1.
1969e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */
1970e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int filter_available_functions(struct map *map __unused,
1971e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				      struct symbol *sym)
1972e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1973e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (sym->binding == STB_GLOBAL &&
1974e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	    strfilter__compare(available_func_filter, sym->name))
1975e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return 0;
1976e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 1;
1977e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
1978e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1979e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint show_available_funcs(const char *module, struct strfilter *_filter)
1980e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
1981e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct map *map;
1982e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret;
1983e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1984e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	setup_pager();
1985e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1986e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = init_vmlinux();
1987e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (ret < 0)
1988e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return ret;
1989e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
1990e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	map = kernel_get_module_map(module);
1991e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!map) {
1992e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_err("Failed to find %s map.\n", (module) ? : "kernel");
1993e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
1994e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
1995e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	available_func_filter = _filter;
1996e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (map__load(map, filter_available_functions)) {
1997e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		pr_err("Failed to load map.\n");
1998e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return -EINVAL;
1999e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
2000e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!dso__sorted_by_name(map->dso, map->type))
2001e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		dso__sort_by_name(map->dso, map->type);
2002e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
2003e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2004e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
2005e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
2006