blob: 8d08e75b2dd3ed948a60b7ae2d70873b3957c25d [file] [log] [blame]
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001/*
2 * probe-event.c : perf-probe definition to kprobe_events format converter
3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22#define _GNU_SOURCE
23#include <sys/utsname.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27#include <errno.h>
28#include <stdio.h>
29#include <unistd.h>
30#include <stdlib.h>
31#include <string.h>
Masami Hiramatsu4de189f2009-11-30 19:20:17 -050032#include <stdarg.h>
33#include <limits.h>
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050034
35#undef _GNU_SOURCE
Masami Hiramatsu31facc52010-03-16 18:05:30 -040036#include "util.h"
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050037#include "event.h"
Masami Hiramatsue1c01d62009-11-30 19:20:05 -050038#include "string.h"
Masami Hiramatsu4de189f2009-11-30 19:20:17 -050039#include "strlist.h"
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050040#include "debug.h"
Masami Hiramatsu72041332010-01-05 17:47:10 -050041#include "cache.h"
Masami Hiramatsu631c9de2010-01-06 09:45:34 -050042#include "color.h"
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -040043#include "symbol.h"
44#include "thread.h"
Masami Hiramatsu7ca59892010-04-14 18:39:28 -040045#include "debugfs.h"
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -030046#include "trace-event.h" /* For __unused */
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050047#include "probe-event.h"
Masami Hiramatsu4235b042010-03-16 18:06:12 -040048#include "probe-finder.h"
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050049
50#define MAX_CMDLEN 256
51#define MAX_PROBE_ARGS 128
52#define PERFPROBE_GROUP "probe"
53
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -040054bool probe_event_dry_run; /* Dry run flag */
55
Masami Hiramatsu146a1432010-04-12 13:17:42 -040056#define semantic_error(msg ...) pr_err("Semantic error :" msg)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050057
Masami Hiramatsu4de189f2009-11-30 19:20:17 -050058/* If there is no space to write, returns -E2BIG. */
59static int e_snprintf(char *str, size_t size, const char *format, ...)
Masami Hiramatsu84988452009-12-07 12:00:53 -050060 __attribute__((format(printf, 3, 4)));
61
62static int e_snprintf(char *str, size_t size, const char *format, ...)
Masami Hiramatsu4de189f2009-11-30 19:20:17 -050063{
64 int ret;
65 va_list ap;
66 va_start(ap, format);
67 ret = vsnprintf(str, size, format, ap);
68 va_end(ap);
69 if (ret >= (int)size)
70 ret = -E2BIG;
71 return ret;
72}
73
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -030074static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
Arnaldo Carvalho de Melod28c6222010-04-27 21:20:43 -030075static struct machine machine;
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -040076
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -030077/* Initialize symbol maps and path of vmlinux */
Masami Hiramatsu146a1432010-04-12 13:17:42 -040078static int init_vmlinux(void)
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -040079{
Zhang, Yanmina1645ce2010-04-19 13:32:50 +080080 struct dso *kernel;
Masami Hiramatsu146a1432010-04-12 13:17:42 -040081 int ret;
82
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -040083 symbol_conf.sort_by_name = true;
84 if (symbol_conf.vmlinux_name == NULL)
85 symbol_conf.try_vmlinux_path = true;
86 else
87 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
Masami Hiramatsu146a1432010-04-12 13:17:42 -040088 ret = symbol__init();
89 if (ret < 0) {
90 pr_debug("Failed to init symbol map.\n");
91 goto out;
92 }
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -040093
Arnaldo Carvalho de Melod28c6222010-04-27 21:20:43 -030094 ret = machine__init(&machine, "/", 0);
95 if (ret < 0)
96 goto out;
97
Zhang, Yanmina1645ce2010-04-19 13:32:50 +080098 kernel = dso__new_kernel(symbol_conf.vmlinux_name);
99 if (kernel == NULL)
100 die("Failed to create kernel dso.");
101
Arnaldo Carvalho de Melod28c6222010-04-27 21:20:43 -0300102 ret = __machine__create_kernel_maps(&machine, kernel);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400103 if (ret < 0)
104 pr_debug("Failed to create kernel maps.\n");
105
106out:
107 if (ret < 0)
108 pr_warning("Failed to init vmlinux path.\n");
109 return ret;
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -0400110}
111
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300112#ifdef DWARF_SUPPORT
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -0400113static int open_vmlinux(void)
114{
Arnaldo Carvalho de Melod28c6222010-04-27 21:20:43 -0300115 if (map__load(machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) {
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -0400116 pr_debug("Failed to load kernel map.\n");
117 return -EINVAL;
118 }
Arnaldo Carvalho de Melod28c6222010-04-27 21:20:43 -0300119 pr_debug("Try to open %s\n", machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name);
120 return open(machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name, O_RDONLY);
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -0400121}
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300122
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400123/* Convert trace point to probe point with debuginfo */
124static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
125 struct perf_probe_point *pp)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300126{
127 struct symbol *sym;
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400128 int fd, ret = -ENOENT;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300129
Arnaldo Carvalho de Melod28c6222010-04-27 21:20:43 -0300130 sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION],
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300131 tp->symbol, NULL);
132 if (sym) {
133 fd = open_vmlinux();
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400134 if (fd >= 0) {
135 ret = find_perf_probe_point(fd,
136 sym->start + tp->offset, pp);
137 close(fd);
138 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300139 }
140 if (ret <= 0) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400141 pr_debug("Failed to find corresponding probes from "
142 "debuginfo. Use kprobe event information.\n");
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400143 pp->function = strdup(tp->symbol);
144 if (pp->function == NULL)
145 return -ENOMEM;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300146 pp->offset = tp->offset;
147 }
148 pp->retprobe = tp->retprobe;
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400149
150 return 0;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300151}
152
153/* Try to find perf_probe_event with debuginfo */
154static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
Masami Hiramatsuef4a3562010-04-21 15:56:40 -0400155 struct kprobe_trace_event **tevs,
156 int max_tevs)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300157{
158 bool need_dwarf = perf_probe_event_need_dwarf(pev);
159 int fd, ntevs;
160
161 fd = open_vmlinux();
162 if (fd < 0) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400163 if (need_dwarf) {
164 pr_warning("Failed to open debuginfo file.\n");
165 return fd;
166 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300167 pr_debug("Could not open vmlinux. Try to use symbols.\n");
168 return 0;
169 }
170
171 /* Searching trace events corresponding to probe event */
Masami Hiramatsuef4a3562010-04-21 15:56:40 -0400172 ntevs = find_kprobe_trace_events(fd, pev, tevs, max_tevs);
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300173 close(fd);
174
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400175 if (ntevs > 0) { /* Succeeded to find trace events */
176 pr_debug("find %d kprobe_trace_events.\n", ntevs);
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300177 return ntevs;
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400178 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300179
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400180 if (ntevs == 0) { /* No error but failed to find probe point. */
181 pr_warning("Probe point '%s' not found.\n",
182 synthesize_perf_probe_point(&pev->point));
183 return -ENOENT;
184 }
185 /* Error path : ntevs < 0 */
Masami Hiramatsu15eca302010-04-21 15:56:24 -0400186 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
187 if (ntevs == -EBADF) {
188 pr_warning("Warning: No dwarf info found in the vmlinux - "
189 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
190 if (!need_dwarf) {
191 pr_debug("Trying to use symbols.\nn");
192 return 0;
193 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300194 }
Masami Hiramatsu15eca302010-04-21 15:56:24 -0400195 return ntevs;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300196}
197
Masami Hiramatsu7cf0b792010-07-09 18:28:59 +0900198/*
199 * Find a src file from a DWARF tag path. Prepend optional source path prefix
200 * and chop off leading directories that do not exist. Result is passed back as
201 * a newly allocated path on success.
202 * Return 0 if file was found and readable, -errno otherwise.
203 */
204static int get_real_path(const char *raw_path, char **new_path)
205{
206 if (!symbol_conf.source_prefix) {
207 if (access(raw_path, R_OK) == 0) {
208 *new_path = strdup(raw_path);
209 return 0;
210 } else
211 return -errno;
212 }
213
214 *new_path = malloc((strlen(symbol_conf.source_prefix) +
215 strlen(raw_path) + 2));
216 if (!*new_path)
217 return -ENOMEM;
218
219 for (;;) {
220 sprintf(*new_path, "%s/%s", symbol_conf.source_prefix,
221 raw_path);
222
223 if (access(*new_path, R_OK) == 0)
224 return 0;
225
226 switch (errno) {
227 case ENAMETOOLONG:
228 case ENOENT:
229 case EROFS:
230 case EFAULT:
231 raw_path = strchr(++raw_path, '/');
232 if (!raw_path) {
233 free(*new_path);
234 *new_path = NULL;
235 return -ENOENT;
236 }
237 continue;
238
239 default:
240 free(*new_path);
241 *new_path = NULL;
242 return -errno;
243 }
244 }
245}
246
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300247#define LINEBUF_SIZE 256
248#define NR_ADDITIONAL_LINES 2
249
Masami Hiramatsud3b63d72010-04-14 18:39:42 -0400250static int show_one_line(FILE *fp, int l, bool skip, bool show_num)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300251{
252 char buf[LINEBUF_SIZE];
253 const char *color = PERF_COLOR_BLUE;
254
255 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
256 goto error;
257 if (!skip) {
258 if (show_num)
Masami Hiramatsud3b63d72010-04-14 18:39:42 -0400259 fprintf(stdout, "%7d %s", l, buf);
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300260 else
261 color_fprintf(stdout, color, " %s", buf);
262 }
263
264 while (strlen(buf) == LINEBUF_SIZE - 1 &&
265 buf[LINEBUF_SIZE - 2] != '\n') {
266 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
267 goto error;
268 if (!skip) {
269 if (show_num)
270 fprintf(stdout, "%s", buf);
271 else
272 color_fprintf(stdout, color, "%s", buf);
273 }
274 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400275
276 return 0;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300277error:
278 if (feof(fp))
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400279 pr_warning("Source file is shorter than expected.\n");
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300280 else
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400281 pr_warning("File read error: %s\n", strerror(errno));
282
283 return -1;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300284}
285
286/*
287 * Show line-range always requires debuginfo to find source file and
288 * line number.
289 */
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400290int show_line_range(struct line_range *lr)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300291{
Masami Hiramatsud3b63d72010-04-14 18:39:42 -0400292 int l = 1;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300293 struct line_node *ln;
294 FILE *fp;
295 int fd, ret;
Masami Hiramatsu7cf0b792010-07-09 18:28:59 +0900296 char *tmp;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300297
298 /* Search a line range */
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400299 ret = init_vmlinux();
300 if (ret < 0)
301 return ret;
302
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300303 fd = open_vmlinux();
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400304 if (fd < 0) {
305 pr_warning("Failed to open debuginfo file.\n");
306 return fd;
307 }
308
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300309 ret = find_line_range(fd, lr);
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300310 close(fd);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400311 if (ret == 0) {
312 pr_warning("Specified source line is not found.\n");
313 return -ENOENT;
314 } else if (ret < 0) {
315 pr_warning("Debuginfo analysis failed. (%d)\n", ret);
316 return ret;
317 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300318
Masami Hiramatsu7cf0b792010-07-09 18:28:59 +0900319 /* Convert source file path */
320 tmp = lr->path;
321 ret = get_real_path(tmp, &lr->path);
322 free(tmp); /* Free old path */
323 if (ret < 0) {
324 pr_warning("Failed to find source file. (%d)\n", ret);
325 return ret;
326 }
327
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300328 setup_pager();
329
330 if (lr->function)
331 fprintf(stdout, "<%s:%d>\n", lr->function,
332 lr->start - lr->offset);
333 else
334 fprintf(stdout, "<%s:%d>\n", lr->file, lr->start);
335
336 fp = fopen(lr->path, "r");
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400337 if (fp == NULL) {
338 pr_warning("Failed to open %s: %s\n", lr->path,
339 strerror(errno));
340 return -errno;
341 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300342 /* Skip to starting line number */
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400343 while (l < lr->start && ret >= 0)
344 ret = show_one_line(fp, l++, true, false);
345 if (ret < 0)
346 goto end;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300347
348 list_for_each_entry(ln, &lr->line_list, list) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400349 while (ln->line > l && ret >= 0)
350 ret = show_one_line(fp, (l++) - lr->offset,
351 false, false);
352 if (ret >= 0)
353 ret = show_one_line(fp, (l++) - lr->offset,
354 false, true);
355 if (ret < 0)
356 goto end;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300357 }
358
359 if (lr->end == INT_MAX)
360 lr->end = l + NR_ADDITIONAL_LINES;
Masami Hiramatsudda4ab32010-04-14 18:39:50 -0400361 while (l <= lr->end && !feof(fp) && ret >= 0)
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400362 ret = show_one_line(fp, (l++) - lr->offset, false, false);
363end:
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300364 fclose(fp);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400365 return ret;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300366}
367
368#else /* !DWARF_SUPPORT */
369
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400370static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300371 struct perf_probe_point *pp)
372{
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400373 pp->function = strdup(tp->symbol);
374 if (pp->function == NULL)
375 return -ENOMEM;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300376 pp->offset = tp->offset;
377 pp->retprobe = tp->retprobe;
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400378
379 return 0;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300380}
381
382static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
Masami Hiramatsuef4a3562010-04-21 15:56:40 -0400383 struct kprobe_trace_event **tevs __unused,
384 int max_tevs __unused)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300385{
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400386 if (perf_probe_event_need_dwarf(pev)) {
387 pr_warning("Debuginfo-analysis is not supported.\n");
388 return -ENOSYS;
389 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300390 return 0;
391}
392
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400393int show_line_range(struct line_range *lr __unused)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300394{
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400395 pr_warning("Debuginfo-analysis is not supported.\n");
396 return -ENOSYS;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300397}
398
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -0400399#endif
400
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400401int parse_line_range_desc(const char *arg, struct line_range *lr)
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500402{
403 const char *ptr;
404 char *tmp;
405 /*
406 * <Syntax>
407 * SRC:SLN[+NUM|-ELN]
408 * FUNC[:SLN[+NUM|-ELN]]
409 */
410 ptr = strchr(arg, ':');
411 if (ptr) {
Masami Hiramatsud3b63d72010-04-14 18:39:42 -0400412 lr->start = (int)strtoul(ptr + 1, &tmp, 0);
Masami Hiramatsudda4ab32010-04-14 18:39:50 -0400413 if (*tmp == '+') {
Masami Hiramatsud3b63d72010-04-14 18:39:42 -0400414 lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0);
Masami Hiramatsudda4ab32010-04-14 18:39:50 -0400415 lr->end--; /*
416 * Adjust the number of lines here.
417 * If the number of lines == 1, the
418 * the end of line should be equal to
419 * the start of line.
420 */
421 } else if (*tmp == '-')
Masami Hiramatsud3b63d72010-04-14 18:39:42 -0400422 lr->end = (int)strtoul(tmp + 1, &tmp, 0);
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500423 else
Masami Hiramatsud3b63d72010-04-14 18:39:42 -0400424 lr->end = INT_MAX;
425 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
426 if (lr->start > lr->end) {
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500427 semantic_error("Start line must be smaller"
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400428 " than end line.\n");
429 return -EINVAL;
430 }
431 if (*tmp != '\0') {
432 semantic_error("Tailing with invalid character '%d'.\n",
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500433 *tmp);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400434 return -EINVAL;
435 }
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400436 tmp = strndup(arg, (ptr - arg));
Masami Hiramatsud3b63d72010-04-14 18:39:42 -0400437 } else {
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400438 tmp = strdup(arg);
Masami Hiramatsud3b63d72010-04-14 18:39:42 -0400439 lr->end = INT_MAX;
440 }
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400441
442 if (tmp == NULL)
443 return -ENOMEM;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500444
445 if (strchr(tmp, '.'))
446 lr->file = tmp;
447 else
448 lr->function = tmp;
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400449
450 return 0;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500451}
452
Masami Hiramatsub7702a22009-12-16 17:24:15 -0500453/* Check the name is good for event/group */
454static bool check_event_name(const char *name)
455{
456 if (!isalpha(*name) && *name != '_')
457 return false;
458 while (*++name != '\0') {
459 if (!isalpha(*name) && !isdigit(*name) && *name != '_')
460 return false;
461 }
462 return true;
463}
464
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500465/* Parse probepoint definition. */
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400466static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500467{
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400468 struct perf_probe_point *pp = &pev->point;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500469 char *ptr, *tmp;
470 char c, nc = 0;
471 /*
472 * <Syntax>
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500473 * perf probe [EVENT=]SRC[:LN|;PTN]
474 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
Masami Hiramatsuaf663d72009-12-15 10:32:18 -0500475 *
476 * TODO:Group name support
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500477 */
478
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500479 ptr = strpbrk(arg, ";=@+%");
480 if (ptr && *ptr == '=') { /* Event name */
Masami Hiramatsuaf663d72009-12-15 10:32:18 -0500481 *ptr = '\0';
482 tmp = ptr + 1;
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400483 if (strchr(arg, ':')) {
484 semantic_error("Group name is not supported yet.\n");
485 return -ENOTSUP;
486 }
487 if (!check_event_name(arg)) {
Masami Hiramatsub7702a22009-12-16 17:24:15 -0500488 semantic_error("%s is bad for event name -it must "
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400489 "follow C symbol-naming rule.\n", arg);
490 return -EINVAL;
491 }
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400492 pev->event = strdup(arg);
493 if (pev->event == NULL)
494 return -ENOMEM;
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400495 pev->group = NULL;
Masami Hiramatsuaf663d72009-12-15 10:32:18 -0500496 arg = tmp;
497 }
498
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500499 ptr = strpbrk(arg, ";:+@%");
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500500 if (ptr) {
501 nc = *ptr;
502 *ptr++ = '\0';
503 }
504
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400505 tmp = strdup(arg);
506 if (tmp == NULL)
507 return -ENOMEM;
508
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500509 /* Check arg is function or file and copy it */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400510 if (strchr(tmp, '.')) /* File */
511 pp->file = tmp;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500512 else /* Function */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400513 pp->function = tmp;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500514
515 /* Parse other options */
516 while (ptr) {
517 arg = ptr;
518 c = nc;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500519 if (c == ';') { /* Lazy pattern must be the last part */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400520 pp->lazy_line = strdup(arg);
521 if (pp->lazy_line == NULL)
522 return -ENOMEM;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500523 break;
524 }
525 ptr = strpbrk(arg, ";:+@%");
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500526 if (ptr) {
527 nc = *ptr;
528 *ptr++ = '\0';
529 }
530 switch (c) {
531 case ':': /* Line number */
532 pp->line = strtoul(arg, &tmp, 0);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400533 if (*tmp != '\0') {
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500534 semantic_error("There is non-digit char"
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400535 " in line number.\n");
536 return -EINVAL;
537 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500538 break;
539 case '+': /* Byte offset from a symbol */
540 pp->offset = strtoul(arg, &tmp, 0);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400541 if (*tmp != '\0') {
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500542 semantic_error("There is non-digit character"
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400543 " in offset.\n");
544 return -EINVAL;
545 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500546 break;
547 case '@': /* File name */
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400548 if (pp->file) {
549 semantic_error("SRC@SRC is not allowed.\n");
550 return -EINVAL;
551 }
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400552 pp->file = strdup(arg);
553 if (pp->file == NULL)
554 return -ENOMEM;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500555 break;
556 case '%': /* Probe places */
557 if (strcmp(arg, "return") == 0) {
558 pp->retprobe = 1;
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400559 } else { /* Others not supported yet */
560 semantic_error("%%%s is not supported.\n", arg);
561 return -ENOTSUP;
562 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500563 break;
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400564 default: /* Buggy case */
565 pr_err("This program has a bug at %s:%d.\n",
566 __FILE__, __LINE__);
567 return -ENOTSUP;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500568 break;
569 }
570 }
571
572 /* Exclusion check */
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400573 if (pp->lazy_line && pp->line) {
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500574 semantic_error("Lazy pattern can't be used with line number.");
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400575 return -EINVAL;
576 }
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500577
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400578 if (pp->lazy_line && pp->offset) {
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500579 semantic_error("Lazy pattern can't be used with offset.");
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400580 return -EINVAL;
581 }
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500582
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400583 if (pp->line && pp->offset) {
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500584 semantic_error("Offset can't be used with line number.");
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400585 return -EINVAL;
586 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500587
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400588 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500589 semantic_error("File always requires line number or "
590 "lazy pattern.");
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400591 return -EINVAL;
592 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500593
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400594 if (pp->offset && !pp->function) {
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500595 semantic_error("Offset requires an entry function.");
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400596 return -EINVAL;
597 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500598
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400599 if (pp->retprobe && !pp->function) {
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500600 semantic_error("Return probe requires an entry function.");
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400601 return -EINVAL;
602 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500603
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400604 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500605 semantic_error("Offset/Line/Lazy pattern can't be used with "
606 "return probe.");
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400607 return -EINVAL;
608 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500609
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400610 pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500611 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
612 pp->lazy_line);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400613 return 0;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500614}
615
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400616/* Parse perf-probe event argument */
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400617static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400618{
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400619 char *tmp, *goodname;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400620 struct perf_probe_arg_field **fieldp;
621
622 pr_debug("parsing arg: %s into ", str);
623
Masami Hiramatsu48481932010-04-12 13:16:53 -0400624 tmp = strchr(str, '=');
625 if (tmp) {
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400626 arg->name = strndup(str, tmp - str);
627 if (arg->name == NULL)
628 return -ENOMEM;
Masami Hiramatsu11a1ca32010-04-12 13:17:22 -0400629 pr_debug("name:%s ", arg->name);
Masami Hiramatsu48481932010-04-12 13:16:53 -0400630 str = tmp + 1;
631 }
632
Masami Hiramatsu11a1ca32010-04-12 13:17:22 -0400633 tmp = strchr(str, ':');
634 if (tmp) { /* Type setting */
635 *tmp = '\0';
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400636 arg->type = strdup(tmp + 1);
637 if (arg->type == NULL)
638 return -ENOMEM;
Masami Hiramatsu11a1ca32010-04-12 13:17:22 -0400639 pr_debug("type:%s ", arg->type);
640 }
641
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400642 tmp = strpbrk(str, "-.[");
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400643 if (!is_c_varname(str) || !tmp) {
644 /* A variable, register, symbol or special value */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400645 arg->var = strdup(str);
646 if (arg->var == NULL)
647 return -ENOMEM;
Masami Hiramatsu48481932010-04-12 13:16:53 -0400648 pr_debug("%s\n", arg->var);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400649 return 0;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400650 }
651
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400652 /* Structure fields or array element */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400653 arg->var = strndup(str, tmp - str);
654 if (arg->var == NULL)
655 return -ENOMEM;
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400656 goodname = arg->var;
Masami Hiramatsu48481932010-04-12 13:16:53 -0400657 pr_debug("%s, ", arg->var);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400658 fieldp = &arg->field;
659
660 do {
Masami Hiramatsue334016f12010-04-12 13:17:49 -0400661 *fieldp = zalloc(sizeof(struct perf_probe_arg_field));
662 if (*fieldp == NULL)
663 return -ENOMEM;
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400664 if (*tmp == '[') { /* Array */
665 str = tmp;
666 (*fieldp)->index = strtol(str + 1, &tmp, 0);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400667 (*fieldp)->ref = true;
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400668 if (*tmp != ']' || tmp == str + 1) {
669 semantic_error("Array index must be a"
670 " number.\n");
671 return -EINVAL;
672 }
673 tmp++;
674 if (*tmp == '\0')
675 tmp = NULL;
676 } else { /* Structure */
677 if (*tmp == '.') {
678 str = tmp + 1;
679 (*fieldp)->ref = false;
680 } else if (tmp[1] == '>') {
681 str = tmp + 2;
682 (*fieldp)->ref = true;
683 } else {
684 semantic_error("Argument parse error: %s\n",
685 str);
686 return -EINVAL;
687 }
688 tmp = strpbrk(str, "-.[");
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400689 }
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400690 if (tmp) {
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400691 (*fieldp)->name = strndup(str, tmp - str);
692 if ((*fieldp)->name == NULL)
693 return -ENOMEM;
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400694 if (*str != '[')
695 goodname = (*fieldp)->name;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400696 pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
697 fieldp = &(*fieldp)->next;
698 }
699 } while (tmp);
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400700 (*fieldp)->name = strdup(str);
701 if ((*fieldp)->name == NULL)
702 return -ENOMEM;
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400703 if (*str != '[')
704 goodname = (*fieldp)->name;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400705 pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
Masami Hiramatsudf0faf42010-04-12 13:17:00 -0400706
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400707 /* If no name is specified, set the last field name (not array index)*/
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400708 if (!arg->name) {
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400709 arg->name = strdup(goodname);
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400710 if (arg->name == NULL)
711 return -ENOMEM;
712 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400713 return 0;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400714}
715
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400716/* Parse perf-probe event command */
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400717int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500718{
Masami Hiramatsue1c01d62009-11-30 19:20:05 -0500719 char **argv;
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400720 int argc, i, ret = 0;
Masami Hiramatsufac13fd2009-12-15 10:31:14 -0500721
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400722 argv = argv_split(cmd, &argc);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400723 if (!argv) {
724 pr_debug("Failed to split arguments.\n");
725 return -ENOMEM;
726 }
727 if (argc - 1 > MAX_PROBE_ARGS) {
728 semantic_error("Too many probe arguments (%d).\n", argc - 1);
729 ret = -ERANGE;
730 goto out;
731 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500732 /* Parse probe point */
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400733 ret = parse_perf_probe_point(argv[0], pev);
734 if (ret < 0)
735 goto out;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500736
Masami Hiramatsue1c01d62009-11-30 19:20:05 -0500737 /* Copy arguments and ensure return probe has no C argument */
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400738 pev->nargs = argc - 1;
Masami Hiramatsue334016f12010-04-12 13:17:49 -0400739 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
740 if (pev->args == NULL) {
741 ret = -ENOMEM;
742 goto out;
743 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400744 for (i = 0; i < pev->nargs && ret >= 0; i++) {
745 ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
746 if (ret >= 0 &&
747 is_c_varname(pev->args[i].var) && pev->point.retprobe) {
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400748 semantic_error("You can't specify local variable for"
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400749 " kretprobe.\n");
750 ret = -EINVAL;
751 }
Masami Hiramatsue1c01d62009-11-30 19:20:05 -0500752 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400753out:
Masami Hiramatsue1c01d62009-11-30 19:20:05 -0500754 argv_free(argv);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400755
756 return ret;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500757}
758
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400759/* Return true if this perf_probe_event requires debuginfo */
760bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500761{
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400762 int i;
763
764 if (pev->point.file || pev->point.line || pev->point.lazy_line)
765 return true;
766
767 for (i = 0; i < pev->nargs; i++)
Masami Hiramatsu48481932010-04-12 13:16:53 -0400768 if (is_c_varname(pev->args[i].var))
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400769 return true;
770
771 return false;
772}
773
774/* Parse kprobe_events event into struct probe_point */
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400775int parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev)
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400776{
777 struct kprobe_trace_point *tp = &tev->point;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500778 char pr;
779 char *p;
780 int ret, i, argc;
781 char **argv;
782
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400783 pr_debug("Parsing kprobe_events: %s\n", cmd);
784 argv = argv_split(cmd, &argc);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400785 if (!argv) {
786 pr_debug("Failed to split arguments.\n");
787 return -ENOMEM;
788 }
789 if (argc < 2) {
790 semantic_error("Too few probe arguments.\n");
791 ret = -ERANGE;
792 goto out;
793 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500794
795 /* Scan event and group name. */
Liming Wang93aaa452009-12-02 16:42:54 +0800796 ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400797 &pr, (float *)(void *)&tev->group,
798 (float *)(void *)&tev->event);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400799 if (ret != 3) {
800 semantic_error("Failed to parse event name: %s\n", argv[0]);
801 ret = -EINVAL;
802 goto out;
803 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400804 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500805
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400806 tp->retprobe = (pr == 'r');
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500807
808 /* Scan function name and offset */
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400809 ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol,
810 &tp->offset);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500811 if (ret == 1)
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400812 tp->offset = 0;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500813
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400814 tev->nargs = argc - 2;
Masami Hiramatsue334016f12010-04-12 13:17:49 -0400815 tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
816 if (tev->args == NULL) {
817 ret = -ENOMEM;
818 goto out;
819 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400820 for (i = 0; i < tev->nargs; i++) {
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500821 p = strchr(argv[i + 2], '=');
822 if (p) /* We don't need which register is assigned. */
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400823 *p++ = '\0';
824 else
825 p = argv[i + 2];
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400826 tev->args[i].name = strdup(argv[i + 2]);
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400827 /* TODO: parse regs and offset */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -0400828 tev->args[i].value = strdup(p);
829 if (tev->args[i].name == NULL || tev->args[i].value == NULL) {
830 ret = -ENOMEM;
831 goto out;
832 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500833 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400834 ret = 0;
835out:
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500836 argv_free(argv);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400837 return ret;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500838}
839
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400840/* Compose only probe arg */
841int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
842{
843 struct perf_probe_arg_field *field = pa->field;
844 int ret;
845 char *tmp = buf;
846
Masami Hiramatsu48481932010-04-12 13:16:53 -0400847 if (pa->name && pa->var)
848 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
849 else
850 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400851 if (ret <= 0)
852 goto error;
853 tmp += ret;
854 len -= ret;
855
856 while (field) {
Masami Hiramatsub2a3c122010-05-19 15:57:42 -0400857 if (field->name[0] == '[')
858 ret = e_snprintf(tmp, len, "%s", field->name);
859 else
860 ret = e_snprintf(tmp, len, "%s%s",
861 field->ref ? "->" : ".", field->name);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400862 if (ret <= 0)
863 goto error;
864 tmp += ret;
865 len -= ret;
866 field = field->next;
867 }
Masami Hiramatsu11a1ca32010-04-12 13:17:22 -0400868
869 if (pa->type) {
870 ret = e_snprintf(tmp, len, ":%s", pa->type);
871 if (ret <= 0)
872 goto error;
873 tmp += ret;
874 len -= ret;
875 }
876
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400877 return tmp - buf;
878error:
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400879 pr_debug("Failed to synthesize perf probe argument: %s",
880 strerror(-ret));
881 return ret;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -0400882}
883
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400884/* Compose only probe point (not argument) */
885static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500886{
Masami Hiramatsufb1587d2010-03-16 18:06:19 -0400887 char *buf, *tmp;
888 char offs[32] = "", line[32] = "", file[32] = "";
889 int ret, len;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500890
Masami Hiramatsue334016f12010-04-12 13:17:49 -0400891 buf = zalloc(MAX_CMDLEN);
892 if (buf == NULL) {
893 ret = -ENOMEM;
894 goto error;
895 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500896 if (pp->offset) {
Masami Hiramatsufb1587d2010-03-16 18:06:19 -0400897 ret = e_snprintf(offs, 32, "+%lu", pp->offset);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500898 if (ret <= 0)
899 goto error;
900 }
901 if (pp->line) {
Masami Hiramatsufb1587d2010-03-16 18:06:19 -0400902 ret = e_snprintf(line, 32, ":%d", pp->line);
903 if (ret <= 0)
904 goto error;
905 }
906 if (pp->file) {
Masami Hiramatsudd259c52010-04-14 18:39:35 -0400907 len = strlen(pp->file) - 31;
Masami Hiramatsufb1587d2010-03-16 18:06:19 -0400908 if (len < 0)
909 len = 0;
910 tmp = strchr(pp->file + len, '/');
911 if (!tmp)
Masami Hiramatsudd259c52010-04-14 18:39:35 -0400912 tmp = pp->file + len;
Masami Hiramatsufb1587d2010-03-16 18:06:19 -0400913 ret = e_snprintf(file, 32, "@%s", tmp + 1);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500914 if (ret <= 0)
915 goto error;
916 }
917
918 if (pp->function)
Masami Hiramatsufb1587d2010-03-16 18:06:19 -0400919 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
920 offs, pp->retprobe ? "%return" : "", line,
921 file);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500922 else
Masami Hiramatsufb1587d2010-03-16 18:06:19 -0400923 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500924 if (ret <= 0)
925 goto error;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500926
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400927 return buf;
928error:
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400929 pr_debug("Failed to synthesize perf probe point: %s",
930 strerror(-ret));
Masami Hiramatsue334016f12010-04-12 13:17:49 -0400931 if (buf)
932 free(buf);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400933 return NULL;
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400934}
935
936#if 0
937char *synthesize_perf_probe_command(struct perf_probe_event *pev)
938{
939 char *buf;
940 int i, len, ret;
941
942 buf = synthesize_perf_probe_point(&pev->point);
943 if (!buf)
944 return NULL;
945
946 len = strlen(buf);
947 for (i = 0; i < pev->nargs; i++) {
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500948 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400949 pev->args[i].name);
950 if (ret <= 0) {
951 free(buf);
952 return NULL;
953 }
954 len += ret;
955 }
956
957 return buf;
958}
959#endif
960
961static int __synthesize_kprobe_trace_arg_ref(struct kprobe_trace_arg_ref *ref,
962 char **buf, size_t *buflen,
963 int depth)
964{
965 int ret;
966 if (ref->next) {
967 depth = __synthesize_kprobe_trace_arg_ref(ref->next, buf,
968 buflen, depth + 1);
969 if (depth < 0)
970 goto out;
971 }
972
973 ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
974 if (ret < 0)
975 depth = ret;
976 else {
977 *buf += ret;
978 *buflen -= ret;
979 }
980out:
981 return depth;
982
983}
984
985static int synthesize_kprobe_trace_arg(struct kprobe_trace_arg *arg,
986 char *buf, size_t buflen)
987{
Masami Hiramatsub7dcb852010-05-19 15:57:49 -0400988 struct kprobe_trace_arg_ref *ref = arg->ref;
Masami Hiramatsu4235b042010-03-16 18:06:12 -0400989 int ret, depth = 0;
990 char *tmp = buf;
991
992 /* Argument name or separator */
993 if (arg->name)
994 ret = e_snprintf(buf, buflen, " %s=", arg->name);
995 else
996 ret = e_snprintf(buf, buflen, " ");
997 if (ret < 0)
998 return ret;
999 buf += ret;
1000 buflen -= ret;
1001
Masami Hiramatsub7dcb852010-05-19 15:57:49 -04001002 /* Special case: @XXX */
1003 if (arg->value[0] == '@' && arg->ref)
1004 ref = ref->next;
1005
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001006 /* Dereferencing arguments */
Masami Hiramatsub7dcb852010-05-19 15:57:49 -04001007 if (ref) {
1008 depth = __synthesize_kprobe_trace_arg_ref(ref, &buf,
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001009 &buflen, 1);
1010 if (depth < 0)
1011 return depth;
1012 }
1013
1014 /* Print argument value */
Masami Hiramatsub7dcb852010-05-19 15:57:49 -04001015 if (arg->value[0] == '@' && arg->ref)
1016 ret = e_snprintf(buf, buflen, "%s%+ld", arg->value,
1017 arg->ref->offset);
1018 else
1019 ret = e_snprintf(buf, buflen, "%s", arg->value);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001020 if (ret < 0)
1021 return ret;
1022 buf += ret;
1023 buflen -= ret;
1024
1025 /* Closing */
1026 while (depth--) {
1027 ret = e_snprintf(buf, buflen, ")");
1028 if (ret < 0)
1029 return ret;
1030 buf += ret;
1031 buflen -= ret;
1032 }
Masami Hiramatsu49849122010-04-12 13:17:15 -04001033 /* Print argument type */
1034 if (arg->type) {
1035 ret = e_snprintf(buf, buflen, ":%s", arg->type);
1036 if (ret <= 0)
1037 return ret;
1038 buf += ret;
1039 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001040
1041 return buf - tmp;
1042}
1043
1044char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev)
1045{
1046 struct kprobe_trace_point *tp = &tev->point;
1047 char *buf;
1048 int i, len, ret;
1049
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001050 buf = zalloc(MAX_CMDLEN);
1051 if (buf == NULL)
1052 return NULL;
1053
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001054 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu",
1055 tp->retprobe ? 'r' : 'p',
1056 tev->group, tev->event,
1057 tp->symbol, tp->offset);
1058 if (len <= 0)
1059 goto error;
1060
1061 for (i = 0; i < tev->nargs; i++) {
1062 ret = synthesize_kprobe_trace_arg(&tev->args[i], buf + len,
1063 MAX_CMDLEN - len);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001064 if (ret <= 0)
1065 goto error;
1066 len += ret;
1067 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001068
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001069 return buf;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001070error:
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001071 free(buf);
1072 return NULL;
1073}
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001074
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001075int convert_to_perf_probe_event(struct kprobe_trace_event *tev,
1076 struct perf_probe_event *pev)
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001077{
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001078 char buf[64] = "";
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001079 int i, ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001080
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -03001081 /* Convert event/group name */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001082 pev->event = strdup(tev->event);
1083 pev->group = strdup(tev->group);
1084 if (pev->event == NULL || pev->group == NULL)
1085 return -ENOMEM;
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001086
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -03001087 /* Convert trace_point to probe_point */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001088 ret = convert_to_perf_probe_point(&tev->point, &pev->point);
1089 if (ret < 0)
1090 return ret;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -03001091
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001092 /* Convert trace_arg to probe_arg */
1093 pev->nargs = tev->nargs;
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001094 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
1095 if (pev->args == NULL)
1096 return -ENOMEM;
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001097 for (i = 0; i < tev->nargs && ret >= 0; i++) {
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001098 if (tev->args[i].name)
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001099 pev->args[i].name = strdup(tev->args[i].name);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001100 else {
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001101 ret = synthesize_kprobe_trace_arg(&tev->args[i],
1102 buf, 64);
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001103 pev->args[i].name = strdup(buf);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001104 }
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001105 if (pev->args[i].name == NULL && ret >= 0)
1106 ret = -ENOMEM;
1107 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001108
1109 if (ret < 0)
1110 clear_perf_probe_event(pev);
1111
1112 return ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001113}
1114
1115void clear_perf_probe_event(struct perf_probe_event *pev)
1116{
1117 struct perf_probe_point *pp = &pev->point;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001118 struct perf_probe_arg_field *field, *next;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001119 int i;
1120
1121 if (pev->event)
1122 free(pev->event);
1123 if (pev->group)
1124 free(pev->group);
1125 if (pp->file)
1126 free(pp->file);
1127 if (pp->function)
1128 free(pp->function);
1129 if (pp->lazy_line)
1130 free(pp->lazy_line);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001131 for (i = 0; i < pev->nargs; i++) {
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001132 if (pev->args[i].name)
1133 free(pev->args[i].name);
Masami Hiramatsu48481932010-04-12 13:16:53 -04001134 if (pev->args[i].var)
1135 free(pev->args[i].var);
Masami Hiramatsu11a1ca32010-04-12 13:17:22 -04001136 if (pev->args[i].type)
1137 free(pev->args[i].type);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001138 field = pev->args[i].field;
1139 while (field) {
1140 next = field->next;
1141 if (field->name)
1142 free(field->name);
1143 free(field);
1144 field = next;
1145 }
1146 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001147 if (pev->args)
1148 free(pev->args);
1149 memset(pev, 0, sizeof(*pev));
1150}
1151
1152void clear_kprobe_trace_event(struct kprobe_trace_event *tev)
1153{
1154 struct kprobe_trace_arg_ref *ref, *next;
1155 int i;
1156
1157 if (tev->event)
1158 free(tev->event);
1159 if (tev->group)
1160 free(tev->group);
1161 if (tev->point.symbol)
1162 free(tev->point.symbol);
1163 for (i = 0; i < tev->nargs; i++) {
1164 if (tev->args[i].name)
1165 free(tev->args[i].name);
1166 if (tev->args[i].value)
1167 free(tev->args[i].value);
Masami Hiramatsu49849122010-04-12 13:17:15 -04001168 if (tev->args[i].type)
1169 free(tev->args[i].type);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001170 ref = tev->args[i].ref;
1171 while (ref) {
1172 next = ref->next;
1173 free(ref);
1174 ref = next;
1175 }
1176 }
1177 if (tev->args)
1178 free(tev->args);
1179 memset(tev, 0, sizeof(*tev));
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001180}
1181
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -04001182static int open_kprobe_events(bool readwrite)
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001183{
1184 char buf[PATH_MAX];
Masami Hiramatsu7ca59892010-04-14 18:39:28 -04001185 const char *__debugfs;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001186 int ret;
1187
Masami Hiramatsu7ca59892010-04-14 18:39:28 -04001188 __debugfs = debugfs_find_mountpoint();
1189 if (__debugfs == NULL) {
1190 pr_warning("Debugfs is not mounted.\n");
1191 return -ENOENT;
1192 }
1193
1194 ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001195 if (ret >= 0) {
Masami Hiramatsu7ca59892010-04-14 18:39:28 -04001196 pr_debug("Opening %s write=%d\n", buf, readwrite);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001197 if (readwrite && !probe_event_dry_run)
1198 ret = open(buf, O_RDWR, O_APPEND);
1199 else
1200 ret = open(buf, O_RDONLY, 0);
1201 }
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -04001202
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001203 if (ret < 0) {
1204 if (errno == ENOENT)
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001205 pr_warning("kprobe_events file does not exist - please"
1206 " rebuild kernel with CONFIG_KPROBE_EVENT.\n");
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001207 else
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001208 pr_warning("Failed to open kprobe_events file: %s\n",
1209 strerror(errno));
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001210 }
1211 return ret;
1212}
1213
1214/* Get raw string list of current kprobe_events */
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001215static struct strlist *get_kprobe_trace_command_rawlist(int fd)
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001216{
1217 int ret, idx;
1218 FILE *fp;
1219 char buf[MAX_CMDLEN];
1220 char *p;
1221 struct strlist *sl;
1222
1223 sl = strlist__new(true, NULL);
1224
1225 fp = fdopen(dup(fd), "r");
1226 while (!feof(fp)) {
1227 p = fgets(buf, MAX_CMDLEN, fp);
1228 if (!p)
1229 break;
1230
1231 idx = strlen(p) - 1;
1232 if (p[idx] == '\n')
1233 p[idx] = '\0';
1234 ret = strlist__add(sl, buf);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001235 if (ret < 0) {
1236 pr_debug("strlist__add failed: %s\n", strerror(-ret));
1237 strlist__delete(sl);
1238 return NULL;
1239 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001240 }
1241 fclose(fp);
1242
1243 return sl;
1244}
1245
Masami Hiramatsu278498d2009-12-08 17:02:40 -05001246/* Show an event */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001247static int show_perf_probe_event(struct perf_probe_event *pev)
Masami Hiramatsu278498d2009-12-08 17:02:40 -05001248{
Masami Hiramatsu7e990a52009-12-15 10:31:21 -05001249 int i, ret;
Masami Hiramatsu278498d2009-12-08 17:02:40 -05001250 char buf[128];
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001251 char *place;
Masami Hiramatsu278498d2009-12-08 17:02:40 -05001252
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001253 /* Synthesize only event probe point */
1254 place = synthesize_perf_probe_point(&pev->point);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001255 if (!place)
1256 return -EINVAL;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001257
1258 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event);
Masami Hiramatsu7e990a52009-12-15 10:31:21 -05001259 if (ret < 0)
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001260 return ret;
1261
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001262 printf(" %-20s (on %s", buf, place);
Masami Hiramatsu278498d2009-12-08 17:02:40 -05001263
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001264 if (pev->nargs > 0) {
Masami Hiramatsu278498d2009-12-08 17:02:40 -05001265 printf(" with");
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001266 for (i = 0; i < pev->nargs; i++) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001267 ret = synthesize_perf_probe_arg(&pev->args[i],
1268 buf, 128);
1269 if (ret < 0)
1270 break;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001271 printf(" %s", buf);
1272 }
Masami Hiramatsu278498d2009-12-08 17:02:40 -05001273 }
1274 printf(")\n");
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001275 free(place);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001276 return ret;
Masami Hiramatsu278498d2009-12-08 17:02:40 -05001277}
1278
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001279/* List up current perf-probe events */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001280int show_perf_probe_events(void)
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001281{
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001282 int fd, ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001283 struct kprobe_trace_event tev;
1284 struct perf_probe_event pev;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001285 struct strlist *rawlist;
1286 struct str_node *ent;
1287
Masami Hiramatsu72041332010-01-05 17:47:10 -05001288 setup_pager();
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001289 ret = init_vmlinux();
1290 if (ret < 0)
1291 return ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001292
1293 memset(&tev, 0, sizeof(tev));
1294 memset(&pev, 0, sizeof(pev));
Masami Hiramatsu72041332010-01-05 17:47:10 -05001295
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -04001296 fd = open_kprobe_events(false);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001297 if (fd < 0)
1298 return fd;
1299
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001300 rawlist = get_kprobe_trace_command_rawlist(fd);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001301 close(fd);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001302 if (!rawlist)
1303 return -ENOENT;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001304
Masami Hiramatsuadf365f2009-12-15 10:32:03 -05001305 strlist__for_each(ent, rawlist) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001306 ret = parse_kprobe_trace_command(ent->s, &tev);
1307 if (ret >= 0) {
1308 ret = convert_to_perf_probe_event(&tev, &pev);
1309 if (ret >= 0)
1310 ret = show_perf_probe_event(&pev);
1311 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001312 clear_perf_probe_event(&pev);
1313 clear_kprobe_trace_event(&tev);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001314 if (ret < 0)
1315 break;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001316 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001317 strlist__delete(rawlist);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001318
1319 return ret;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001320}
1321
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001322/* Get current perf-probe event names */
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001323static struct strlist *get_kprobe_trace_event_names(int fd, bool include_group)
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001324{
Masami Hiramatsufa282442009-12-08 17:03:23 -05001325 char buf[128];
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001326 struct strlist *sl, *rawlist;
1327 struct str_node *ent;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001328 struct kprobe_trace_event tev;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001329 int ret = 0;
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001330
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001331 memset(&tev, 0, sizeof(tev));
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001332
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001333 rawlist = get_kprobe_trace_command_rawlist(fd);
Masami Hiramatsue1d20172009-12-07 12:00:46 -05001334 sl = strlist__new(true, NULL);
Masami Hiramatsuadf365f2009-12-15 10:32:03 -05001335 strlist__for_each(ent, rawlist) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001336 ret = parse_kprobe_trace_command(ent->s, &tev);
1337 if (ret < 0)
1338 break;
Masami Hiramatsufa282442009-12-08 17:03:23 -05001339 if (include_group) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001340 ret = e_snprintf(buf, 128, "%s:%s", tev.group,
1341 tev.event);
1342 if (ret >= 0)
1343 ret = strlist__add(sl, buf);
Masami Hiramatsufa282442009-12-08 17:03:23 -05001344 } else
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001345 ret = strlist__add(sl, tev.event);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001346 clear_kprobe_trace_event(&tev);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001347 if (ret < 0)
1348 break;
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001349 }
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001350 strlist__delete(rawlist);
1351
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001352 if (ret < 0) {
1353 strlist__delete(sl);
1354 return NULL;
1355 }
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001356 return sl;
1357}
1358
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001359static int write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001360{
Frederic Weisbecker6eca8cc2010-04-21 02:01:05 +02001361 int ret = 0;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001362 char *buf = synthesize_kprobe_trace_command(tev);
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001363
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001364 if (!buf) {
1365 pr_debug("Failed to synthesize kprobe trace event.\n");
1366 return -EINVAL;
1367 }
1368
Masami Hiramatsufa282442009-12-08 17:03:23 -05001369 pr_debug("Writing event: %s\n", buf);
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -04001370 if (!probe_event_dry_run) {
1371 ret = write(fd, buf, strlen(buf));
1372 if (ret <= 0)
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001373 pr_warning("Failed to write event: %s\n",
1374 strerror(errno));
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -04001375 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001376 free(buf);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001377 return ret;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001378}
1379
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001380static int get_new_event_name(char *buf, size_t len, const char *base,
1381 struct strlist *namelist, bool allow_suffix)
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001382{
1383 int i, ret;
Masami Hiramatsu17f88fc2009-12-08 17:03:02 -05001384
1385 /* Try no suffix */
1386 ret = e_snprintf(buf, len, "%s", base);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001387 if (ret < 0) {
1388 pr_debug("snprintf() failed: %s\n", strerror(-ret));
1389 return ret;
1390 }
Masami Hiramatsu17f88fc2009-12-08 17:03:02 -05001391 if (!strlist__has_entry(namelist, buf))
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001392 return 0;
Masami Hiramatsu17f88fc2009-12-08 17:03:02 -05001393
Masami Hiramatsud761b082009-12-15 10:32:25 -05001394 if (!allow_suffix) {
1395 pr_warning("Error: event \"%s\" already exists. "
1396 "(Use -f to force duplicates.)\n", base);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001397 return -EEXIST;
Masami Hiramatsud761b082009-12-15 10:32:25 -05001398 }
1399
Masami Hiramatsu17f88fc2009-12-08 17:03:02 -05001400 /* Try to add suffix */
1401 for (i = 1; i < MAX_EVENT_INDEX; i++) {
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001402 ret = e_snprintf(buf, len, "%s_%d", base, i);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001403 if (ret < 0) {
1404 pr_debug("snprintf() failed: %s\n", strerror(-ret));
1405 return ret;
1406 }
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001407 if (!strlist__has_entry(namelist, buf))
1408 break;
1409 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001410 if (i == MAX_EVENT_INDEX) {
1411 pr_warning("Too many events are on the same function.\n");
1412 ret = -ERANGE;
1413 }
1414
1415 return ret;
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001416}
1417
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001418static int __add_kprobe_trace_events(struct perf_probe_event *pev,
1419 struct kprobe_trace_event *tevs,
1420 int ntevs, bool allow_suffix)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001421{
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001422 int i, fd, ret;
Ingo Molnar55632772010-03-18 16:51:16 +01001423 struct kprobe_trace_event *tev = NULL;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001424 char buf[64];
1425 const char *event, *group;
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001426 struct strlist *namelist;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001427
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -04001428 fd = open_kprobe_events(true);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001429 if (fd < 0)
1430 return fd;
Masami Hiramatsub498ce12009-11-30 19:20:25 -05001431 /* Get current event names */
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001432 namelist = get_kprobe_trace_event_names(fd, false);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001433 if (!namelist) {
1434 pr_debug("Failed to get current event list.\n");
1435 return -EIO;
1436 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001437
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001438 ret = 0;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001439 printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":");
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001440 for (i = 0; i < ntevs; i++) {
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001441 tev = &tevs[i];
1442 if (pev->event)
1443 event = pev->event;
1444 else
1445 if (pev->point.function)
1446 event = pev->point.function;
1447 else
1448 event = tev->point.symbol;
1449 if (pev->group)
1450 group = pev->group;
1451 else
1452 group = PERFPROBE_GROUP;
1453
1454 /* Get an unused new event name */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001455 ret = get_new_event_name(buf, 64, event,
1456 namelist, allow_suffix);
1457 if (ret < 0)
1458 break;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001459 event = buf;
1460
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001461 tev->event = strdup(event);
1462 tev->group = strdup(group);
1463 if (tev->event == NULL || tev->group == NULL) {
1464 ret = -ENOMEM;
1465 break;
1466 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001467 ret = write_kprobe_trace_event(fd, tev);
1468 if (ret < 0)
1469 break;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001470 /* Add added event name to namelist */
1471 strlist__add(namelist, event);
1472
1473 /* Trick here - save current event/group */
1474 event = pev->event;
1475 group = pev->group;
1476 pev->event = tev->event;
1477 pev->group = tev->group;
1478 show_perf_probe_event(pev);
1479 /* Trick here - restore current event/group */
1480 pev->event = (char *)event;
1481 pev->group = (char *)group;
1482
1483 /*
1484 * Probes after the first probe which comes from same
1485 * user input are always allowed to add suffix, because
1486 * there might be several addresses corresponding to
1487 * one code line.
1488 */
1489 allow_suffix = true;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001490 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001491
1492 if (ret >= 0) {
1493 /* Show how to use the event. */
1494 printf("\nYou can now use it on all perf tools, such as:\n\n");
1495 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
1496 tev->event);
1497 }
Masami Hiramatsua9b495b2009-12-08 17:02:47 -05001498
Masami Hiramatsue1d20172009-12-07 12:00:46 -05001499 strlist__delete(namelist);
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001500 close(fd);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001501 return ret;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001502}
Masami Hiramatsufa282442009-12-08 17:03:23 -05001503
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001504static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
Masami Hiramatsuef4a3562010-04-21 15:56:40 -04001505 struct kprobe_trace_event **tevs,
1506 int max_tevs)
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -04001507{
1508 struct symbol *sym;
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001509 int ret = 0, i;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001510 struct kprobe_trace_event *tev;
1511
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -03001512 /* Convert perf_probe_event with debuginfo */
Masami Hiramatsuef4a3562010-04-21 15:56:40 -04001513 ret = try_to_find_kprobe_trace_events(pev, tevs, max_tevs);
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001514 if (ret != 0)
1515 return ret;
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -04001516
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001517 /* Allocate trace event buffer */
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001518 tev = *tevs = zalloc(sizeof(struct kprobe_trace_event));
1519 if (tev == NULL)
1520 return -ENOMEM;
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -04001521
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001522 /* Copy parameters */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001523 tev->point.symbol = strdup(pev->point.function);
1524 if (tev->point.symbol == NULL) {
1525 ret = -ENOMEM;
1526 goto error;
1527 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001528 tev->point.offset = pev->point.offset;
1529 tev->nargs = pev->nargs;
1530 if (tev->nargs) {
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001531 tev->args = zalloc(sizeof(struct kprobe_trace_arg)
1532 * tev->nargs);
1533 if (tev->args == NULL) {
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001534 ret = -ENOMEM;
1535 goto error;
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001536 }
Masami Hiramatsu48481932010-04-12 13:16:53 -04001537 for (i = 0; i < tev->nargs; i++) {
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001538 if (pev->args[i].name) {
1539 tev->args[i].name = strdup(pev->args[i].name);
1540 if (tev->args[i].name == NULL) {
1541 ret = -ENOMEM;
1542 goto error;
1543 }
1544 }
1545 tev->args[i].value = strdup(pev->args[i].var);
1546 if (tev->args[i].value == NULL) {
1547 ret = -ENOMEM;
1548 goto error;
1549 }
1550 if (pev->args[i].type) {
1551 tev->args[i].type = strdup(pev->args[i].type);
1552 if (tev->args[i].type == NULL) {
1553 ret = -ENOMEM;
1554 goto error;
1555 }
1556 }
Masami Hiramatsu48481932010-04-12 13:16:53 -04001557 }
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -04001558 }
1559
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001560 /* Currently just checking function name from symbol map */
Arnaldo Carvalho de Melod28c6222010-04-27 21:20:43 -03001561 sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION],
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001562 tev->point.symbol, NULL);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001563 if (!sym) {
1564 pr_warning("Kernel symbol \'%s\' not found.\n",
1565 tev->point.symbol);
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001566 ret = -ENOENT;
1567 goto error;
1568 }
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001569
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001570 return 1;
1571error:
1572 clear_kprobe_trace_event(tev);
1573 free(tev);
1574 *tevs = NULL;
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001575 return ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001576}
1577
1578struct __event_package {
1579 struct perf_probe_event *pev;
1580 struct kprobe_trace_event *tevs;
1581 int ntevs;
1582};
1583
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001584int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
Masami Hiramatsuef4a3562010-04-21 15:56:40 -04001585 bool force_add, int max_tevs)
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001586{
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001587 int i, j, ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001588 struct __event_package *pkgs;
1589
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001590 pkgs = zalloc(sizeof(struct __event_package) * npevs);
1591 if (pkgs == NULL)
1592 return -ENOMEM;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001593
1594 /* Init vmlinux path */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001595 ret = init_vmlinux();
1596 if (ret < 0)
1597 return ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001598
1599 /* Loop 1: convert all events */
1600 for (i = 0; i < npevs; i++) {
1601 pkgs[i].pev = &pevs[i];
1602 /* Convert with or without debuginfo */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001603 ret = convert_to_kprobe_trace_events(pkgs[i].pev,
Masami Hiramatsuef4a3562010-04-21 15:56:40 -04001604 &pkgs[i].tevs, max_tevs);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001605 if (ret < 0)
1606 goto end;
1607 pkgs[i].ntevs = ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001608 }
1609
1610 /* Loop 2: add all events */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001611 for (i = 0; i < npevs && ret >= 0; i++)
1612 ret = __add_kprobe_trace_events(pkgs[i].pev, pkgs[i].tevs,
1613 pkgs[i].ntevs, force_add);
1614end:
1615 /* Loop 3: cleanup trace events */
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001616 for (i = 0; i < npevs; i++)
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001617 for (j = 0; j < pkgs[i].ntevs; j++)
1618 clear_kprobe_trace_event(&pkgs[i].tevs[j]);
1619
1620 return ret;
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -04001621}
1622
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001623static int __del_trace_kprobe_event(int fd, struct str_node *ent)
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001624{
1625 char *p;
1626 char buf[128];
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001627 int ret;
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001628
1629 /* Convert from perf-probe event to trace-kprobe event */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001630 ret = e_snprintf(buf, 128, "-:%s", ent->s);
1631 if (ret < 0)
1632 goto error;
1633
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001634 p = strchr(buf + 2, ':');
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001635 if (!p) {
1636 pr_debug("Internal error: %s should have ':' but not.\n",
1637 ent->s);
1638 ret = -ENOTSUP;
1639 goto error;
1640 }
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001641 *p = '/';
1642
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001643 pr_debug("Writing event: %s\n", buf);
1644 ret = write(fd, buf, strlen(buf));
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001645 if (ret < 0)
1646 goto error;
1647
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001648 printf("Remove event: %s\n", ent->s);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001649 return 0;
1650error:
1651 pr_warning("Failed to delete event: %s\n", strerror(-ret));
1652 return ret;
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001653}
1654
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001655static int del_trace_kprobe_event(int fd, const char *group,
1656 const char *event, struct strlist *namelist)
Masami Hiramatsufa282442009-12-08 17:03:23 -05001657{
1658 char buf[128];
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001659 struct str_node *ent, *n;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001660 int found = 0, ret = 0;
Masami Hiramatsufa282442009-12-08 17:03:23 -05001661
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001662 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1663 if (ret < 0) {
1664 pr_err("Failed to copy event.");
1665 return ret;
1666 }
Masami Hiramatsufa282442009-12-08 17:03:23 -05001667
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001668 if (strpbrk(buf, "*?")) { /* Glob-exp */
1669 strlist__for_each_safe(ent, n, namelist)
1670 if (strglobmatch(ent->s, buf)) {
1671 found++;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001672 ret = __del_trace_kprobe_event(fd, ent);
1673 if (ret < 0)
1674 break;
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001675 strlist__remove(namelist, ent);
1676 }
1677 } else {
1678 ent = strlist__find(namelist, buf);
1679 if (ent) {
1680 found++;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001681 ret = __del_trace_kprobe_event(fd, ent);
1682 if (ret >= 0)
1683 strlist__remove(namelist, ent);
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001684 }
1685 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001686 if (found == 0 && ret >= 0)
1687 pr_info("Info: Event \"%s\" does not exist.\n", buf);
1688
1689 return ret;
Masami Hiramatsufa282442009-12-08 17:03:23 -05001690}
1691
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001692int del_perf_probe_events(struct strlist *dellist)
Masami Hiramatsufa282442009-12-08 17:03:23 -05001693{
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001694 int fd, ret = 0;
Masami Hiramatsufa282442009-12-08 17:03:23 -05001695 const char *group, *event;
1696 char *p, *str;
1697 struct str_node *ent;
1698 struct strlist *namelist;
1699
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -04001700 fd = open_kprobe_events(true);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001701 if (fd < 0)
1702 return fd;
1703
Masami Hiramatsufa282442009-12-08 17:03:23 -05001704 /* Get current event names */
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001705 namelist = get_kprobe_trace_event_names(fd, true);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001706 if (namelist == NULL)
1707 return -EINVAL;
Masami Hiramatsufa282442009-12-08 17:03:23 -05001708
Masami Hiramatsuadf365f2009-12-15 10:32:03 -05001709 strlist__for_each(ent, dellist) {
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001710 str = strdup(ent->s);
1711 if (str == NULL) {
1712 ret = -ENOMEM;
1713 break;
1714 }
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001715 pr_debug("Parsing: %s\n", str);
Masami Hiramatsufa282442009-12-08 17:03:23 -05001716 p = strchr(str, ':');
1717 if (p) {
1718 group = str;
1719 *p = '\0';
1720 event = p + 1;
1721 } else {
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001722 group = "*";
Masami Hiramatsufa282442009-12-08 17:03:23 -05001723 event = str;
1724 }
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05001725 pr_debug("Group: %s, Event: %s\n", group, event);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001726 ret = del_trace_kprobe_event(fd, group, event, namelist);
Masami Hiramatsufa282442009-12-08 17:03:23 -05001727 free(str);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001728 if (ret < 0)
1729 break;
Masami Hiramatsufa282442009-12-08 17:03:23 -05001730 }
1731 strlist__delete(namelist);
1732 close(fd);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001733
1734 return ret;
Masami Hiramatsufa282442009-12-08 17:03:23 -05001735}
1736