xref: /linux/tools/perf/util/probe-event.c (revision 63bbd5e2d539c9290b229c832f62d42aac23db94)
150656eecSMasami Hiramatsu /*
250656eecSMasami Hiramatsu  * probe-event.c : perf-probe definition to kprobe_events format converter
350656eecSMasami Hiramatsu  *
450656eecSMasami Hiramatsu  * Written by Masami Hiramatsu <mhiramat@redhat.com>
550656eecSMasami Hiramatsu  *
650656eecSMasami Hiramatsu  * This program is free software; you can redistribute it and/or modify
750656eecSMasami Hiramatsu  * it under the terms of the GNU General Public License as published by
850656eecSMasami Hiramatsu  * the Free Software Foundation; either version 2 of the License, or
950656eecSMasami Hiramatsu  * (at your option) any later version.
1050656eecSMasami Hiramatsu  *
1150656eecSMasami Hiramatsu  * This program is distributed in the hope that it will be useful,
1250656eecSMasami Hiramatsu  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1350656eecSMasami Hiramatsu  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1450656eecSMasami Hiramatsu  * GNU General Public License for more details.
1550656eecSMasami Hiramatsu  *
1650656eecSMasami Hiramatsu  * You should have received a copy of the GNU General Public License
1750656eecSMasami Hiramatsu  * along with this program; if not, write to the Free Software
1850656eecSMasami Hiramatsu  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1950656eecSMasami Hiramatsu  *
2050656eecSMasami Hiramatsu  */
2150656eecSMasami Hiramatsu 
2250656eecSMasami Hiramatsu #define _GNU_SOURCE
2350656eecSMasami Hiramatsu #include <sys/utsname.h>
2450656eecSMasami Hiramatsu #include <sys/types.h>
2550656eecSMasami Hiramatsu #include <sys/stat.h>
2650656eecSMasami Hiramatsu #include <fcntl.h>
2750656eecSMasami Hiramatsu #include <errno.h>
2850656eecSMasami Hiramatsu #include <stdio.h>
2950656eecSMasami Hiramatsu #include <unistd.h>
3050656eecSMasami Hiramatsu #include <stdlib.h>
3150656eecSMasami Hiramatsu #include <string.h>
324de189feSMasami Hiramatsu #include <stdarg.h>
334de189feSMasami Hiramatsu #include <limits.h>
3450656eecSMasami Hiramatsu 
3550656eecSMasami Hiramatsu #undef _GNU_SOURCE
3650656eecSMasami Hiramatsu #include "event.h"
37e1c01d61SMasami Hiramatsu #include "string.h"
384de189feSMasami Hiramatsu #include "strlist.h"
3950656eecSMasami Hiramatsu #include "debug.h"
4050656eecSMasami Hiramatsu #include "parse-events.h"  /* For debugfs_path */
4150656eecSMasami Hiramatsu #include "probe-event.h"
4250656eecSMasami Hiramatsu 
4350656eecSMasami Hiramatsu #define MAX_CMDLEN 256
4450656eecSMasami Hiramatsu #define MAX_PROBE_ARGS 128
4550656eecSMasami Hiramatsu #define PERFPROBE_GROUP "probe"
4650656eecSMasami Hiramatsu 
4750656eecSMasami Hiramatsu #define semantic_error(msg ...) die("Semantic error :" msg)
4850656eecSMasami Hiramatsu 
494de189feSMasami Hiramatsu /* If there is no space to write, returns -E2BIG. */
504de189feSMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...)
5184988450SMasami Hiramatsu 	__attribute__((format(printf, 3, 4)));
5284988450SMasami Hiramatsu 
5384988450SMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...)
544de189feSMasami Hiramatsu {
554de189feSMasami Hiramatsu 	int ret;
564de189feSMasami Hiramatsu 	va_list ap;
574de189feSMasami Hiramatsu 	va_start(ap, format);
584de189feSMasami Hiramatsu 	ret = vsnprintf(str, size, format, ap);
594de189feSMasami Hiramatsu 	va_end(ap);
604de189feSMasami Hiramatsu 	if (ret >= (int)size)
614de189feSMasami Hiramatsu 		ret = -E2BIG;
624de189feSMasami Hiramatsu 	return ret;
634de189feSMasami Hiramatsu }
644de189feSMasami Hiramatsu 
65b7702a21SMasami Hiramatsu /* Check the name is good for event/group */
66b7702a21SMasami Hiramatsu static bool check_event_name(const char *name)
67b7702a21SMasami Hiramatsu {
68b7702a21SMasami Hiramatsu 	if (!isalpha(*name) && *name != '_')
69b7702a21SMasami Hiramatsu 		return false;
70b7702a21SMasami Hiramatsu 	while (*++name != '\0') {
71b7702a21SMasami Hiramatsu 		if (!isalpha(*name) && !isdigit(*name) && *name != '_')
72b7702a21SMasami Hiramatsu 			return false;
73b7702a21SMasami Hiramatsu 	}
74b7702a21SMasami Hiramatsu 	return true;
75b7702a21SMasami Hiramatsu }
76b7702a21SMasami Hiramatsu 
7750656eecSMasami Hiramatsu /* Parse probepoint definition. */
7850656eecSMasami Hiramatsu static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
7950656eecSMasami Hiramatsu {
8050656eecSMasami Hiramatsu 	char *ptr, *tmp;
8150656eecSMasami Hiramatsu 	char c, nc = 0;
8250656eecSMasami Hiramatsu 	/*
8350656eecSMasami Hiramatsu 	 * <Syntax>
84af663d75SMasami Hiramatsu 	 * perf probe [EVENT=]SRC:LN
85af663d75SMasami Hiramatsu 	 * perf probe [EVENT=]FUNC[+OFFS|%return][@SRC]
86af663d75SMasami Hiramatsu 	 *
87af663d75SMasami Hiramatsu 	 * TODO:Group name support
8850656eecSMasami Hiramatsu 	 */
8950656eecSMasami Hiramatsu 
90af663d75SMasami Hiramatsu 	ptr = strchr(arg, '=');
91af663d75SMasami Hiramatsu 	if (ptr) {	/* Event name */
92af663d75SMasami Hiramatsu 		*ptr = '\0';
93af663d75SMasami Hiramatsu 		tmp = ptr + 1;
94af663d75SMasami Hiramatsu 		ptr = strchr(arg, ':');
95af663d75SMasami Hiramatsu 		if (ptr)	/* Group name is not supported yet. */
96af663d75SMasami Hiramatsu 			semantic_error("Group name is not supported yet.");
97b7702a21SMasami Hiramatsu 		if (!check_event_name(arg))
98b7702a21SMasami Hiramatsu 			semantic_error("%s is bad for event name -it must "
99b7702a21SMasami Hiramatsu 				       "follow C symbol-naming rule.", arg);
100af663d75SMasami Hiramatsu 		pp->event = strdup(arg);
101af663d75SMasami Hiramatsu 		arg = tmp;
102af663d75SMasami Hiramatsu 	}
103af663d75SMasami Hiramatsu 
10450656eecSMasami Hiramatsu 	ptr = strpbrk(arg, ":+@%");
10550656eecSMasami Hiramatsu 	if (ptr) {
10650656eecSMasami Hiramatsu 		nc = *ptr;
10750656eecSMasami Hiramatsu 		*ptr++ = '\0';
10850656eecSMasami Hiramatsu 	}
10950656eecSMasami Hiramatsu 
11050656eecSMasami Hiramatsu 	/* Check arg is function or file and copy it */
11150656eecSMasami Hiramatsu 	if (strchr(arg, '.'))	/* File */
11250656eecSMasami Hiramatsu 		pp->file = strdup(arg);
11350656eecSMasami Hiramatsu 	else			/* Function */
11450656eecSMasami Hiramatsu 		pp->function = strdup(arg);
11550656eecSMasami Hiramatsu 	DIE_IF(pp->file == NULL && pp->function == NULL);
11650656eecSMasami Hiramatsu 
11750656eecSMasami Hiramatsu 	/* Parse other options */
11850656eecSMasami Hiramatsu 	while (ptr) {
11950656eecSMasami Hiramatsu 		arg = ptr;
12050656eecSMasami Hiramatsu 		c = nc;
12150656eecSMasami Hiramatsu 		ptr = strpbrk(arg, ":+@%");
12250656eecSMasami Hiramatsu 		if (ptr) {
12350656eecSMasami Hiramatsu 			nc = *ptr;
12450656eecSMasami Hiramatsu 			*ptr++ = '\0';
12550656eecSMasami Hiramatsu 		}
12650656eecSMasami Hiramatsu 		switch (c) {
12750656eecSMasami Hiramatsu 		case ':':	/* Line number */
12850656eecSMasami Hiramatsu 			pp->line = strtoul(arg, &tmp, 0);
12950656eecSMasami Hiramatsu 			if (*tmp != '\0')
13050656eecSMasami Hiramatsu 				semantic_error("There is non-digit charactor"
13150656eecSMasami Hiramatsu 						" in line number.");
13250656eecSMasami Hiramatsu 			break;
13350656eecSMasami Hiramatsu 		case '+':	/* Byte offset from a symbol */
13450656eecSMasami Hiramatsu 			pp->offset = strtoul(arg, &tmp, 0);
13550656eecSMasami Hiramatsu 			if (*tmp != '\0')
13650656eecSMasami Hiramatsu 				semantic_error("There is non-digit charactor"
13750656eecSMasami Hiramatsu 						" in offset.");
13850656eecSMasami Hiramatsu 			break;
13950656eecSMasami Hiramatsu 		case '@':	/* File name */
14050656eecSMasami Hiramatsu 			if (pp->file)
14150656eecSMasami Hiramatsu 				semantic_error("SRC@SRC is not allowed.");
14250656eecSMasami Hiramatsu 			pp->file = strdup(arg);
14350656eecSMasami Hiramatsu 			DIE_IF(pp->file == NULL);
14450656eecSMasami Hiramatsu 			if (ptr)
14550656eecSMasami Hiramatsu 				semantic_error("@SRC must be the last "
14650656eecSMasami Hiramatsu 					       "option.");
14750656eecSMasami Hiramatsu 			break;
14850656eecSMasami Hiramatsu 		case '%':	/* Probe places */
14950656eecSMasami Hiramatsu 			if (strcmp(arg, "return") == 0) {
15050656eecSMasami Hiramatsu 				pp->retprobe = 1;
15150656eecSMasami Hiramatsu 			} else	/* Others not supported yet */
15250656eecSMasami Hiramatsu 				semantic_error("%%%s is not supported.", arg);
15350656eecSMasami Hiramatsu 			break;
15450656eecSMasami Hiramatsu 		default:
15550656eecSMasami Hiramatsu 			DIE_IF("Program has a bug.");
15650656eecSMasami Hiramatsu 			break;
15750656eecSMasami Hiramatsu 		}
15850656eecSMasami Hiramatsu 	}
15950656eecSMasami Hiramatsu 
16050656eecSMasami Hiramatsu 	/* Exclusion check */
16150656eecSMasami Hiramatsu 	if (pp->line && pp->offset)
16250656eecSMasami Hiramatsu 		semantic_error("Offset can't be used with line number.");
16350656eecSMasami Hiramatsu 
16450656eecSMasami Hiramatsu 	if (!pp->line && pp->file && !pp->function)
16550656eecSMasami Hiramatsu 		semantic_error("File always requires line number.");
16650656eecSMasami Hiramatsu 
16750656eecSMasami Hiramatsu 	if (pp->offset && !pp->function)
16850656eecSMasami Hiramatsu 		semantic_error("Offset requires an entry function.");
16950656eecSMasami Hiramatsu 
17050656eecSMasami Hiramatsu 	if (pp->retprobe && !pp->function)
17150656eecSMasami Hiramatsu 		semantic_error("Return probe requires an entry function.");
17250656eecSMasami Hiramatsu 
17350656eecSMasami Hiramatsu 	if ((pp->offset || pp->line) && pp->retprobe)
17450656eecSMasami Hiramatsu 		semantic_error("Offset/Line can't be used with return probe.");
17550656eecSMasami Hiramatsu 
17650656eecSMasami Hiramatsu 	pr_debug("symbol:%s file:%s line:%d offset:%d, return:%d\n",
17750656eecSMasami Hiramatsu 		 pp->function, pp->file, pp->line, pp->offset, pp->retprobe);
17850656eecSMasami Hiramatsu }
17950656eecSMasami Hiramatsu 
18050656eecSMasami Hiramatsu /* Parse perf-probe event definition */
181fac13fd5SMasami Hiramatsu void parse_perf_probe_event(const char *str, struct probe_point *pp,
182fac13fd5SMasami Hiramatsu 			    bool *need_dwarf)
18350656eecSMasami Hiramatsu {
184e1c01d61SMasami Hiramatsu 	char **argv;
185fac13fd5SMasami Hiramatsu 	int argc, i;
186fac13fd5SMasami Hiramatsu 
187fac13fd5SMasami Hiramatsu 	*need_dwarf = false;
18850656eecSMasami Hiramatsu 
189e1c01d61SMasami Hiramatsu 	argv = argv_split(str, &argc);
190e1c01d61SMasami Hiramatsu 	if (!argv)
191e1c01d61SMasami Hiramatsu 		die("argv_split failed.");
192e1c01d61SMasami Hiramatsu 	if (argc > MAX_PROBE_ARGS + 1)
19350656eecSMasami Hiramatsu 		semantic_error("Too many arguments");
19450656eecSMasami Hiramatsu 
19550656eecSMasami Hiramatsu 	/* Parse probe point */
19650656eecSMasami Hiramatsu 	parse_perf_probe_probepoint(argv[0], pp);
19750656eecSMasami Hiramatsu 	if (pp->file || pp->line)
198fac13fd5SMasami Hiramatsu 		*need_dwarf = true;
19950656eecSMasami Hiramatsu 
200e1c01d61SMasami Hiramatsu 	/* Copy arguments and ensure return probe has no C argument */
20150656eecSMasami Hiramatsu 	pp->nr_args = argc - 1;
202e1c01d61SMasami Hiramatsu 	pp->args = zalloc(sizeof(char *) * pp->nr_args);
203e1c01d61SMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
204e1c01d61SMasami Hiramatsu 		pp->args[i] = strdup(argv[i + 1]);
205e1c01d61SMasami Hiramatsu 		if (!pp->args[i])
206e1c01d61SMasami Hiramatsu 			die("Failed to copy argument.");
20750656eecSMasami Hiramatsu 		if (is_c_varname(pp->args[i])) {
20850656eecSMasami Hiramatsu 			if (pp->retprobe)
20950656eecSMasami Hiramatsu 				semantic_error("You can't specify local"
21050656eecSMasami Hiramatsu 						" variable for kretprobe");
211fac13fd5SMasami Hiramatsu 			*need_dwarf = true;
21250656eecSMasami Hiramatsu 		}
213e1c01d61SMasami Hiramatsu 	}
21450656eecSMasami Hiramatsu 
215e1c01d61SMasami Hiramatsu 	argv_free(argv);
21650656eecSMasami Hiramatsu }
21750656eecSMasami Hiramatsu 
2184de189feSMasami Hiramatsu /* Parse kprobe_events event into struct probe_point */
219af663d75SMasami Hiramatsu void parse_trace_kprobe_event(const char *str, struct probe_point *pp)
2204de189feSMasami Hiramatsu {
2214de189feSMasami Hiramatsu 	char pr;
2224de189feSMasami Hiramatsu 	char *p;
2234de189feSMasami Hiramatsu 	int ret, i, argc;
2244de189feSMasami Hiramatsu 	char **argv;
2254de189feSMasami Hiramatsu 
2264de189feSMasami Hiramatsu 	pr_debug("Parsing kprobe_events: %s\n", str);
2274de189feSMasami Hiramatsu 	argv = argv_split(str, &argc);
2284de189feSMasami Hiramatsu 	if (!argv)
2294de189feSMasami Hiramatsu 		die("argv_split failed.");
2304de189feSMasami Hiramatsu 	if (argc < 2)
2314de189feSMasami Hiramatsu 		semantic_error("Too less arguments.");
2324de189feSMasami Hiramatsu 
2334de189feSMasami Hiramatsu 	/* Scan event and group name. */
23493aaa45aSLiming Wang 	ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
235af663d75SMasami Hiramatsu 		     &pr, (float *)(void *)&pp->group,
236af663d75SMasami Hiramatsu 		     (float *)(void *)&pp->event);
2374de189feSMasami Hiramatsu 	if (ret != 3)
2384de189feSMasami Hiramatsu 		semantic_error("Failed to parse event name: %s", argv[0]);
239af663d75SMasami Hiramatsu 	pr_debug("Group:%s Event:%s probe:%c\n", pp->group, pp->event, pr);
2404de189feSMasami Hiramatsu 
2414de189feSMasami Hiramatsu 	pp->retprobe = (pr == 'r');
2424de189feSMasami Hiramatsu 
2434de189feSMasami Hiramatsu 	/* Scan function name and offset */
244af663d75SMasami Hiramatsu 	ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function,
245af663d75SMasami Hiramatsu 		     &pp->offset);
2464de189feSMasami Hiramatsu 	if (ret == 1)
2474de189feSMasami Hiramatsu 		pp->offset = 0;
2484de189feSMasami Hiramatsu 
2494de189feSMasami Hiramatsu 	/* kprobe_events doesn't have this information */
2504de189feSMasami Hiramatsu 	pp->line = 0;
2514de189feSMasami Hiramatsu 	pp->file = NULL;
2524de189feSMasami Hiramatsu 
2534de189feSMasami Hiramatsu 	pp->nr_args = argc - 2;
2544de189feSMasami Hiramatsu 	pp->args = zalloc(sizeof(char *) * pp->nr_args);
2554de189feSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
2564de189feSMasami Hiramatsu 		p = strchr(argv[i + 2], '=');
2574de189feSMasami Hiramatsu 		if (p)	/* We don't need which register is assigned. */
2584de189feSMasami Hiramatsu 			*p = '\0';
2594de189feSMasami Hiramatsu 		pp->args[i] = strdup(argv[i + 2]);
2604de189feSMasami Hiramatsu 		if (!pp->args[i])
2614de189feSMasami Hiramatsu 			die("Failed to copy argument.");
2624de189feSMasami Hiramatsu 	}
2634de189feSMasami Hiramatsu 
2644de189feSMasami Hiramatsu 	argv_free(argv);
2654de189feSMasami Hiramatsu }
2664de189feSMasami Hiramatsu 
2677ef17aafSMasami Hiramatsu /* Synthesize only probe point (not argument) */
2687ef17aafSMasami Hiramatsu int synthesize_perf_probe_point(struct probe_point *pp)
26950656eecSMasami Hiramatsu {
27050656eecSMasami Hiramatsu 	char *buf;
2714de189feSMasami Hiramatsu 	char offs[64] = "", line[64] = "";
2727ef17aafSMasami Hiramatsu 	int ret;
27350656eecSMasami Hiramatsu 
27450656eecSMasami Hiramatsu 	pp->probes[0] = buf = zalloc(MAX_CMDLEN);
27550656eecSMasami Hiramatsu 	if (!buf)
27650656eecSMasami Hiramatsu 		die("Failed to allocate memory by zalloc.");
2774de189feSMasami Hiramatsu 	if (pp->offset) {
2784de189feSMasami Hiramatsu 		ret = e_snprintf(offs, 64, "+%d", pp->offset);
2794de189feSMasami Hiramatsu 		if (ret <= 0)
2804de189feSMasami Hiramatsu 			goto error;
2814de189feSMasami Hiramatsu 	}
2824de189feSMasami Hiramatsu 	if (pp->line) {
2834de189feSMasami Hiramatsu 		ret = e_snprintf(line, 64, ":%d", pp->line);
2844de189feSMasami Hiramatsu 		if (ret <= 0)
2854de189feSMasami Hiramatsu 			goto error;
2864de189feSMasami Hiramatsu 	}
2874de189feSMasami Hiramatsu 
2884de189feSMasami Hiramatsu 	if (pp->function)
2894de189feSMasami Hiramatsu 		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function,
2904de189feSMasami Hiramatsu 				 offs, pp->retprobe ? "%return" : "", line);
2914de189feSMasami Hiramatsu 	else
29284988450SMasami Hiramatsu 		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line);
2937ef17aafSMasami Hiramatsu 	if (ret <= 0) {
2947ef17aafSMasami Hiramatsu error:
2957ef17aafSMasami Hiramatsu 		free(pp->probes[0]);
2967ef17aafSMasami Hiramatsu 		pp->probes[0] = NULL;
2977ef17aafSMasami Hiramatsu 	}
2987ef17aafSMasami Hiramatsu 	return ret;
2997ef17aafSMasami Hiramatsu }
30050656eecSMasami Hiramatsu 
3017ef17aafSMasami Hiramatsu int synthesize_perf_probe_event(struct probe_point *pp)
3027ef17aafSMasami Hiramatsu {
3037ef17aafSMasami Hiramatsu 	char *buf;
3047ef17aafSMasami Hiramatsu 	int i, len, ret;
3057ef17aafSMasami Hiramatsu 
3067ef17aafSMasami Hiramatsu 	len = synthesize_perf_probe_point(pp);
3077ef17aafSMasami Hiramatsu 	if (len < 0)
3087ef17aafSMasami Hiramatsu 		return 0;
3097ef17aafSMasami Hiramatsu 
3107ef17aafSMasami Hiramatsu 	buf = pp->probes[0];
31150656eecSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
3124de189feSMasami Hiramatsu 		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
31350656eecSMasami Hiramatsu 				 pp->args[i]);
3144de189feSMasami Hiramatsu 		if (ret <= 0)
31550656eecSMasami Hiramatsu 			goto error;
31650656eecSMasami Hiramatsu 		len += ret;
31750656eecSMasami Hiramatsu 	}
31850656eecSMasami Hiramatsu 	pp->found = 1;
31950656eecSMasami Hiramatsu 
32050656eecSMasami Hiramatsu 	return pp->found;
32150656eecSMasami Hiramatsu error:
32250656eecSMasami Hiramatsu 	free(pp->probes[0]);
3237ef17aafSMasami Hiramatsu 	pp->probes[0] = NULL;
32450656eecSMasami Hiramatsu 
32550656eecSMasami Hiramatsu 	return ret;
32650656eecSMasami Hiramatsu }
32750656eecSMasami Hiramatsu 
3284de189feSMasami Hiramatsu int synthesize_trace_kprobe_event(struct probe_point *pp)
3294de189feSMasami Hiramatsu {
3304de189feSMasami Hiramatsu 	char *buf;
3314de189feSMasami Hiramatsu 	int i, len, ret;
3324de189feSMasami Hiramatsu 
3334de189feSMasami Hiramatsu 	pp->probes[0] = buf = zalloc(MAX_CMDLEN);
3344de189feSMasami Hiramatsu 	if (!buf)
3354de189feSMasami Hiramatsu 		die("Failed to allocate memory by zalloc.");
3364de189feSMasami Hiramatsu 	ret = e_snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset);
3374de189feSMasami Hiramatsu 	if (ret <= 0)
3384de189feSMasami Hiramatsu 		goto error;
3394de189feSMasami Hiramatsu 	len = ret;
3404de189feSMasami Hiramatsu 
3414de189feSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
3424de189feSMasami Hiramatsu 		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
3434de189feSMasami Hiramatsu 				 pp->args[i]);
3444de189feSMasami Hiramatsu 		if (ret <= 0)
3454de189feSMasami Hiramatsu 			goto error;
3464de189feSMasami Hiramatsu 		len += ret;
3474de189feSMasami Hiramatsu 	}
3484de189feSMasami Hiramatsu 	pp->found = 1;
3494de189feSMasami Hiramatsu 
3504de189feSMasami Hiramatsu 	return pp->found;
3514de189feSMasami Hiramatsu error:
3524de189feSMasami Hiramatsu 	free(pp->probes[0]);
3537ef17aafSMasami Hiramatsu 	pp->probes[0] = NULL;
3544de189feSMasami Hiramatsu 
3554de189feSMasami Hiramatsu 	return ret;
3564de189feSMasami Hiramatsu }
3574de189feSMasami Hiramatsu 
3584de189feSMasami Hiramatsu static int open_kprobe_events(int flags, int mode)
3594de189feSMasami Hiramatsu {
3604de189feSMasami Hiramatsu 	char buf[PATH_MAX];
3614de189feSMasami Hiramatsu 	int ret;
3624de189feSMasami Hiramatsu 
3634de189feSMasami Hiramatsu 	ret = e_snprintf(buf, PATH_MAX, "%s/../kprobe_events", debugfs_path);
3644de189feSMasami Hiramatsu 	if (ret < 0)
3654de189feSMasami Hiramatsu 		die("Failed to make kprobe_events path.");
3664de189feSMasami Hiramatsu 
3674de189feSMasami Hiramatsu 	ret = open(buf, flags, mode);
3684de189feSMasami Hiramatsu 	if (ret < 0) {
3694de189feSMasami Hiramatsu 		if (errno == ENOENT)
3704de189feSMasami Hiramatsu 			die("kprobe_events file does not exist -"
371*63bbd5e2SLiming Wang 			    " please rebuild with CONFIG_KPROBE_EVENT.");
3724de189feSMasami Hiramatsu 		else
3734de189feSMasami Hiramatsu 			die("Could not open kprobe_events file: %s",
3744de189feSMasami Hiramatsu 			    strerror(errno));
3754de189feSMasami Hiramatsu 	}
3764de189feSMasami Hiramatsu 	return ret;
3774de189feSMasami Hiramatsu }
3784de189feSMasami Hiramatsu 
3794de189feSMasami Hiramatsu /* Get raw string list of current kprobe_events */
3804de189feSMasami Hiramatsu static struct strlist *get_trace_kprobe_event_rawlist(int fd)
3814de189feSMasami Hiramatsu {
3824de189feSMasami Hiramatsu 	int ret, idx;
3834de189feSMasami Hiramatsu 	FILE *fp;
3844de189feSMasami Hiramatsu 	char buf[MAX_CMDLEN];
3854de189feSMasami Hiramatsu 	char *p;
3864de189feSMasami Hiramatsu 	struct strlist *sl;
3874de189feSMasami Hiramatsu 
3884de189feSMasami Hiramatsu 	sl = strlist__new(true, NULL);
3894de189feSMasami Hiramatsu 
3904de189feSMasami Hiramatsu 	fp = fdopen(dup(fd), "r");
3914de189feSMasami Hiramatsu 	while (!feof(fp)) {
3924de189feSMasami Hiramatsu 		p = fgets(buf, MAX_CMDLEN, fp);
3934de189feSMasami Hiramatsu 		if (!p)
3944de189feSMasami Hiramatsu 			break;
3954de189feSMasami Hiramatsu 
3964de189feSMasami Hiramatsu 		idx = strlen(p) - 1;
3974de189feSMasami Hiramatsu 		if (p[idx] == '\n')
3984de189feSMasami Hiramatsu 			p[idx] = '\0';
3994de189feSMasami Hiramatsu 		ret = strlist__add(sl, buf);
4004de189feSMasami Hiramatsu 		if (ret < 0)
4014de189feSMasami Hiramatsu 			die("strlist__add failed: %s", strerror(-ret));
4024de189feSMasami Hiramatsu 	}
4034de189feSMasami Hiramatsu 	fclose(fp);
4044de189feSMasami Hiramatsu 
4054de189feSMasami Hiramatsu 	return sl;
4064de189feSMasami Hiramatsu }
4074de189feSMasami Hiramatsu 
4084de189feSMasami Hiramatsu /* Free and zero clear probe_point */
4094de189feSMasami Hiramatsu static void clear_probe_point(struct probe_point *pp)
4104de189feSMasami Hiramatsu {
4114de189feSMasami Hiramatsu 	int i;
4124de189feSMasami Hiramatsu 
413af663d75SMasami Hiramatsu 	if (pp->event)
414af663d75SMasami Hiramatsu 		free(pp->event);
415af663d75SMasami Hiramatsu 	if (pp->group)
416af663d75SMasami Hiramatsu 		free(pp->group);
4174de189feSMasami Hiramatsu 	if (pp->function)
4184de189feSMasami Hiramatsu 		free(pp->function);
4194de189feSMasami Hiramatsu 	if (pp->file)
4204de189feSMasami Hiramatsu 		free(pp->file);
4214de189feSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++)
4224de189feSMasami Hiramatsu 		free(pp->args[i]);
4234de189feSMasami Hiramatsu 	if (pp->args)
4244de189feSMasami Hiramatsu 		free(pp->args);
4254de189feSMasami Hiramatsu 	for (i = 0; i < pp->found; i++)
4264de189feSMasami Hiramatsu 		free(pp->probes[i]);
4275660ce34SJulia Lawall 	memset(pp, 0, sizeof(*pp));
4284de189feSMasami Hiramatsu }
4294de189feSMasami Hiramatsu 
430278498d4SMasami Hiramatsu /* Show an event */
431af663d75SMasami Hiramatsu static void show_perf_probe_event(const char *event, const char *place,
432af663d75SMasami Hiramatsu 				  struct probe_point *pp)
433278498d4SMasami Hiramatsu {
4347e990a51SMasami Hiramatsu 	int i, ret;
435278498d4SMasami Hiramatsu 	char buf[128];
436278498d4SMasami Hiramatsu 
437af663d75SMasami Hiramatsu 	ret = e_snprintf(buf, 128, "%s:%s", pp->group, event);
4387e990a51SMasami Hiramatsu 	if (ret < 0)
4397e990a51SMasami Hiramatsu 		die("Failed to copy event: %s", strerror(-ret));
440278498d4SMasami Hiramatsu 	printf("  %-40s (on %s", buf, place);
441278498d4SMasami Hiramatsu 
442278498d4SMasami Hiramatsu 	if (pp->nr_args > 0) {
443278498d4SMasami Hiramatsu 		printf(" with");
444278498d4SMasami Hiramatsu 		for (i = 0; i < pp->nr_args; i++)
445278498d4SMasami Hiramatsu 			printf(" %s", pp->args[i]);
446278498d4SMasami Hiramatsu 	}
447278498d4SMasami Hiramatsu 	printf(")\n");
448278498d4SMasami Hiramatsu }
449278498d4SMasami Hiramatsu 
4504de189feSMasami Hiramatsu /* List up current perf-probe events */
4514de189feSMasami Hiramatsu void show_perf_probe_events(void)
4524de189feSMasami Hiramatsu {
4537ef17aafSMasami Hiramatsu 	int fd;
4544de189feSMasami Hiramatsu 	struct probe_point pp;
4554de189feSMasami Hiramatsu 	struct strlist *rawlist;
4564de189feSMasami Hiramatsu 	struct str_node *ent;
4574de189feSMasami Hiramatsu 
4584de189feSMasami Hiramatsu 	fd = open_kprobe_events(O_RDONLY, 0);
4594de189feSMasami Hiramatsu 	rawlist = get_trace_kprobe_event_rawlist(fd);
4604de189feSMasami Hiramatsu 	close(fd);
4614de189feSMasami Hiramatsu 
462adf365f4SMasami Hiramatsu 	strlist__for_each(ent, rawlist) {
463af663d75SMasami Hiramatsu 		parse_trace_kprobe_event(ent->s, &pp);
464278498d4SMasami Hiramatsu 		/* Synthesize only event probe point */
4657ef17aafSMasami Hiramatsu 		synthesize_perf_probe_point(&pp);
466278498d4SMasami Hiramatsu 		/* Show an event */
467af663d75SMasami Hiramatsu 		show_perf_probe_event(pp.event, pp.probes[0], &pp);
4684de189feSMasami Hiramatsu 		clear_probe_point(&pp);
4694de189feSMasami Hiramatsu 	}
4704de189feSMasami Hiramatsu 
4714de189feSMasami Hiramatsu 	strlist__delete(rawlist);
4724de189feSMasami Hiramatsu }
4734de189feSMasami Hiramatsu 
474b498ce1fSMasami Hiramatsu /* Get current perf-probe event names */
475fa28244dSMasami Hiramatsu static struct strlist *get_perf_event_names(int fd, bool include_group)
476b498ce1fSMasami Hiramatsu {
477fa28244dSMasami Hiramatsu 	char buf[128];
478b498ce1fSMasami Hiramatsu 	struct strlist *sl, *rawlist;
479b498ce1fSMasami Hiramatsu 	struct str_node *ent;
480af663d75SMasami Hiramatsu 	struct probe_point pp;
481b498ce1fSMasami Hiramatsu 
482af663d75SMasami Hiramatsu 	memset(&pp, 0, sizeof(pp));
483b498ce1fSMasami Hiramatsu 	rawlist = get_trace_kprobe_event_rawlist(fd);
484b498ce1fSMasami Hiramatsu 
485e1d2017bSMasami Hiramatsu 	sl = strlist__new(true, NULL);
486adf365f4SMasami Hiramatsu 	strlist__for_each(ent, rawlist) {
487af663d75SMasami Hiramatsu 		parse_trace_kprobe_event(ent->s, &pp);
488fa28244dSMasami Hiramatsu 		if (include_group) {
489af663d75SMasami Hiramatsu 			if (e_snprintf(buf, 128, "%s:%s", pp.group,
490af663d75SMasami Hiramatsu 				       pp.event) < 0)
491fa28244dSMasami Hiramatsu 				die("Failed to copy group:event name.");
492fa28244dSMasami Hiramatsu 			strlist__add(sl, buf);
493fa28244dSMasami Hiramatsu 		} else
494af663d75SMasami Hiramatsu 			strlist__add(sl, pp.event);
495af663d75SMasami Hiramatsu 		clear_probe_point(&pp);
496b498ce1fSMasami Hiramatsu 	}
497b498ce1fSMasami Hiramatsu 
498b498ce1fSMasami Hiramatsu 	strlist__delete(rawlist);
499b498ce1fSMasami Hiramatsu 
500b498ce1fSMasami Hiramatsu 	return sl;
501b498ce1fSMasami Hiramatsu }
502b498ce1fSMasami Hiramatsu 
503a9b495b0SMasami Hiramatsu static void write_trace_kprobe_event(int fd, const char *buf)
50450656eecSMasami Hiramatsu {
50550656eecSMasami Hiramatsu 	int ret;
50650656eecSMasami Hiramatsu 
507fa28244dSMasami Hiramatsu 	pr_debug("Writing event: %s\n", buf);
50850656eecSMasami Hiramatsu 	ret = write(fd, buf, strlen(buf));
50950656eecSMasami Hiramatsu 	if (ret <= 0)
510fa28244dSMasami Hiramatsu 		die("Failed to write event: %s", strerror(errno));
51150656eecSMasami Hiramatsu }
51250656eecSMasami Hiramatsu 
513b498ce1fSMasami Hiramatsu static void get_new_event_name(char *buf, size_t len, const char *base,
514d761b08bSMasami Hiramatsu 			       struct strlist *namelist, bool allow_suffix)
515b498ce1fSMasami Hiramatsu {
516b498ce1fSMasami Hiramatsu 	int i, ret;
51717f88fcdSMasami Hiramatsu 
51817f88fcdSMasami Hiramatsu 	/* Try no suffix */
51917f88fcdSMasami Hiramatsu 	ret = e_snprintf(buf, len, "%s", base);
52017f88fcdSMasami Hiramatsu 	if (ret < 0)
52117f88fcdSMasami Hiramatsu 		die("snprintf() failed: %s", strerror(-ret));
52217f88fcdSMasami Hiramatsu 	if (!strlist__has_entry(namelist, buf))
52317f88fcdSMasami Hiramatsu 		return;
52417f88fcdSMasami Hiramatsu 
525d761b08bSMasami Hiramatsu 	if (!allow_suffix) {
526d761b08bSMasami Hiramatsu 		pr_warning("Error: event \"%s\" already exists. "
527d761b08bSMasami Hiramatsu 			   "(Use -f to force duplicates.)\n", base);
528d761b08bSMasami Hiramatsu 		die("Can't add new event.");
529d761b08bSMasami Hiramatsu 	}
530d761b08bSMasami Hiramatsu 
53117f88fcdSMasami Hiramatsu 	/* Try to add suffix */
53217f88fcdSMasami Hiramatsu 	for (i = 1; i < MAX_EVENT_INDEX; i++) {
533b498ce1fSMasami Hiramatsu 		ret = e_snprintf(buf, len, "%s_%d", base, i);
534b498ce1fSMasami Hiramatsu 		if (ret < 0)
535b498ce1fSMasami Hiramatsu 			die("snprintf() failed: %s", strerror(-ret));
536b498ce1fSMasami Hiramatsu 		if (!strlist__has_entry(namelist, buf))
537b498ce1fSMasami Hiramatsu 			break;
538b498ce1fSMasami Hiramatsu 	}
539b498ce1fSMasami Hiramatsu 	if (i == MAX_EVENT_INDEX)
540b498ce1fSMasami Hiramatsu 		die("Too many events are on the same function.");
541b498ce1fSMasami Hiramatsu }
542b498ce1fSMasami Hiramatsu 
543d761b08bSMasami Hiramatsu void add_trace_kprobe_events(struct probe_point *probes, int nr_probes,
544d761b08bSMasami Hiramatsu 			     bool force_add)
54550656eecSMasami Hiramatsu {
54650656eecSMasami Hiramatsu 	int i, j, fd;
54750656eecSMasami Hiramatsu 	struct probe_point *pp;
54850656eecSMasami Hiramatsu 	char buf[MAX_CMDLEN];
549b498ce1fSMasami Hiramatsu 	char event[64];
550b498ce1fSMasami Hiramatsu 	struct strlist *namelist;
551d761b08bSMasami Hiramatsu 	bool allow_suffix;
55250656eecSMasami Hiramatsu 
553b498ce1fSMasami Hiramatsu 	fd = open_kprobe_events(O_RDWR, O_APPEND);
554b498ce1fSMasami Hiramatsu 	/* Get current event names */
555fa28244dSMasami Hiramatsu 	namelist = get_perf_event_names(fd, false);
55650656eecSMasami Hiramatsu 
55750656eecSMasami Hiramatsu 	for (j = 0; j < nr_probes; j++) {
55850656eecSMasami Hiramatsu 		pp = probes + j;
559af663d75SMasami Hiramatsu 		if (!pp->event)
560af663d75SMasami Hiramatsu 			pp->event = strdup(pp->function);
561af663d75SMasami Hiramatsu 		if (!pp->group)
562af663d75SMasami Hiramatsu 			pp->group = strdup(PERFPROBE_GROUP);
563af663d75SMasami Hiramatsu 		DIE_IF(!pp->event || !pp->group);
564d761b08bSMasami Hiramatsu 		/* If force_add is true, suffix search is allowed */
565d761b08bSMasami Hiramatsu 		allow_suffix = force_add;
56650656eecSMasami Hiramatsu 		for (i = 0; i < pp->found; i++) {
567b498ce1fSMasami Hiramatsu 			/* Get an unused new event name */
568d761b08bSMasami Hiramatsu 			get_new_event_name(event, 64, pp->event, namelist,
569d761b08bSMasami Hiramatsu 					   allow_suffix);
570b498ce1fSMasami Hiramatsu 			snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n",
57150656eecSMasami Hiramatsu 				 pp->retprobe ? 'r' : 'p',
572af663d75SMasami Hiramatsu 				 pp->group, event,
57350656eecSMasami Hiramatsu 				 pp->probes[i]);
57450656eecSMasami Hiramatsu 			write_trace_kprobe_event(fd, buf);
575a9b495b0SMasami Hiramatsu 			printf("Added new event:\n");
576a9b495b0SMasami Hiramatsu 			/* Get the first parameter (probe-point) */
577a9b495b0SMasami Hiramatsu 			sscanf(pp->probes[i], "%s", buf);
578af663d75SMasami Hiramatsu 			show_perf_probe_event(event, buf, pp);
579b498ce1fSMasami Hiramatsu 			/* Add added event name to namelist */
580b498ce1fSMasami Hiramatsu 			strlist__add(namelist, event);
581d761b08bSMasami Hiramatsu 			/*
582d761b08bSMasami Hiramatsu 			 * Probes after the first probe which comes from same
583d761b08bSMasami Hiramatsu 			 * user input are always allowed to add suffix, because
584d761b08bSMasami Hiramatsu 			 * there might be several addresses corresponding to
585d761b08bSMasami Hiramatsu 			 * one code line.
586d761b08bSMasami Hiramatsu 			 */
587d761b08bSMasami Hiramatsu 			allow_suffix = true;
58850656eecSMasami Hiramatsu 		}
58950656eecSMasami Hiramatsu 	}
590a9b495b0SMasami Hiramatsu 	/* Show how to use the event. */
591a9b495b0SMasami Hiramatsu 	printf("\nYou can now use it on all perf tools, such as:\n\n");
592a9b495b0SMasami Hiramatsu 	printf("\tperf record -e %s:%s -a sleep 1\n\n", PERFPROBE_GROUP, event);
593a9b495b0SMasami Hiramatsu 
594e1d2017bSMasami Hiramatsu 	strlist__delete(namelist);
59550656eecSMasami Hiramatsu 	close(fd);
59650656eecSMasami Hiramatsu }
597fa28244dSMasami Hiramatsu 
598bbbb521bSMasami Hiramatsu static void __del_trace_kprobe_event(int fd, struct str_node *ent)
599bbbb521bSMasami Hiramatsu {
600bbbb521bSMasami Hiramatsu 	char *p;
601bbbb521bSMasami Hiramatsu 	char buf[128];
602bbbb521bSMasami Hiramatsu 
603bbbb521bSMasami Hiramatsu 	/* Convert from perf-probe event to trace-kprobe event */
604bbbb521bSMasami Hiramatsu 	if (e_snprintf(buf, 128, "-:%s", ent->s) < 0)
605bbbb521bSMasami Hiramatsu 		die("Failed to copy event.");
606bbbb521bSMasami Hiramatsu 	p = strchr(buf + 2, ':');
607bbbb521bSMasami Hiramatsu 	if (!p)
608bbbb521bSMasami Hiramatsu 		die("Internal error: %s should have ':' but not.", ent->s);
609bbbb521bSMasami Hiramatsu 	*p = '/';
610bbbb521bSMasami Hiramatsu 
611bbbb521bSMasami Hiramatsu 	write_trace_kprobe_event(fd, buf);
612bbbb521bSMasami Hiramatsu 	printf("Remove event: %s\n", ent->s);
613bbbb521bSMasami Hiramatsu }
614bbbb521bSMasami Hiramatsu 
615fa28244dSMasami Hiramatsu static void del_trace_kprobe_event(int fd, const char *group,
616fa28244dSMasami Hiramatsu 				   const char *event, struct strlist *namelist)
617fa28244dSMasami Hiramatsu {
618fa28244dSMasami Hiramatsu 	char buf[128];
619bbbb521bSMasami Hiramatsu 	struct str_node *ent, *n;
620bbbb521bSMasami Hiramatsu 	int found = 0;
621fa28244dSMasami Hiramatsu 
622fa28244dSMasami Hiramatsu 	if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
623fa28244dSMasami Hiramatsu 		die("Failed to copy event.");
624fa28244dSMasami Hiramatsu 
625bbbb521bSMasami Hiramatsu 	if (strpbrk(buf, "*?")) { /* Glob-exp */
626bbbb521bSMasami Hiramatsu 		strlist__for_each_safe(ent, n, namelist)
627bbbb521bSMasami Hiramatsu 			if (strglobmatch(ent->s, buf)) {
628bbbb521bSMasami Hiramatsu 				found++;
629bbbb521bSMasami Hiramatsu 				__del_trace_kprobe_event(fd, ent);
6303e340590SMasami Hiramatsu 				strlist__remove(namelist, ent);
631fa28244dSMasami Hiramatsu 			}
632bbbb521bSMasami Hiramatsu 	} else {
633bbbb521bSMasami Hiramatsu 		ent = strlist__find(namelist, buf);
634bbbb521bSMasami Hiramatsu 		if (ent) {
635bbbb521bSMasami Hiramatsu 			found++;
636bbbb521bSMasami Hiramatsu 			__del_trace_kprobe_event(fd, ent);
637bbbb521bSMasami Hiramatsu 			strlist__remove(namelist, ent);
638bbbb521bSMasami Hiramatsu 		}
639bbbb521bSMasami Hiramatsu 	}
640bbbb521bSMasami Hiramatsu 	if (found == 0)
641bbbb521bSMasami Hiramatsu 		pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf);
642bbbb521bSMasami Hiramatsu }
643fa28244dSMasami Hiramatsu 
644fa28244dSMasami Hiramatsu void del_trace_kprobe_events(struct strlist *dellist)
645fa28244dSMasami Hiramatsu {
646fa28244dSMasami Hiramatsu 	int fd;
647fa28244dSMasami Hiramatsu 	const char *group, *event;
648fa28244dSMasami Hiramatsu 	char *p, *str;
649fa28244dSMasami Hiramatsu 	struct str_node *ent;
650fa28244dSMasami Hiramatsu 	struct strlist *namelist;
651fa28244dSMasami Hiramatsu 
652fa28244dSMasami Hiramatsu 	fd = open_kprobe_events(O_RDWR, O_APPEND);
653fa28244dSMasami Hiramatsu 	/* Get current event names */
654fa28244dSMasami Hiramatsu 	namelist = get_perf_event_names(fd, true);
655fa28244dSMasami Hiramatsu 
656adf365f4SMasami Hiramatsu 	strlist__for_each(ent, dellist) {
657fa28244dSMasami Hiramatsu 		str = strdup(ent->s);
658fa28244dSMasami Hiramatsu 		if (!str)
659fa28244dSMasami Hiramatsu 			die("Failed to copy event.");
660bbbb521bSMasami Hiramatsu 		pr_debug("Parsing: %s\n", str);
661fa28244dSMasami Hiramatsu 		p = strchr(str, ':');
662fa28244dSMasami Hiramatsu 		if (p) {
663fa28244dSMasami Hiramatsu 			group = str;
664fa28244dSMasami Hiramatsu 			*p = '\0';
665fa28244dSMasami Hiramatsu 			event = p + 1;
666fa28244dSMasami Hiramatsu 		} else {
667bbbb521bSMasami Hiramatsu 			group = "*";
668fa28244dSMasami Hiramatsu 			event = str;
669fa28244dSMasami Hiramatsu 		}
670bbbb521bSMasami Hiramatsu 		pr_debug("Group: %s, Event: %s\n", group, event);
671fa28244dSMasami Hiramatsu 		del_trace_kprobe_event(fd, group, event, namelist);
672fa28244dSMasami Hiramatsu 		free(str);
673fa28244dSMasami Hiramatsu 	}
674fa28244dSMasami Hiramatsu 	strlist__delete(namelist);
675fa28244dSMasami Hiramatsu 	close(fd);
676fa28244dSMasami Hiramatsu }
677fa28244dSMasami Hiramatsu 
678