xref: /linux/tools/perf/util/probe-event.c (revision fc6ceea045031658d0b59af562369eae980b4370)
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"
4072041334SMasami Hiramatsu #include "cache.h"
41631c9defSMasami Hiramatsu #include "color.h"
4250656eecSMasami Hiramatsu #include "parse-events.h"  /* For debugfs_path */
4350656eecSMasami Hiramatsu #include "probe-event.h"
4450656eecSMasami Hiramatsu 
4550656eecSMasami Hiramatsu #define MAX_CMDLEN 256
4650656eecSMasami Hiramatsu #define MAX_PROBE_ARGS 128
4750656eecSMasami Hiramatsu #define PERFPROBE_GROUP "probe"
4850656eecSMasami Hiramatsu 
4950656eecSMasami Hiramatsu #define semantic_error(msg ...) die("Semantic error :" msg)
5050656eecSMasami Hiramatsu 
514de189feSMasami Hiramatsu /* If there is no space to write, returns -E2BIG. */
524de189feSMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...)
5384988450SMasami Hiramatsu 	__attribute__((format(printf, 3, 4)));
5484988450SMasami Hiramatsu 
5584988450SMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...)
564de189feSMasami Hiramatsu {
574de189feSMasami Hiramatsu 	int ret;
584de189feSMasami Hiramatsu 	va_list ap;
594de189feSMasami Hiramatsu 	va_start(ap, format);
604de189feSMasami Hiramatsu 	ret = vsnprintf(str, size, format, ap);
614de189feSMasami Hiramatsu 	va_end(ap);
624de189feSMasami Hiramatsu 	if (ret >= (int)size)
634de189feSMasami Hiramatsu 		ret = -E2BIG;
644de189feSMasami Hiramatsu 	return ret;
654de189feSMasami Hiramatsu }
664de189feSMasami Hiramatsu 
67631c9defSMasami Hiramatsu void parse_line_range_desc(const char *arg, struct line_range *lr)
68631c9defSMasami Hiramatsu {
69631c9defSMasami Hiramatsu 	const char *ptr;
70631c9defSMasami Hiramatsu 	char *tmp;
71631c9defSMasami Hiramatsu 	/*
72631c9defSMasami Hiramatsu 	 * <Syntax>
73631c9defSMasami Hiramatsu 	 * SRC:SLN[+NUM|-ELN]
74631c9defSMasami Hiramatsu 	 * FUNC[:SLN[+NUM|-ELN]]
75631c9defSMasami Hiramatsu 	 */
76631c9defSMasami Hiramatsu 	ptr = strchr(arg, ':');
77631c9defSMasami Hiramatsu 	if (ptr) {
78631c9defSMasami Hiramatsu 		lr->start = (unsigned int)strtoul(ptr + 1, &tmp, 0);
79631c9defSMasami Hiramatsu 		if (*tmp == '+')
80631c9defSMasami Hiramatsu 			lr->end = lr->start + (unsigned int)strtoul(tmp + 1,
81631c9defSMasami Hiramatsu 								    &tmp, 0);
82631c9defSMasami Hiramatsu 		else if (*tmp == '-')
83631c9defSMasami Hiramatsu 			lr->end = (unsigned int)strtoul(tmp + 1, &tmp, 0);
84631c9defSMasami Hiramatsu 		else
85631c9defSMasami Hiramatsu 			lr->end = 0;
86631c9defSMasami Hiramatsu 		pr_debug("Line range is %u to %u\n", lr->start, lr->end);
87631c9defSMasami Hiramatsu 		if (lr->end && lr->start > lr->end)
88631c9defSMasami Hiramatsu 			semantic_error("Start line must be smaller"
89631c9defSMasami Hiramatsu 				       " than end line.");
90631c9defSMasami Hiramatsu 		if (*tmp != '\0')
91631c9defSMasami Hiramatsu 			semantic_error("Tailing with invalid character '%d'.",
92631c9defSMasami Hiramatsu 				       *tmp);
93631c9defSMasami Hiramatsu 		tmp = strndup(arg, (ptr - arg));
94631c9defSMasami Hiramatsu 	} else
95631c9defSMasami Hiramatsu 		tmp = strdup(arg);
96631c9defSMasami Hiramatsu 
97631c9defSMasami Hiramatsu 	if (strchr(tmp, '.'))
98631c9defSMasami Hiramatsu 		lr->file = tmp;
99631c9defSMasami Hiramatsu 	else
100631c9defSMasami Hiramatsu 		lr->function = tmp;
101631c9defSMasami Hiramatsu }
102631c9defSMasami Hiramatsu 
103b7702a21SMasami Hiramatsu /* Check the name is good for event/group */
104b7702a21SMasami Hiramatsu static bool check_event_name(const char *name)
105b7702a21SMasami Hiramatsu {
106b7702a21SMasami Hiramatsu 	if (!isalpha(*name) && *name != '_')
107b7702a21SMasami Hiramatsu 		return false;
108b7702a21SMasami Hiramatsu 	while (*++name != '\0') {
109b7702a21SMasami Hiramatsu 		if (!isalpha(*name) && !isdigit(*name) && *name != '_')
110b7702a21SMasami Hiramatsu 			return false;
111b7702a21SMasami Hiramatsu 	}
112b7702a21SMasami Hiramatsu 	return true;
113b7702a21SMasami Hiramatsu }
114b7702a21SMasami Hiramatsu 
11550656eecSMasami Hiramatsu /* Parse probepoint definition. */
11650656eecSMasami Hiramatsu static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
11750656eecSMasami Hiramatsu {
11850656eecSMasami Hiramatsu 	char *ptr, *tmp;
11950656eecSMasami Hiramatsu 	char c, nc = 0;
12050656eecSMasami Hiramatsu 	/*
12150656eecSMasami Hiramatsu 	 * <Syntax>
1222a9c8c36SMasami Hiramatsu 	 * perf probe [EVENT=]SRC[:LN|;PTN]
1232a9c8c36SMasami Hiramatsu 	 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
124af663d75SMasami Hiramatsu 	 *
125af663d75SMasami Hiramatsu 	 * TODO:Group name support
12650656eecSMasami Hiramatsu 	 */
12750656eecSMasami Hiramatsu 
1282a9c8c36SMasami Hiramatsu 	ptr = strpbrk(arg, ";=@+%");
1292a9c8c36SMasami Hiramatsu 	if (ptr && *ptr == '=') {	/* Event name */
130af663d75SMasami Hiramatsu 		*ptr = '\0';
131af663d75SMasami Hiramatsu 		tmp = ptr + 1;
132af663d75SMasami Hiramatsu 		ptr = strchr(arg, ':');
133af663d75SMasami Hiramatsu 		if (ptr)	/* Group name is not supported yet. */
134af663d75SMasami Hiramatsu 			semantic_error("Group name is not supported yet.");
135b7702a21SMasami Hiramatsu 		if (!check_event_name(arg))
136b7702a21SMasami Hiramatsu 			semantic_error("%s is bad for event name -it must "
137b7702a21SMasami Hiramatsu 				       "follow C symbol-naming rule.", arg);
138af663d75SMasami Hiramatsu 		pp->event = strdup(arg);
139af663d75SMasami Hiramatsu 		arg = tmp;
140af663d75SMasami Hiramatsu 	}
141af663d75SMasami Hiramatsu 
1422a9c8c36SMasami Hiramatsu 	ptr = strpbrk(arg, ";:+@%");
14350656eecSMasami Hiramatsu 	if (ptr) {
14450656eecSMasami Hiramatsu 		nc = *ptr;
14550656eecSMasami Hiramatsu 		*ptr++ = '\0';
14650656eecSMasami Hiramatsu 	}
14750656eecSMasami Hiramatsu 
14850656eecSMasami Hiramatsu 	/* Check arg is function or file and copy it */
14950656eecSMasami Hiramatsu 	if (strchr(arg, '.'))	/* File */
15050656eecSMasami Hiramatsu 		pp->file = strdup(arg);
15150656eecSMasami Hiramatsu 	else			/* Function */
15250656eecSMasami Hiramatsu 		pp->function = strdup(arg);
15350656eecSMasami Hiramatsu 	DIE_IF(pp->file == NULL && pp->function == NULL);
15450656eecSMasami Hiramatsu 
15550656eecSMasami Hiramatsu 	/* Parse other options */
15650656eecSMasami Hiramatsu 	while (ptr) {
15750656eecSMasami Hiramatsu 		arg = ptr;
15850656eecSMasami Hiramatsu 		c = nc;
1592a9c8c36SMasami Hiramatsu 		if (c == ';') {	/* Lazy pattern must be the last part */
1602a9c8c36SMasami Hiramatsu 			pp->lazy_line = strdup(arg);
1612a9c8c36SMasami Hiramatsu 			break;
1622a9c8c36SMasami Hiramatsu 		}
1632a9c8c36SMasami Hiramatsu 		ptr = strpbrk(arg, ";:+@%");
16450656eecSMasami Hiramatsu 		if (ptr) {
16550656eecSMasami Hiramatsu 			nc = *ptr;
16650656eecSMasami Hiramatsu 			*ptr++ = '\0';
16750656eecSMasami Hiramatsu 		}
16850656eecSMasami Hiramatsu 		switch (c) {
16950656eecSMasami Hiramatsu 		case ':':	/* Line number */
17050656eecSMasami Hiramatsu 			pp->line = strtoul(arg, &tmp, 0);
17150656eecSMasami Hiramatsu 			if (*tmp != '\0')
1722a9c8c36SMasami Hiramatsu 				semantic_error("There is non-digit char"
17350656eecSMasami Hiramatsu 					       " in line number.");
17450656eecSMasami Hiramatsu 			break;
17550656eecSMasami Hiramatsu 		case '+':	/* Byte offset from a symbol */
17650656eecSMasami Hiramatsu 			pp->offset = strtoul(arg, &tmp, 0);
17750656eecSMasami Hiramatsu 			if (*tmp != '\0')
1782a9c8c36SMasami Hiramatsu 				semantic_error("There is non-digit character"
17950656eecSMasami Hiramatsu 						" in offset.");
18050656eecSMasami Hiramatsu 			break;
18150656eecSMasami Hiramatsu 		case '@':	/* File name */
18250656eecSMasami Hiramatsu 			if (pp->file)
18350656eecSMasami Hiramatsu 				semantic_error("SRC@SRC is not allowed.");
18450656eecSMasami Hiramatsu 			pp->file = strdup(arg);
18550656eecSMasami Hiramatsu 			DIE_IF(pp->file == NULL);
18650656eecSMasami Hiramatsu 			break;
18750656eecSMasami Hiramatsu 		case '%':	/* Probe places */
18850656eecSMasami Hiramatsu 			if (strcmp(arg, "return") == 0) {
18950656eecSMasami Hiramatsu 				pp->retprobe = 1;
19050656eecSMasami Hiramatsu 			} else	/* Others not supported yet */
19150656eecSMasami Hiramatsu 				semantic_error("%%%s is not supported.", arg);
19250656eecSMasami Hiramatsu 			break;
19350656eecSMasami Hiramatsu 		default:
19450656eecSMasami Hiramatsu 			DIE_IF("Program has a bug.");
19550656eecSMasami Hiramatsu 			break;
19650656eecSMasami Hiramatsu 		}
19750656eecSMasami Hiramatsu 	}
19850656eecSMasami Hiramatsu 
19950656eecSMasami Hiramatsu 	/* Exclusion check */
2002a9c8c36SMasami Hiramatsu 	if (pp->lazy_line && pp->line)
2012a9c8c36SMasami Hiramatsu 		semantic_error("Lazy pattern can't be used with line number.");
2022a9c8c36SMasami Hiramatsu 
2032a9c8c36SMasami Hiramatsu 	if (pp->lazy_line && pp->offset)
2042a9c8c36SMasami Hiramatsu 		semantic_error("Lazy pattern can't be used with offset.");
2052a9c8c36SMasami Hiramatsu 
20650656eecSMasami Hiramatsu 	if (pp->line && pp->offset)
20750656eecSMasami Hiramatsu 		semantic_error("Offset can't be used with line number.");
20850656eecSMasami Hiramatsu 
2092a9c8c36SMasami Hiramatsu 	if (!pp->line && !pp->lazy_line && pp->file && !pp->function)
2102a9c8c36SMasami Hiramatsu 		semantic_error("File always requires line number or "
2112a9c8c36SMasami Hiramatsu 			       "lazy pattern.");
21250656eecSMasami Hiramatsu 
21350656eecSMasami Hiramatsu 	if (pp->offset && !pp->function)
21450656eecSMasami Hiramatsu 		semantic_error("Offset requires an entry function.");
21550656eecSMasami Hiramatsu 
21650656eecSMasami Hiramatsu 	if (pp->retprobe && !pp->function)
21750656eecSMasami Hiramatsu 		semantic_error("Return probe requires an entry function.");
21850656eecSMasami Hiramatsu 
2192a9c8c36SMasami Hiramatsu 	if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe)
2202a9c8c36SMasami Hiramatsu 		semantic_error("Offset/Line/Lazy pattern can't be used with "
2212a9c8c36SMasami Hiramatsu 			       "return probe.");
22250656eecSMasami Hiramatsu 
2232a9c8c36SMasami Hiramatsu 	pr_debug("symbol:%s file:%s line:%d offset:%d return:%d lazy:%s\n",
2242a9c8c36SMasami Hiramatsu 		 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
2252a9c8c36SMasami Hiramatsu 		 pp->lazy_line);
22650656eecSMasami Hiramatsu }
22750656eecSMasami Hiramatsu 
22850656eecSMasami Hiramatsu /* Parse perf-probe event definition */
229fac13fd5SMasami Hiramatsu void parse_perf_probe_event(const char *str, struct probe_point *pp,
230fac13fd5SMasami Hiramatsu 			    bool *need_dwarf)
23150656eecSMasami Hiramatsu {
232e1c01d61SMasami Hiramatsu 	char **argv;
233fac13fd5SMasami Hiramatsu 	int argc, i;
234fac13fd5SMasami Hiramatsu 
235fac13fd5SMasami Hiramatsu 	*need_dwarf = false;
23650656eecSMasami Hiramatsu 
237e1c01d61SMasami Hiramatsu 	argv = argv_split(str, &argc);
238e1c01d61SMasami Hiramatsu 	if (!argv)
239e1c01d61SMasami Hiramatsu 		die("argv_split failed.");
240e1c01d61SMasami Hiramatsu 	if (argc > MAX_PROBE_ARGS + 1)
24150656eecSMasami Hiramatsu 		semantic_error("Too many arguments");
24250656eecSMasami Hiramatsu 
24350656eecSMasami Hiramatsu 	/* Parse probe point */
24450656eecSMasami Hiramatsu 	parse_perf_probe_probepoint(argv[0], pp);
245*fc6ceea0SMasami Hiramatsu 	if (pp->file || pp->line || pp->lazy_line)
246fac13fd5SMasami Hiramatsu 		*need_dwarf = true;
24750656eecSMasami Hiramatsu 
248e1c01d61SMasami Hiramatsu 	/* Copy arguments and ensure return probe has no C argument */
24950656eecSMasami Hiramatsu 	pp->nr_args = argc - 1;
250e1c01d61SMasami Hiramatsu 	pp->args = zalloc(sizeof(char *) * pp->nr_args);
251e1c01d61SMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
252e1c01d61SMasami Hiramatsu 		pp->args[i] = strdup(argv[i + 1]);
253e1c01d61SMasami Hiramatsu 		if (!pp->args[i])
254e1c01d61SMasami Hiramatsu 			die("Failed to copy argument.");
25550656eecSMasami Hiramatsu 		if (is_c_varname(pp->args[i])) {
25650656eecSMasami Hiramatsu 			if (pp->retprobe)
25750656eecSMasami Hiramatsu 				semantic_error("You can't specify local"
25850656eecSMasami Hiramatsu 						" variable for kretprobe");
259fac13fd5SMasami Hiramatsu 			*need_dwarf = true;
26050656eecSMasami Hiramatsu 		}
261e1c01d61SMasami Hiramatsu 	}
26250656eecSMasami Hiramatsu 
263e1c01d61SMasami Hiramatsu 	argv_free(argv);
26450656eecSMasami Hiramatsu }
26550656eecSMasami Hiramatsu 
2664de189feSMasami Hiramatsu /* Parse kprobe_events event into struct probe_point */
267af663d75SMasami Hiramatsu void parse_trace_kprobe_event(const char *str, struct probe_point *pp)
2684de189feSMasami Hiramatsu {
2694de189feSMasami Hiramatsu 	char pr;
2704de189feSMasami Hiramatsu 	char *p;
2714de189feSMasami Hiramatsu 	int ret, i, argc;
2724de189feSMasami Hiramatsu 	char **argv;
2734de189feSMasami Hiramatsu 
2744de189feSMasami Hiramatsu 	pr_debug("Parsing kprobe_events: %s\n", str);
2754de189feSMasami Hiramatsu 	argv = argv_split(str, &argc);
2764de189feSMasami Hiramatsu 	if (!argv)
2774de189feSMasami Hiramatsu 		die("argv_split failed.");
2784de189feSMasami Hiramatsu 	if (argc < 2)
2794de189feSMasami Hiramatsu 		semantic_error("Too less arguments.");
2804de189feSMasami Hiramatsu 
2814de189feSMasami Hiramatsu 	/* Scan event and group name. */
28293aaa45aSLiming Wang 	ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
283af663d75SMasami Hiramatsu 		     &pr, (float *)(void *)&pp->group,
284af663d75SMasami Hiramatsu 		     (float *)(void *)&pp->event);
2854de189feSMasami Hiramatsu 	if (ret != 3)
2864de189feSMasami Hiramatsu 		semantic_error("Failed to parse event name: %s", argv[0]);
287af663d75SMasami Hiramatsu 	pr_debug("Group:%s Event:%s probe:%c\n", pp->group, pp->event, pr);
2884de189feSMasami Hiramatsu 
2894de189feSMasami Hiramatsu 	pp->retprobe = (pr == 'r');
2904de189feSMasami Hiramatsu 
2914de189feSMasami Hiramatsu 	/* Scan function name and offset */
292af663d75SMasami Hiramatsu 	ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function,
293af663d75SMasami Hiramatsu 		     &pp->offset);
2944de189feSMasami Hiramatsu 	if (ret == 1)
2954de189feSMasami Hiramatsu 		pp->offset = 0;
2964de189feSMasami Hiramatsu 
2974de189feSMasami Hiramatsu 	/* kprobe_events doesn't have this information */
2984de189feSMasami Hiramatsu 	pp->line = 0;
2994de189feSMasami Hiramatsu 	pp->file = NULL;
3004de189feSMasami Hiramatsu 
3014de189feSMasami Hiramatsu 	pp->nr_args = argc - 2;
3024de189feSMasami Hiramatsu 	pp->args = zalloc(sizeof(char *) * pp->nr_args);
3034de189feSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
3044de189feSMasami Hiramatsu 		p = strchr(argv[i + 2], '=');
3054de189feSMasami Hiramatsu 		if (p)	/* We don't need which register is assigned. */
3064de189feSMasami Hiramatsu 			*p = '\0';
3074de189feSMasami Hiramatsu 		pp->args[i] = strdup(argv[i + 2]);
3084de189feSMasami Hiramatsu 		if (!pp->args[i])
3094de189feSMasami Hiramatsu 			die("Failed to copy argument.");
3104de189feSMasami Hiramatsu 	}
3114de189feSMasami Hiramatsu 
3124de189feSMasami Hiramatsu 	argv_free(argv);
3134de189feSMasami Hiramatsu }
3144de189feSMasami Hiramatsu 
3157ef17aafSMasami Hiramatsu /* Synthesize only probe point (not argument) */
3167ef17aafSMasami Hiramatsu int synthesize_perf_probe_point(struct probe_point *pp)
31750656eecSMasami Hiramatsu {
31850656eecSMasami Hiramatsu 	char *buf;
3194de189feSMasami Hiramatsu 	char offs[64] = "", line[64] = "";
3207ef17aafSMasami Hiramatsu 	int ret;
32150656eecSMasami Hiramatsu 
32250656eecSMasami Hiramatsu 	pp->probes[0] = buf = zalloc(MAX_CMDLEN);
323388c3aabSMasami Hiramatsu 	pp->found = 1;
32450656eecSMasami Hiramatsu 	if (!buf)
32550656eecSMasami Hiramatsu 		die("Failed to allocate memory by zalloc.");
3264de189feSMasami Hiramatsu 	if (pp->offset) {
3274de189feSMasami Hiramatsu 		ret = e_snprintf(offs, 64, "+%d", pp->offset);
3284de189feSMasami Hiramatsu 		if (ret <= 0)
3294de189feSMasami Hiramatsu 			goto error;
3304de189feSMasami Hiramatsu 	}
3314de189feSMasami Hiramatsu 	if (pp->line) {
3324de189feSMasami Hiramatsu 		ret = e_snprintf(line, 64, ":%d", pp->line);
3334de189feSMasami Hiramatsu 		if (ret <= 0)
3344de189feSMasami Hiramatsu 			goto error;
3354de189feSMasami Hiramatsu 	}
3364de189feSMasami Hiramatsu 
3374de189feSMasami Hiramatsu 	if (pp->function)
3384de189feSMasami Hiramatsu 		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function,
3394de189feSMasami Hiramatsu 				 offs, pp->retprobe ? "%return" : "", line);
3404de189feSMasami Hiramatsu 	else
34184988450SMasami Hiramatsu 		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line);
3427ef17aafSMasami Hiramatsu 	if (ret <= 0) {
3437ef17aafSMasami Hiramatsu error:
3447ef17aafSMasami Hiramatsu 		free(pp->probes[0]);
3457ef17aafSMasami Hiramatsu 		pp->probes[0] = NULL;
346388c3aabSMasami Hiramatsu 		pp->found = 0;
3477ef17aafSMasami Hiramatsu 	}
3487ef17aafSMasami Hiramatsu 	return ret;
3497ef17aafSMasami Hiramatsu }
35050656eecSMasami Hiramatsu 
3517ef17aafSMasami Hiramatsu int synthesize_perf_probe_event(struct probe_point *pp)
3527ef17aafSMasami Hiramatsu {
3537ef17aafSMasami Hiramatsu 	char *buf;
3547ef17aafSMasami Hiramatsu 	int i, len, ret;
3557ef17aafSMasami Hiramatsu 
3567ef17aafSMasami Hiramatsu 	len = synthesize_perf_probe_point(pp);
3577ef17aafSMasami Hiramatsu 	if (len < 0)
3587ef17aafSMasami Hiramatsu 		return 0;
3597ef17aafSMasami Hiramatsu 
3607ef17aafSMasami Hiramatsu 	buf = pp->probes[0];
36150656eecSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
3624de189feSMasami Hiramatsu 		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
36350656eecSMasami Hiramatsu 				 pp->args[i]);
3644de189feSMasami Hiramatsu 		if (ret <= 0)
36550656eecSMasami Hiramatsu 			goto error;
36650656eecSMasami Hiramatsu 		len += ret;
36750656eecSMasami Hiramatsu 	}
36850656eecSMasami Hiramatsu 	pp->found = 1;
36950656eecSMasami Hiramatsu 
37050656eecSMasami Hiramatsu 	return pp->found;
37150656eecSMasami Hiramatsu error:
37250656eecSMasami Hiramatsu 	free(pp->probes[0]);
3737ef17aafSMasami Hiramatsu 	pp->probes[0] = NULL;
37450656eecSMasami Hiramatsu 
37550656eecSMasami Hiramatsu 	return ret;
37650656eecSMasami Hiramatsu }
37750656eecSMasami Hiramatsu 
3784de189feSMasami Hiramatsu int synthesize_trace_kprobe_event(struct probe_point *pp)
3794de189feSMasami Hiramatsu {
3804de189feSMasami Hiramatsu 	char *buf;
3814de189feSMasami Hiramatsu 	int i, len, ret;
3824de189feSMasami Hiramatsu 
3834de189feSMasami Hiramatsu 	pp->probes[0] = buf = zalloc(MAX_CMDLEN);
3844de189feSMasami Hiramatsu 	if (!buf)
3854de189feSMasami Hiramatsu 		die("Failed to allocate memory by zalloc.");
3864de189feSMasami Hiramatsu 	ret = e_snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset);
3874de189feSMasami Hiramatsu 	if (ret <= 0)
3884de189feSMasami Hiramatsu 		goto error;
3894de189feSMasami Hiramatsu 	len = ret;
3904de189feSMasami Hiramatsu 
3914de189feSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
3924de189feSMasami Hiramatsu 		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
3934de189feSMasami Hiramatsu 				 pp->args[i]);
3944de189feSMasami Hiramatsu 		if (ret <= 0)
3954de189feSMasami Hiramatsu 			goto error;
3964de189feSMasami Hiramatsu 		len += ret;
3974de189feSMasami Hiramatsu 	}
3984de189feSMasami Hiramatsu 	pp->found = 1;
3994de189feSMasami Hiramatsu 
4004de189feSMasami Hiramatsu 	return pp->found;
4014de189feSMasami Hiramatsu error:
4024de189feSMasami Hiramatsu 	free(pp->probes[0]);
4037ef17aafSMasami Hiramatsu 	pp->probes[0] = NULL;
4044de189feSMasami Hiramatsu 
4054de189feSMasami Hiramatsu 	return ret;
4064de189feSMasami Hiramatsu }
4074de189feSMasami Hiramatsu 
4084de189feSMasami Hiramatsu static int open_kprobe_events(int flags, int mode)
4094de189feSMasami Hiramatsu {
4104de189feSMasami Hiramatsu 	char buf[PATH_MAX];
4114de189feSMasami Hiramatsu 	int ret;
4124de189feSMasami Hiramatsu 
4134de189feSMasami Hiramatsu 	ret = e_snprintf(buf, PATH_MAX, "%s/../kprobe_events", debugfs_path);
4144de189feSMasami Hiramatsu 	if (ret < 0)
4154de189feSMasami Hiramatsu 		die("Failed to make kprobe_events path.");
4164de189feSMasami Hiramatsu 
4174de189feSMasami Hiramatsu 	ret = open(buf, flags, mode);
4184de189feSMasami Hiramatsu 	if (ret < 0) {
4194de189feSMasami Hiramatsu 		if (errno == ENOENT)
4204de189feSMasami Hiramatsu 			die("kprobe_events file does not exist -"
42163bbd5e2SLiming Wang 			    " please rebuild with CONFIG_KPROBE_EVENT.");
4224de189feSMasami Hiramatsu 		else
4234de189feSMasami Hiramatsu 			die("Could not open kprobe_events file: %s",
4244de189feSMasami Hiramatsu 			    strerror(errno));
4254de189feSMasami Hiramatsu 	}
4264de189feSMasami Hiramatsu 	return ret;
4274de189feSMasami Hiramatsu }
4284de189feSMasami Hiramatsu 
4294de189feSMasami Hiramatsu /* Get raw string list of current kprobe_events */
4304de189feSMasami Hiramatsu static struct strlist *get_trace_kprobe_event_rawlist(int fd)
4314de189feSMasami Hiramatsu {
4324de189feSMasami Hiramatsu 	int ret, idx;
4334de189feSMasami Hiramatsu 	FILE *fp;
4344de189feSMasami Hiramatsu 	char buf[MAX_CMDLEN];
4354de189feSMasami Hiramatsu 	char *p;
4364de189feSMasami Hiramatsu 	struct strlist *sl;
4374de189feSMasami Hiramatsu 
4384de189feSMasami Hiramatsu 	sl = strlist__new(true, NULL);
4394de189feSMasami Hiramatsu 
4404de189feSMasami Hiramatsu 	fp = fdopen(dup(fd), "r");
4414de189feSMasami Hiramatsu 	while (!feof(fp)) {
4424de189feSMasami Hiramatsu 		p = fgets(buf, MAX_CMDLEN, fp);
4434de189feSMasami Hiramatsu 		if (!p)
4444de189feSMasami Hiramatsu 			break;
4454de189feSMasami Hiramatsu 
4464de189feSMasami Hiramatsu 		idx = strlen(p) - 1;
4474de189feSMasami Hiramatsu 		if (p[idx] == '\n')
4484de189feSMasami Hiramatsu 			p[idx] = '\0';
4494de189feSMasami Hiramatsu 		ret = strlist__add(sl, buf);
4504de189feSMasami Hiramatsu 		if (ret < 0)
4514de189feSMasami Hiramatsu 			die("strlist__add failed: %s", strerror(-ret));
4524de189feSMasami Hiramatsu 	}
4534de189feSMasami Hiramatsu 	fclose(fp);
4544de189feSMasami Hiramatsu 
4554de189feSMasami Hiramatsu 	return sl;
4564de189feSMasami Hiramatsu }
4574de189feSMasami Hiramatsu 
4584de189feSMasami Hiramatsu /* Free and zero clear probe_point */
4594de189feSMasami Hiramatsu static void clear_probe_point(struct probe_point *pp)
4604de189feSMasami Hiramatsu {
4614de189feSMasami Hiramatsu 	int i;
4624de189feSMasami Hiramatsu 
463af663d75SMasami Hiramatsu 	if (pp->event)
464af663d75SMasami Hiramatsu 		free(pp->event);
465af663d75SMasami Hiramatsu 	if (pp->group)
466af663d75SMasami Hiramatsu 		free(pp->group);
4674de189feSMasami Hiramatsu 	if (pp->function)
4684de189feSMasami Hiramatsu 		free(pp->function);
4694de189feSMasami Hiramatsu 	if (pp->file)
4704de189feSMasami Hiramatsu 		free(pp->file);
4712a9c8c36SMasami Hiramatsu 	if (pp->lazy_line)
4722a9c8c36SMasami Hiramatsu 		free(pp->lazy_line);
4734de189feSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++)
4744de189feSMasami Hiramatsu 		free(pp->args[i]);
4754de189feSMasami Hiramatsu 	if (pp->args)
4764de189feSMasami Hiramatsu 		free(pp->args);
4774de189feSMasami Hiramatsu 	for (i = 0; i < pp->found; i++)
4784de189feSMasami Hiramatsu 		free(pp->probes[i]);
4795660ce34SJulia Lawall 	memset(pp, 0, sizeof(*pp));
4804de189feSMasami Hiramatsu }
4814de189feSMasami Hiramatsu 
482278498d4SMasami Hiramatsu /* Show an event */
483af663d75SMasami Hiramatsu static void show_perf_probe_event(const char *event, const char *place,
484af663d75SMasami Hiramatsu 				  struct probe_point *pp)
485278498d4SMasami Hiramatsu {
4867e990a51SMasami Hiramatsu 	int i, ret;
487278498d4SMasami Hiramatsu 	char buf[128];
488278498d4SMasami Hiramatsu 
489af663d75SMasami Hiramatsu 	ret = e_snprintf(buf, 128, "%s:%s", pp->group, event);
4907e990a51SMasami Hiramatsu 	if (ret < 0)
4917e990a51SMasami Hiramatsu 		die("Failed to copy event: %s", strerror(-ret));
492278498d4SMasami Hiramatsu 	printf("  %-40s (on %s", buf, place);
493278498d4SMasami Hiramatsu 
494278498d4SMasami Hiramatsu 	if (pp->nr_args > 0) {
495278498d4SMasami Hiramatsu 		printf(" with");
496278498d4SMasami Hiramatsu 		for (i = 0; i < pp->nr_args; i++)
497278498d4SMasami Hiramatsu 			printf(" %s", pp->args[i]);
498278498d4SMasami Hiramatsu 	}
499278498d4SMasami Hiramatsu 	printf(")\n");
500278498d4SMasami Hiramatsu }
501278498d4SMasami Hiramatsu 
5024de189feSMasami Hiramatsu /* List up current perf-probe events */
5034de189feSMasami Hiramatsu void show_perf_probe_events(void)
5044de189feSMasami Hiramatsu {
5057ef17aafSMasami Hiramatsu 	int fd;
5064de189feSMasami Hiramatsu 	struct probe_point pp;
5074de189feSMasami Hiramatsu 	struct strlist *rawlist;
5084de189feSMasami Hiramatsu 	struct str_node *ent;
5094de189feSMasami Hiramatsu 
51072041334SMasami Hiramatsu 	setup_pager();
511388c3aabSMasami Hiramatsu 	memset(&pp, 0, sizeof(pp));
51272041334SMasami Hiramatsu 
5134de189feSMasami Hiramatsu 	fd = open_kprobe_events(O_RDONLY, 0);
5144de189feSMasami Hiramatsu 	rawlist = get_trace_kprobe_event_rawlist(fd);
5154de189feSMasami Hiramatsu 	close(fd);
5164de189feSMasami Hiramatsu 
517adf365f4SMasami Hiramatsu 	strlist__for_each(ent, rawlist) {
518af663d75SMasami Hiramatsu 		parse_trace_kprobe_event(ent->s, &pp);
519278498d4SMasami Hiramatsu 		/* Synthesize only event probe point */
5207ef17aafSMasami Hiramatsu 		synthesize_perf_probe_point(&pp);
521278498d4SMasami Hiramatsu 		/* Show an event */
522af663d75SMasami Hiramatsu 		show_perf_probe_event(pp.event, pp.probes[0], &pp);
5234de189feSMasami Hiramatsu 		clear_probe_point(&pp);
5244de189feSMasami Hiramatsu 	}
5254de189feSMasami Hiramatsu 
5264de189feSMasami Hiramatsu 	strlist__delete(rawlist);
5274de189feSMasami Hiramatsu }
5284de189feSMasami Hiramatsu 
529b498ce1fSMasami Hiramatsu /* Get current perf-probe event names */
530fa28244dSMasami Hiramatsu static struct strlist *get_perf_event_names(int fd, bool include_group)
531b498ce1fSMasami Hiramatsu {
532fa28244dSMasami Hiramatsu 	char buf[128];
533b498ce1fSMasami Hiramatsu 	struct strlist *sl, *rawlist;
534b498ce1fSMasami Hiramatsu 	struct str_node *ent;
535af663d75SMasami Hiramatsu 	struct probe_point pp;
536b498ce1fSMasami Hiramatsu 
537af663d75SMasami Hiramatsu 	memset(&pp, 0, sizeof(pp));
538b498ce1fSMasami Hiramatsu 	rawlist = get_trace_kprobe_event_rawlist(fd);
539b498ce1fSMasami Hiramatsu 
540e1d2017bSMasami Hiramatsu 	sl = strlist__new(true, NULL);
541adf365f4SMasami Hiramatsu 	strlist__for_each(ent, rawlist) {
542af663d75SMasami Hiramatsu 		parse_trace_kprobe_event(ent->s, &pp);
543fa28244dSMasami Hiramatsu 		if (include_group) {
544af663d75SMasami Hiramatsu 			if (e_snprintf(buf, 128, "%s:%s", pp.group,
545af663d75SMasami Hiramatsu 				       pp.event) < 0)
546fa28244dSMasami Hiramatsu 				die("Failed to copy group:event name.");
547fa28244dSMasami Hiramatsu 			strlist__add(sl, buf);
548fa28244dSMasami Hiramatsu 		} else
549af663d75SMasami Hiramatsu 			strlist__add(sl, pp.event);
550af663d75SMasami Hiramatsu 		clear_probe_point(&pp);
551b498ce1fSMasami Hiramatsu 	}
552b498ce1fSMasami Hiramatsu 
553b498ce1fSMasami Hiramatsu 	strlist__delete(rawlist);
554b498ce1fSMasami Hiramatsu 
555b498ce1fSMasami Hiramatsu 	return sl;
556b498ce1fSMasami Hiramatsu }
557b498ce1fSMasami Hiramatsu 
558a9b495b0SMasami Hiramatsu static void write_trace_kprobe_event(int fd, const char *buf)
55950656eecSMasami Hiramatsu {
56050656eecSMasami Hiramatsu 	int ret;
56150656eecSMasami Hiramatsu 
562fa28244dSMasami Hiramatsu 	pr_debug("Writing event: %s\n", buf);
56350656eecSMasami Hiramatsu 	ret = write(fd, buf, strlen(buf));
56450656eecSMasami Hiramatsu 	if (ret <= 0)
565fa28244dSMasami Hiramatsu 		die("Failed to write event: %s", strerror(errno));
56650656eecSMasami Hiramatsu }
56750656eecSMasami Hiramatsu 
568b498ce1fSMasami Hiramatsu static void get_new_event_name(char *buf, size_t len, const char *base,
569d761b08bSMasami Hiramatsu 			       struct strlist *namelist, bool allow_suffix)
570b498ce1fSMasami Hiramatsu {
571b498ce1fSMasami Hiramatsu 	int i, ret;
57217f88fcdSMasami Hiramatsu 
57317f88fcdSMasami Hiramatsu 	/* Try no suffix */
57417f88fcdSMasami Hiramatsu 	ret = e_snprintf(buf, len, "%s", base);
57517f88fcdSMasami Hiramatsu 	if (ret < 0)
57617f88fcdSMasami Hiramatsu 		die("snprintf() failed: %s", strerror(-ret));
57717f88fcdSMasami Hiramatsu 	if (!strlist__has_entry(namelist, buf))
57817f88fcdSMasami Hiramatsu 		return;
57917f88fcdSMasami Hiramatsu 
580d761b08bSMasami Hiramatsu 	if (!allow_suffix) {
581d761b08bSMasami Hiramatsu 		pr_warning("Error: event \"%s\" already exists. "
582d761b08bSMasami Hiramatsu 			   "(Use -f to force duplicates.)\n", base);
583d761b08bSMasami Hiramatsu 		die("Can't add new event.");
584d761b08bSMasami Hiramatsu 	}
585d761b08bSMasami Hiramatsu 
58617f88fcdSMasami Hiramatsu 	/* Try to add suffix */
58717f88fcdSMasami Hiramatsu 	for (i = 1; i < MAX_EVENT_INDEX; i++) {
588b498ce1fSMasami Hiramatsu 		ret = e_snprintf(buf, len, "%s_%d", base, i);
589b498ce1fSMasami Hiramatsu 		if (ret < 0)
590b498ce1fSMasami Hiramatsu 			die("snprintf() failed: %s", strerror(-ret));
591b498ce1fSMasami Hiramatsu 		if (!strlist__has_entry(namelist, buf))
592b498ce1fSMasami Hiramatsu 			break;
593b498ce1fSMasami Hiramatsu 	}
594b498ce1fSMasami Hiramatsu 	if (i == MAX_EVENT_INDEX)
595b498ce1fSMasami Hiramatsu 		die("Too many events are on the same function.");
596b498ce1fSMasami Hiramatsu }
597b498ce1fSMasami Hiramatsu 
598d761b08bSMasami Hiramatsu void add_trace_kprobe_events(struct probe_point *probes, int nr_probes,
599d761b08bSMasami Hiramatsu 			     bool force_add)
60050656eecSMasami Hiramatsu {
60150656eecSMasami Hiramatsu 	int i, j, fd;
60250656eecSMasami Hiramatsu 	struct probe_point *pp;
60350656eecSMasami Hiramatsu 	char buf[MAX_CMDLEN];
604b498ce1fSMasami Hiramatsu 	char event[64];
605b498ce1fSMasami Hiramatsu 	struct strlist *namelist;
606d761b08bSMasami Hiramatsu 	bool allow_suffix;
60750656eecSMasami Hiramatsu 
608b498ce1fSMasami Hiramatsu 	fd = open_kprobe_events(O_RDWR, O_APPEND);
609b498ce1fSMasami Hiramatsu 	/* Get current event names */
610fa28244dSMasami Hiramatsu 	namelist = get_perf_event_names(fd, false);
61150656eecSMasami Hiramatsu 
61250656eecSMasami Hiramatsu 	for (j = 0; j < nr_probes; j++) {
61350656eecSMasami Hiramatsu 		pp = probes + j;
614af663d75SMasami Hiramatsu 		if (!pp->event)
615af663d75SMasami Hiramatsu 			pp->event = strdup(pp->function);
616af663d75SMasami Hiramatsu 		if (!pp->group)
617af663d75SMasami Hiramatsu 			pp->group = strdup(PERFPROBE_GROUP);
618af663d75SMasami Hiramatsu 		DIE_IF(!pp->event || !pp->group);
619d761b08bSMasami Hiramatsu 		/* If force_add is true, suffix search is allowed */
620d761b08bSMasami Hiramatsu 		allow_suffix = force_add;
62150656eecSMasami Hiramatsu 		for (i = 0; i < pp->found; i++) {
622b498ce1fSMasami Hiramatsu 			/* Get an unused new event name */
623d761b08bSMasami Hiramatsu 			get_new_event_name(event, 64, pp->event, namelist,
624d761b08bSMasami Hiramatsu 					   allow_suffix);
625b498ce1fSMasami Hiramatsu 			snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n",
62650656eecSMasami Hiramatsu 				 pp->retprobe ? 'r' : 'p',
627af663d75SMasami Hiramatsu 				 pp->group, event,
62850656eecSMasami Hiramatsu 				 pp->probes[i]);
62950656eecSMasami Hiramatsu 			write_trace_kprobe_event(fd, buf);
630a9b495b0SMasami Hiramatsu 			printf("Added new event:\n");
631a9b495b0SMasami Hiramatsu 			/* Get the first parameter (probe-point) */
632a9b495b0SMasami Hiramatsu 			sscanf(pp->probes[i], "%s", buf);
633af663d75SMasami Hiramatsu 			show_perf_probe_event(event, buf, pp);
634b498ce1fSMasami Hiramatsu 			/* Add added event name to namelist */
635b498ce1fSMasami Hiramatsu 			strlist__add(namelist, event);
636d761b08bSMasami Hiramatsu 			/*
637d761b08bSMasami Hiramatsu 			 * Probes after the first probe which comes from same
638d761b08bSMasami Hiramatsu 			 * user input are always allowed to add suffix, because
639d761b08bSMasami Hiramatsu 			 * there might be several addresses corresponding to
640d761b08bSMasami Hiramatsu 			 * one code line.
641d761b08bSMasami Hiramatsu 			 */
642d761b08bSMasami Hiramatsu 			allow_suffix = true;
64350656eecSMasami Hiramatsu 		}
64450656eecSMasami Hiramatsu 	}
645a9b495b0SMasami Hiramatsu 	/* Show how to use the event. */
646a9b495b0SMasami Hiramatsu 	printf("\nYou can now use it on all perf tools, such as:\n\n");
647a9b495b0SMasami Hiramatsu 	printf("\tperf record -e %s:%s -a sleep 1\n\n", PERFPROBE_GROUP, event);
648a9b495b0SMasami Hiramatsu 
649e1d2017bSMasami Hiramatsu 	strlist__delete(namelist);
65050656eecSMasami Hiramatsu 	close(fd);
65150656eecSMasami Hiramatsu }
652fa28244dSMasami Hiramatsu 
653bbbb521bSMasami Hiramatsu static void __del_trace_kprobe_event(int fd, struct str_node *ent)
654bbbb521bSMasami Hiramatsu {
655bbbb521bSMasami Hiramatsu 	char *p;
656bbbb521bSMasami Hiramatsu 	char buf[128];
657bbbb521bSMasami Hiramatsu 
658bbbb521bSMasami Hiramatsu 	/* Convert from perf-probe event to trace-kprobe event */
659bbbb521bSMasami Hiramatsu 	if (e_snprintf(buf, 128, "-:%s", ent->s) < 0)
660bbbb521bSMasami Hiramatsu 		die("Failed to copy event.");
661bbbb521bSMasami Hiramatsu 	p = strchr(buf + 2, ':');
662bbbb521bSMasami Hiramatsu 	if (!p)
663bbbb521bSMasami Hiramatsu 		die("Internal error: %s should have ':' but not.", ent->s);
664bbbb521bSMasami Hiramatsu 	*p = '/';
665bbbb521bSMasami Hiramatsu 
666bbbb521bSMasami Hiramatsu 	write_trace_kprobe_event(fd, buf);
667bbbb521bSMasami Hiramatsu 	printf("Remove event: %s\n", ent->s);
668bbbb521bSMasami Hiramatsu }
669bbbb521bSMasami Hiramatsu 
670fa28244dSMasami Hiramatsu static void del_trace_kprobe_event(int fd, const char *group,
671fa28244dSMasami Hiramatsu 				   const char *event, struct strlist *namelist)
672fa28244dSMasami Hiramatsu {
673fa28244dSMasami Hiramatsu 	char buf[128];
674bbbb521bSMasami Hiramatsu 	struct str_node *ent, *n;
675bbbb521bSMasami Hiramatsu 	int found = 0;
676fa28244dSMasami Hiramatsu 
677fa28244dSMasami Hiramatsu 	if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
678fa28244dSMasami Hiramatsu 		die("Failed to copy event.");
679fa28244dSMasami Hiramatsu 
680bbbb521bSMasami Hiramatsu 	if (strpbrk(buf, "*?")) { /* Glob-exp */
681bbbb521bSMasami Hiramatsu 		strlist__for_each_safe(ent, n, namelist)
682bbbb521bSMasami Hiramatsu 			if (strglobmatch(ent->s, buf)) {
683bbbb521bSMasami Hiramatsu 				found++;
684bbbb521bSMasami Hiramatsu 				__del_trace_kprobe_event(fd, ent);
6853e340590SMasami Hiramatsu 				strlist__remove(namelist, ent);
686fa28244dSMasami Hiramatsu 			}
687bbbb521bSMasami Hiramatsu 	} else {
688bbbb521bSMasami Hiramatsu 		ent = strlist__find(namelist, buf);
689bbbb521bSMasami Hiramatsu 		if (ent) {
690bbbb521bSMasami Hiramatsu 			found++;
691bbbb521bSMasami Hiramatsu 			__del_trace_kprobe_event(fd, ent);
692bbbb521bSMasami Hiramatsu 			strlist__remove(namelist, ent);
693bbbb521bSMasami Hiramatsu 		}
694bbbb521bSMasami Hiramatsu 	}
695bbbb521bSMasami Hiramatsu 	if (found == 0)
696bbbb521bSMasami Hiramatsu 		pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf);
697bbbb521bSMasami Hiramatsu }
698fa28244dSMasami Hiramatsu 
699fa28244dSMasami Hiramatsu void del_trace_kprobe_events(struct strlist *dellist)
700fa28244dSMasami Hiramatsu {
701fa28244dSMasami Hiramatsu 	int fd;
702fa28244dSMasami Hiramatsu 	const char *group, *event;
703fa28244dSMasami Hiramatsu 	char *p, *str;
704fa28244dSMasami Hiramatsu 	struct str_node *ent;
705fa28244dSMasami Hiramatsu 	struct strlist *namelist;
706fa28244dSMasami Hiramatsu 
707fa28244dSMasami Hiramatsu 	fd = open_kprobe_events(O_RDWR, O_APPEND);
708fa28244dSMasami Hiramatsu 	/* Get current event names */
709fa28244dSMasami Hiramatsu 	namelist = get_perf_event_names(fd, true);
710fa28244dSMasami Hiramatsu 
711adf365f4SMasami Hiramatsu 	strlist__for_each(ent, dellist) {
712fa28244dSMasami Hiramatsu 		str = strdup(ent->s);
713fa28244dSMasami Hiramatsu 		if (!str)
714fa28244dSMasami Hiramatsu 			die("Failed to copy event.");
715bbbb521bSMasami Hiramatsu 		pr_debug("Parsing: %s\n", str);
716fa28244dSMasami Hiramatsu 		p = strchr(str, ':');
717fa28244dSMasami Hiramatsu 		if (p) {
718fa28244dSMasami Hiramatsu 			group = str;
719fa28244dSMasami Hiramatsu 			*p = '\0';
720fa28244dSMasami Hiramatsu 			event = p + 1;
721fa28244dSMasami Hiramatsu 		} else {
722bbbb521bSMasami Hiramatsu 			group = "*";
723fa28244dSMasami Hiramatsu 			event = str;
724fa28244dSMasami Hiramatsu 		}
725bbbb521bSMasami Hiramatsu 		pr_debug("Group: %s, Event: %s\n", group, event);
726fa28244dSMasami Hiramatsu 		del_trace_kprobe_event(fd, group, event, namelist);
727fa28244dSMasami Hiramatsu 		free(str);
728fa28244dSMasami Hiramatsu 	}
729fa28244dSMasami Hiramatsu 	strlist__delete(namelist);
730fa28244dSMasami Hiramatsu 	close(fd);
731fa28244dSMasami Hiramatsu }
732fa28244dSMasami Hiramatsu 
733631c9defSMasami Hiramatsu #define LINEBUF_SIZE 256
7345c8d1cbbSMasami Hiramatsu #define NR_ADDITIONAL_LINES 2
735631c9defSMasami Hiramatsu 
736631c9defSMasami Hiramatsu static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num)
737631c9defSMasami Hiramatsu {
738631c9defSMasami Hiramatsu 	char buf[LINEBUF_SIZE];
739631c9defSMasami Hiramatsu 	const char *color = PERF_COLOR_BLUE;
740631c9defSMasami Hiramatsu 
741631c9defSMasami Hiramatsu 	if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
742631c9defSMasami Hiramatsu 		goto error;
743631c9defSMasami Hiramatsu 	if (!skip) {
744631c9defSMasami Hiramatsu 		if (show_num)
745631c9defSMasami Hiramatsu 			fprintf(stdout, "%7u  %s", l, buf);
746631c9defSMasami Hiramatsu 		else
747631c9defSMasami Hiramatsu 			color_fprintf(stdout, color, "         %s", buf);
748631c9defSMasami Hiramatsu 	}
749631c9defSMasami Hiramatsu 
750631c9defSMasami Hiramatsu 	while (strlen(buf) == LINEBUF_SIZE - 1 &&
751631c9defSMasami Hiramatsu 	       buf[LINEBUF_SIZE - 2] != '\n') {
752631c9defSMasami Hiramatsu 		if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
753631c9defSMasami Hiramatsu 			goto error;
754631c9defSMasami Hiramatsu 		if (!skip) {
755631c9defSMasami Hiramatsu 			if (show_num)
756631c9defSMasami Hiramatsu 				fprintf(stdout, "%s", buf);
757631c9defSMasami Hiramatsu 			else
758631c9defSMasami Hiramatsu 				color_fprintf(stdout, color, "%s", buf);
759631c9defSMasami Hiramatsu 		}
760631c9defSMasami Hiramatsu 	}
761631c9defSMasami Hiramatsu 	return;
762631c9defSMasami Hiramatsu error:
763631c9defSMasami Hiramatsu 	if (feof(fp))
764631c9defSMasami Hiramatsu 		die("Source file is shorter than expected.");
765631c9defSMasami Hiramatsu 	else
766631c9defSMasami Hiramatsu 		die("File read error: %s", strerror(errno));
767631c9defSMasami Hiramatsu }
768631c9defSMasami Hiramatsu 
769631c9defSMasami Hiramatsu void show_line_range(struct line_range *lr)
770631c9defSMasami Hiramatsu {
771631c9defSMasami Hiramatsu 	unsigned int l = 1;
772631c9defSMasami Hiramatsu 	struct line_node *ln;
773631c9defSMasami Hiramatsu 	FILE *fp;
774631c9defSMasami Hiramatsu 
775631c9defSMasami Hiramatsu 	setup_pager();
776631c9defSMasami Hiramatsu 
777631c9defSMasami Hiramatsu 	if (lr->function)
778631c9defSMasami Hiramatsu 		fprintf(stdout, "<%s:%d>\n", lr->function,
779631c9defSMasami Hiramatsu 			lr->start - lr->offset);
780631c9defSMasami Hiramatsu 	else
781631c9defSMasami Hiramatsu 		fprintf(stdout, "<%s:%d>\n", lr->file, lr->start);
782631c9defSMasami Hiramatsu 
783631c9defSMasami Hiramatsu 	fp = fopen(lr->path, "r");
784631c9defSMasami Hiramatsu 	if (fp == NULL)
785631c9defSMasami Hiramatsu 		die("Failed to open %s: %s", lr->path, strerror(errno));
786631c9defSMasami Hiramatsu 	/* Skip to starting line number */
787631c9defSMasami Hiramatsu 	while (l < lr->start)
788631c9defSMasami Hiramatsu 		show_one_line(fp, l++, true, false);
789631c9defSMasami Hiramatsu 
790631c9defSMasami Hiramatsu 	list_for_each_entry(ln, &lr->line_list, list) {
791631c9defSMasami Hiramatsu 		while (ln->line > l)
792631c9defSMasami Hiramatsu 			show_one_line(fp, (l++) - lr->offset, false, false);
793631c9defSMasami Hiramatsu 		show_one_line(fp, (l++) - lr->offset, false, true);
794631c9defSMasami Hiramatsu 	}
7955c8d1cbbSMasami Hiramatsu 
7965c8d1cbbSMasami Hiramatsu 	if (lr->end == INT_MAX)
7975c8d1cbbSMasami Hiramatsu 		lr->end = l + NR_ADDITIONAL_LINES;
7985c8d1cbbSMasami Hiramatsu 	while (l < lr->end && !feof(fp))
7995c8d1cbbSMasami Hiramatsu 		show_one_line(fp, (l++) - lr->offset, false, false);
8005c8d1cbbSMasami Hiramatsu 
801631c9defSMasami Hiramatsu 	fclose(fp);
802631c9defSMasami Hiramatsu }
803