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