xref: /linux/tools/perf/util/probe-event.c (revision 31facc5f1ac674fbcc29f212377e589396bb934c)
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
36*31facc5fSMasami Hiramatsu #include "util.h"
3750656eecSMasami Hiramatsu #include "event.h"
38e1c01d61SMasami Hiramatsu #include "string.h"
394de189feSMasami Hiramatsu #include "strlist.h"
4050656eecSMasami Hiramatsu #include "debug.h"
4172041334SMasami Hiramatsu #include "cache.h"
42631c9defSMasami Hiramatsu #include "color.h"
4350656eecSMasami Hiramatsu #include "parse-events.h"  /* For debugfs_path */
4450656eecSMasami Hiramatsu #include "probe-event.h"
4550656eecSMasami Hiramatsu 
4650656eecSMasami Hiramatsu #define MAX_CMDLEN 256
4750656eecSMasami Hiramatsu #define MAX_PROBE_ARGS 128
4850656eecSMasami Hiramatsu #define PERFPROBE_GROUP "probe"
4950656eecSMasami Hiramatsu 
5050656eecSMasami Hiramatsu #define semantic_error(msg ...) die("Semantic error :" msg)
5150656eecSMasami Hiramatsu 
524de189feSMasami Hiramatsu /* If there is no space to write, returns -E2BIG. */
534de189feSMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...)
5484988450SMasami Hiramatsu 	__attribute__((format(printf, 3, 4)));
5584988450SMasami Hiramatsu 
5684988450SMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...)
574de189feSMasami Hiramatsu {
584de189feSMasami Hiramatsu 	int ret;
594de189feSMasami Hiramatsu 	va_list ap;
604de189feSMasami Hiramatsu 	va_start(ap, format);
614de189feSMasami Hiramatsu 	ret = vsnprintf(str, size, format, ap);
624de189feSMasami Hiramatsu 	va_end(ap);
634de189feSMasami Hiramatsu 	if (ret >= (int)size)
644de189feSMasami Hiramatsu 		ret = -E2BIG;
654de189feSMasami Hiramatsu 	return ret;
664de189feSMasami Hiramatsu }
674de189feSMasami Hiramatsu 
68631c9defSMasami Hiramatsu void parse_line_range_desc(const char *arg, struct line_range *lr)
69631c9defSMasami Hiramatsu {
70631c9defSMasami Hiramatsu 	const char *ptr;
71631c9defSMasami Hiramatsu 	char *tmp;
72631c9defSMasami Hiramatsu 	/*
73631c9defSMasami Hiramatsu 	 * <Syntax>
74631c9defSMasami Hiramatsu 	 * SRC:SLN[+NUM|-ELN]
75631c9defSMasami Hiramatsu 	 * FUNC[:SLN[+NUM|-ELN]]
76631c9defSMasami Hiramatsu 	 */
77631c9defSMasami Hiramatsu 	ptr = strchr(arg, ':');
78631c9defSMasami Hiramatsu 	if (ptr) {
79631c9defSMasami Hiramatsu 		lr->start = (unsigned int)strtoul(ptr + 1, &tmp, 0);
80631c9defSMasami Hiramatsu 		if (*tmp == '+')
81631c9defSMasami Hiramatsu 			lr->end = lr->start + (unsigned int)strtoul(tmp + 1,
82631c9defSMasami Hiramatsu 								    &tmp, 0);
83631c9defSMasami Hiramatsu 		else if (*tmp == '-')
84631c9defSMasami Hiramatsu 			lr->end = (unsigned int)strtoul(tmp + 1, &tmp, 0);
85631c9defSMasami Hiramatsu 		else
86631c9defSMasami Hiramatsu 			lr->end = 0;
87631c9defSMasami Hiramatsu 		pr_debug("Line range is %u to %u\n", lr->start, lr->end);
88631c9defSMasami Hiramatsu 		if (lr->end && lr->start > lr->end)
89631c9defSMasami Hiramatsu 			semantic_error("Start line must be smaller"
90631c9defSMasami Hiramatsu 				       " than end line.");
91631c9defSMasami Hiramatsu 		if (*tmp != '\0')
92631c9defSMasami Hiramatsu 			semantic_error("Tailing with invalid character '%d'.",
93631c9defSMasami Hiramatsu 				       *tmp);
94*31facc5fSMasami Hiramatsu 		tmp = xstrndup(arg, (ptr - arg));
95631c9defSMasami Hiramatsu 	} else
96*31facc5fSMasami Hiramatsu 		tmp = xstrdup(arg);
97631c9defSMasami Hiramatsu 
98631c9defSMasami Hiramatsu 	if (strchr(tmp, '.'))
99631c9defSMasami Hiramatsu 		lr->file = tmp;
100631c9defSMasami Hiramatsu 	else
101631c9defSMasami Hiramatsu 		lr->function = tmp;
102631c9defSMasami Hiramatsu }
103631c9defSMasami Hiramatsu 
104b7702a21SMasami Hiramatsu /* Check the name is good for event/group */
105b7702a21SMasami Hiramatsu static bool check_event_name(const char *name)
106b7702a21SMasami Hiramatsu {
107b7702a21SMasami Hiramatsu 	if (!isalpha(*name) && *name != '_')
108b7702a21SMasami Hiramatsu 		return false;
109b7702a21SMasami Hiramatsu 	while (*++name != '\0') {
110b7702a21SMasami Hiramatsu 		if (!isalpha(*name) && !isdigit(*name) && *name != '_')
111b7702a21SMasami Hiramatsu 			return false;
112b7702a21SMasami Hiramatsu 	}
113b7702a21SMasami Hiramatsu 	return true;
114b7702a21SMasami Hiramatsu }
115b7702a21SMasami Hiramatsu 
11650656eecSMasami Hiramatsu /* Parse probepoint definition. */
11750656eecSMasami Hiramatsu static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
11850656eecSMasami Hiramatsu {
11950656eecSMasami Hiramatsu 	char *ptr, *tmp;
12050656eecSMasami Hiramatsu 	char c, nc = 0;
12150656eecSMasami Hiramatsu 	/*
12250656eecSMasami Hiramatsu 	 * <Syntax>
1232a9c8c36SMasami Hiramatsu 	 * perf probe [EVENT=]SRC[:LN|;PTN]
1242a9c8c36SMasami Hiramatsu 	 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
125af663d75SMasami Hiramatsu 	 *
126af663d75SMasami Hiramatsu 	 * TODO:Group name support
12750656eecSMasami Hiramatsu 	 */
12850656eecSMasami Hiramatsu 
1292a9c8c36SMasami Hiramatsu 	ptr = strpbrk(arg, ";=@+%");
1302a9c8c36SMasami Hiramatsu 	if (ptr && *ptr == '=') {	/* Event name */
131af663d75SMasami Hiramatsu 		*ptr = '\0';
132af663d75SMasami Hiramatsu 		tmp = ptr + 1;
133af663d75SMasami Hiramatsu 		ptr = strchr(arg, ':');
134af663d75SMasami Hiramatsu 		if (ptr)	/* Group name is not supported yet. */
135af663d75SMasami Hiramatsu 			semantic_error("Group name is not supported yet.");
136b7702a21SMasami Hiramatsu 		if (!check_event_name(arg))
137b7702a21SMasami Hiramatsu 			semantic_error("%s is bad for event name -it must "
138b7702a21SMasami Hiramatsu 				       "follow C symbol-naming rule.", arg);
139*31facc5fSMasami Hiramatsu 		pp->event = xstrdup(arg);
140af663d75SMasami Hiramatsu 		arg = tmp;
141af663d75SMasami Hiramatsu 	}
142af663d75SMasami Hiramatsu 
1432a9c8c36SMasami Hiramatsu 	ptr = strpbrk(arg, ";:+@%");
14450656eecSMasami Hiramatsu 	if (ptr) {
14550656eecSMasami Hiramatsu 		nc = *ptr;
14650656eecSMasami Hiramatsu 		*ptr++ = '\0';
14750656eecSMasami Hiramatsu 	}
14850656eecSMasami Hiramatsu 
14950656eecSMasami Hiramatsu 	/* Check arg is function or file and copy it */
15050656eecSMasami Hiramatsu 	if (strchr(arg, '.'))	/* File */
151*31facc5fSMasami Hiramatsu 		pp->file = xstrdup(arg);
15250656eecSMasami Hiramatsu 	else			/* Function */
153*31facc5fSMasami Hiramatsu 		pp->function = xstrdup(arg);
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 */
160*31facc5fSMasami Hiramatsu 			pp->lazy_line = xstrdup(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.");
184*31facc5fSMasami Hiramatsu 			pp->file = xstrdup(arg);
18550656eecSMasami Hiramatsu 			break;
18650656eecSMasami Hiramatsu 		case '%':	/* Probe places */
18750656eecSMasami Hiramatsu 			if (strcmp(arg, "return") == 0) {
18850656eecSMasami Hiramatsu 				pp->retprobe = 1;
18950656eecSMasami Hiramatsu 			} else	/* Others not supported yet */
19050656eecSMasami Hiramatsu 				semantic_error("%%%s is not supported.", arg);
19150656eecSMasami Hiramatsu 			break;
19250656eecSMasami Hiramatsu 		default:
19350656eecSMasami Hiramatsu 			DIE_IF("Program has a bug.");
19450656eecSMasami Hiramatsu 			break;
19550656eecSMasami Hiramatsu 		}
19650656eecSMasami Hiramatsu 	}
19750656eecSMasami Hiramatsu 
19850656eecSMasami Hiramatsu 	/* Exclusion check */
1992a9c8c36SMasami Hiramatsu 	if (pp->lazy_line && pp->line)
2002a9c8c36SMasami Hiramatsu 		semantic_error("Lazy pattern can't be used with line number.");
2012a9c8c36SMasami Hiramatsu 
2022a9c8c36SMasami Hiramatsu 	if (pp->lazy_line && pp->offset)
2032a9c8c36SMasami Hiramatsu 		semantic_error("Lazy pattern can't be used with offset.");
2042a9c8c36SMasami Hiramatsu 
20550656eecSMasami Hiramatsu 	if (pp->line && pp->offset)
20650656eecSMasami Hiramatsu 		semantic_error("Offset can't be used with line number.");
20750656eecSMasami Hiramatsu 
2082a9c8c36SMasami Hiramatsu 	if (!pp->line && !pp->lazy_line && pp->file && !pp->function)
2092a9c8c36SMasami Hiramatsu 		semantic_error("File always requires line number or "
2102a9c8c36SMasami Hiramatsu 			       "lazy pattern.");
21150656eecSMasami Hiramatsu 
21250656eecSMasami Hiramatsu 	if (pp->offset && !pp->function)
21350656eecSMasami Hiramatsu 		semantic_error("Offset requires an entry function.");
21450656eecSMasami Hiramatsu 
21550656eecSMasami Hiramatsu 	if (pp->retprobe && !pp->function)
21650656eecSMasami Hiramatsu 		semantic_error("Return probe requires an entry function.");
21750656eecSMasami Hiramatsu 
2182a9c8c36SMasami Hiramatsu 	if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe)
2192a9c8c36SMasami Hiramatsu 		semantic_error("Offset/Line/Lazy pattern can't be used with "
2202a9c8c36SMasami Hiramatsu 			       "return probe.");
22150656eecSMasami Hiramatsu 
2222a9c8c36SMasami Hiramatsu 	pr_debug("symbol:%s file:%s line:%d offset:%d return:%d lazy:%s\n",
2232a9c8c36SMasami Hiramatsu 		 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
2242a9c8c36SMasami Hiramatsu 		 pp->lazy_line);
22550656eecSMasami Hiramatsu }
22650656eecSMasami Hiramatsu 
22750656eecSMasami Hiramatsu /* Parse perf-probe event definition */
228fac13fd5SMasami Hiramatsu void parse_perf_probe_event(const char *str, struct probe_point *pp,
229fac13fd5SMasami Hiramatsu 			    bool *need_dwarf)
23050656eecSMasami Hiramatsu {
231e1c01d61SMasami Hiramatsu 	char **argv;
232fac13fd5SMasami Hiramatsu 	int argc, i;
233fac13fd5SMasami Hiramatsu 
234fac13fd5SMasami Hiramatsu 	*need_dwarf = false;
23550656eecSMasami Hiramatsu 
236e1c01d61SMasami Hiramatsu 	argv = argv_split(str, &argc);
237e1c01d61SMasami Hiramatsu 	if (!argv)
238e1c01d61SMasami Hiramatsu 		die("argv_split failed.");
239e1c01d61SMasami Hiramatsu 	if (argc > MAX_PROBE_ARGS + 1)
24050656eecSMasami Hiramatsu 		semantic_error("Too many arguments");
24150656eecSMasami Hiramatsu 
24250656eecSMasami Hiramatsu 	/* Parse probe point */
24350656eecSMasami Hiramatsu 	parse_perf_probe_probepoint(argv[0], pp);
244fc6ceea0SMasami Hiramatsu 	if (pp->file || pp->line || pp->lazy_line)
245fac13fd5SMasami Hiramatsu 		*need_dwarf = true;
24650656eecSMasami Hiramatsu 
247e1c01d61SMasami Hiramatsu 	/* Copy arguments and ensure return probe has no C argument */
24850656eecSMasami Hiramatsu 	pp->nr_args = argc - 1;
249*31facc5fSMasami Hiramatsu 	pp->args = xzalloc(sizeof(char *) * pp->nr_args);
250e1c01d61SMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
251*31facc5fSMasami Hiramatsu 		pp->args[i] = xstrdup(argv[i + 1]);
25250656eecSMasami Hiramatsu 		if (is_c_varname(pp->args[i])) {
25350656eecSMasami Hiramatsu 			if (pp->retprobe)
25450656eecSMasami Hiramatsu 				semantic_error("You can't specify local"
25550656eecSMasami Hiramatsu 						" variable for kretprobe");
256fac13fd5SMasami Hiramatsu 			*need_dwarf = true;
25750656eecSMasami Hiramatsu 		}
258e1c01d61SMasami Hiramatsu 	}
25950656eecSMasami Hiramatsu 
260e1c01d61SMasami Hiramatsu 	argv_free(argv);
26150656eecSMasami Hiramatsu }
26250656eecSMasami Hiramatsu 
2634de189feSMasami Hiramatsu /* Parse kprobe_events event into struct probe_point */
264af663d75SMasami Hiramatsu void parse_trace_kprobe_event(const char *str, struct probe_point *pp)
2654de189feSMasami Hiramatsu {
2664de189feSMasami Hiramatsu 	char pr;
2674de189feSMasami Hiramatsu 	char *p;
2684de189feSMasami Hiramatsu 	int ret, i, argc;
2694de189feSMasami Hiramatsu 	char **argv;
2704de189feSMasami Hiramatsu 
2714de189feSMasami Hiramatsu 	pr_debug("Parsing kprobe_events: %s\n", str);
2724de189feSMasami Hiramatsu 	argv = argv_split(str, &argc);
2734de189feSMasami Hiramatsu 	if (!argv)
2744de189feSMasami Hiramatsu 		die("argv_split failed.");
2754de189feSMasami Hiramatsu 	if (argc < 2)
2764de189feSMasami Hiramatsu 		semantic_error("Too less arguments.");
2774de189feSMasami Hiramatsu 
2784de189feSMasami Hiramatsu 	/* Scan event and group name. */
27993aaa45aSLiming Wang 	ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
280af663d75SMasami Hiramatsu 		     &pr, (float *)(void *)&pp->group,
281af663d75SMasami Hiramatsu 		     (float *)(void *)&pp->event);
2824de189feSMasami Hiramatsu 	if (ret != 3)
2834de189feSMasami Hiramatsu 		semantic_error("Failed to parse event name: %s", argv[0]);
284af663d75SMasami Hiramatsu 	pr_debug("Group:%s Event:%s probe:%c\n", pp->group, pp->event, pr);
2854de189feSMasami Hiramatsu 
2864de189feSMasami Hiramatsu 	pp->retprobe = (pr == 'r');
2874de189feSMasami Hiramatsu 
2884de189feSMasami Hiramatsu 	/* Scan function name and offset */
289af663d75SMasami Hiramatsu 	ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function,
290af663d75SMasami Hiramatsu 		     &pp->offset);
2914de189feSMasami Hiramatsu 	if (ret == 1)
2924de189feSMasami Hiramatsu 		pp->offset = 0;
2934de189feSMasami Hiramatsu 
2944de189feSMasami Hiramatsu 	/* kprobe_events doesn't have this information */
2954de189feSMasami Hiramatsu 	pp->line = 0;
2964de189feSMasami Hiramatsu 	pp->file = NULL;
2974de189feSMasami Hiramatsu 
2984de189feSMasami Hiramatsu 	pp->nr_args = argc - 2;
299*31facc5fSMasami Hiramatsu 	pp->args = xzalloc(sizeof(char *) * pp->nr_args);
3004de189feSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
3014de189feSMasami Hiramatsu 		p = strchr(argv[i + 2], '=');
3024de189feSMasami Hiramatsu 		if (p)	/* We don't need which register is assigned. */
3034de189feSMasami Hiramatsu 			*p = '\0';
304*31facc5fSMasami Hiramatsu 		pp->args[i] = xstrdup(argv[i + 2]);
3054de189feSMasami Hiramatsu 	}
3064de189feSMasami Hiramatsu 
3074de189feSMasami Hiramatsu 	argv_free(argv);
3084de189feSMasami Hiramatsu }
3094de189feSMasami Hiramatsu 
3107ef17aafSMasami Hiramatsu /* Synthesize only probe point (not argument) */
3117ef17aafSMasami Hiramatsu int synthesize_perf_probe_point(struct probe_point *pp)
31250656eecSMasami Hiramatsu {
31350656eecSMasami Hiramatsu 	char *buf;
3144de189feSMasami Hiramatsu 	char offs[64] = "", line[64] = "";
3157ef17aafSMasami Hiramatsu 	int ret;
31650656eecSMasami Hiramatsu 
317*31facc5fSMasami Hiramatsu 	pp->probes[0] = buf = xzalloc(MAX_CMDLEN);
318388c3aabSMasami Hiramatsu 	pp->found = 1;
3194de189feSMasami Hiramatsu 	if (pp->offset) {
3204de189feSMasami Hiramatsu 		ret = e_snprintf(offs, 64, "+%d", pp->offset);
3214de189feSMasami Hiramatsu 		if (ret <= 0)
3224de189feSMasami Hiramatsu 			goto error;
3234de189feSMasami Hiramatsu 	}
3244de189feSMasami Hiramatsu 	if (pp->line) {
3254de189feSMasami Hiramatsu 		ret = e_snprintf(line, 64, ":%d", pp->line);
3264de189feSMasami Hiramatsu 		if (ret <= 0)
3274de189feSMasami Hiramatsu 			goto error;
3284de189feSMasami Hiramatsu 	}
3294de189feSMasami Hiramatsu 
3304de189feSMasami Hiramatsu 	if (pp->function)
3314de189feSMasami Hiramatsu 		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function,
3324de189feSMasami Hiramatsu 				 offs, pp->retprobe ? "%return" : "", line);
3334de189feSMasami Hiramatsu 	else
33484988450SMasami Hiramatsu 		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line);
3357ef17aafSMasami Hiramatsu 	if (ret <= 0) {
3367ef17aafSMasami Hiramatsu error:
3377ef17aafSMasami Hiramatsu 		free(pp->probes[0]);
3387ef17aafSMasami Hiramatsu 		pp->probes[0] = NULL;
339388c3aabSMasami Hiramatsu 		pp->found = 0;
3407ef17aafSMasami Hiramatsu 	}
3417ef17aafSMasami Hiramatsu 	return ret;
3427ef17aafSMasami Hiramatsu }
34350656eecSMasami Hiramatsu 
3447ef17aafSMasami Hiramatsu int synthesize_perf_probe_event(struct probe_point *pp)
3457ef17aafSMasami Hiramatsu {
3467ef17aafSMasami Hiramatsu 	char *buf;
3477ef17aafSMasami Hiramatsu 	int i, len, ret;
3487ef17aafSMasami Hiramatsu 
3497ef17aafSMasami Hiramatsu 	len = synthesize_perf_probe_point(pp);
3507ef17aafSMasami Hiramatsu 	if (len < 0)
3517ef17aafSMasami Hiramatsu 		return 0;
3527ef17aafSMasami Hiramatsu 
3537ef17aafSMasami Hiramatsu 	buf = pp->probes[0];
35450656eecSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
3554de189feSMasami Hiramatsu 		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
35650656eecSMasami Hiramatsu 				 pp->args[i]);
3574de189feSMasami Hiramatsu 		if (ret <= 0)
35850656eecSMasami Hiramatsu 			goto error;
35950656eecSMasami Hiramatsu 		len += ret;
36050656eecSMasami Hiramatsu 	}
36150656eecSMasami Hiramatsu 	pp->found = 1;
36250656eecSMasami Hiramatsu 
36350656eecSMasami Hiramatsu 	return pp->found;
36450656eecSMasami Hiramatsu error:
36550656eecSMasami Hiramatsu 	free(pp->probes[0]);
3667ef17aafSMasami Hiramatsu 	pp->probes[0] = NULL;
36750656eecSMasami Hiramatsu 
36850656eecSMasami Hiramatsu 	return ret;
36950656eecSMasami Hiramatsu }
37050656eecSMasami Hiramatsu 
3714de189feSMasami Hiramatsu int synthesize_trace_kprobe_event(struct probe_point *pp)
3724de189feSMasami Hiramatsu {
3734de189feSMasami Hiramatsu 	char *buf;
3744de189feSMasami Hiramatsu 	int i, len, ret;
3754de189feSMasami Hiramatsu 
376*31facc5fSMasami Hiramatsu 	pp->probes[0] = buf = xzalloc(MAX_CMDLEN);
3774de189feSMasami Hiramatsu 	ret = e_snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset);
3784de189feSMasami Hiramatsu 	if (ret <= 0)
3794de189feSMasami Hiramatsu 		goto error;
3804de189feSMasami Hiramatsu 	len = ret;
3814de189feSMasami Hiramatsu 
3824de189feSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++) {
3834de189feSMasami Hiramatsu 		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
3844de189feSMasami Hiramatsu 				 pp->args[i]);
3854de189feSMasami Hiramatsu 		if (ret <= 0)
3864de189feSMasami Hiramatsu 			goto error;
3874de189feSMasami Hiramatsu 		len += ret;
3884de189feSMasami Hiramatsu 	}
3894de189feSMasami Hiramatsu 	pp->found = 1;
3904de189feSMasami Hiramatsu 
3914de189feSMasami Hiramatsu 	return pp->found;
3924de189feSMasami Hiramatsu error:
3934de189feSMasami Hiramatsu 	free(pp->probes[0]);
3947ef17aafSMasami Hiramatsu 	pp->probes[0] = NULL;
3954de189feSMasami Hiramatsu 
3964de189feSMasami Hiramatsu 	return ret;
3974de189feSMasami Hiramatsu }
3984de189feSMasami Hiramatsu 
3994de189feSMasami Hiramatsu static int open_kprobe_events(int flags, int mode)
4004de189feSMasami Hiramatsu {
4014de189feSMasami Hiramatsu 	char buf[PATH_MAX];
4024de189feSMasami Hiramatsu 	int ret;
4034de189feSMasami Hiramatsu 
4044de189feSMasami Hiramatsu 	ret = e_snprintf(buf, PATH_MAX, "%s/../kprobe_events", debugfs_path);
4054de189feSMasami Hiramatsu 	if (ret < 0)
4064de189feSMasami Hiramatsu 		die("Failed to make kprobe_events path.");
4074de189feSMasami Hiramatsu 
4084de189feSMasami Hiramatsu 	ret = open(buf, flags, mode);
4094de189feSMasami Hiramatsu 	if (ret < 0) {
4104de189feSMasami Hiramatsu 		if (errno == ENOENT)
4114de189feSMasami Hiramatsu 			die("kprobe_events file does not exist -"
41263bbd5e2SLiming Wang 			    " please rebuild with CONFIG_KPROBE_EVENT.");
4134de189feSMasami Hiramatsu 		else
4144de189feSMasami Hiramatsu 			die("Could not open kprobe_events file: %s",
4154de189feSMasami Hiramatsu 			    strerror(errno));
4164de189feSMasami Hiramatsu 	}
4174de189feSMasami Hiramatsu 	return ret;
4184de189feSMasami Hiramatsu }
4194de189feSMasami Hiramatsu 
4204de189feSMasami Hiramatsu /* Get raw string list of current kprobe_events */
4214de189feSMasami Hiramatsu static struct strlist *get_trace_kprobe_event_rawlist(int fd)
4224de189feSMasami Hiramatsu {
4234de189feSMasami Hiramatsu 	int ret, idx;
4244de189feSMasami Hiramatsu 	FILE *fp;
4254de189feSMasami Hiramatsu 	char buf[MAX_CMDLEN];
4264de189feSMasami Hiramatsu 	char *p;
4274de189feSMasami Hiramatsu 	struct strlist *sl;
4284de189feSMasami Hiramatsu 
4294de189feSMasami Hiramatsu 	sl = strlist__new(true, NULL);
4304de189feSMasami Hiramatsu 
4314de189feSMasami Hiramatsu 	fp = fdopen(dup(fd), "r");
4324de189feSMasami Hiramatsu 	while (!feof(fp)) {
4334de189feSMasami Hiramatsu 		p = fgets(buf, MAX_CMDLEN, fp);
4344de189feSMasami Hiramatsu 		if (!p)
4354de189feSMasami Hiramatsu 			break;
4364de189feSMasami Hiramatsu 
4374de189feSMasami Hiramatsu 		idx = strlen(p) - 1;
4384de189feSMasami Hiramatsu 		if (p[idx] == '\n')
4394de189feSMasami Hiramatsu 			p[idx] = '\0';
4404de189feSMasami Hiramatsu 		ret = strlist__add(sl, buf);
4414de189feSMasami Hiramatsu 		if (ret < 0)
4424de189feSMasami Hiramatsu 			die("strlist__add failed: %s", strerror(-ret));
4434de189feSMasami Hiramatsu 	}
4444de189feSMasami Hiramatsu 	fclose(fp);
4454de189feSMasami Hiramatsu 
4464de189feSMasami Hiramatsu 	return sl;
4474de189feSMasami Hiramatsu }
4484de189feSMasami Hiramatsu 
4494de189feSMasami Hiramatsu /* Free and zero clear probe_point */
4504de189feSMasami Hiramatsu static void clear_probe_point(struct probe_point *pp)
4514de189feSMasami Hiramatsu {
4524de189feSMasami Hiramatsu 	int i;
4534de189feSMasami Hiramatsu 
454af663d75SMasami Hiramatsu 	if (pp->event)
455af663d75SMasami Hiramatsu 		free(pp->event);
456af663d75SMasami Hiramatsu 	if (pp->group)
457af663d75SMasami Hiramatsu 		free(pp->group);
4584de189feSMasami Hiramatsu 	if (pp->function)
4594de189feSMasami Hiramatsu 		free(pp->function);
4604de189feSMasami Hiramatsu 	if (pp->file)
4614de189feSMasami Hiramatsu 		free(pp->file);
4622a9c8c36SMasami Hiramatsu 	if (pp->lazy_line)
4632a9c8c36SMasami Hiramatsu 		free(pp->lazy_line);
4644de189feSMasami Hiramatsu 	for (i = 0; i < pp->nr_args; i++)
4654de189feSMasami Hiramatsu 		free(pp->args[i]);
4664de189feSMasami Hiramatsu 	if (pp->args)
4674de189feSMasami Hiramatsu 		free(pp->args);
4684de189feSMasami Hiramatsu 	for (i = 0; i < pp->found; i++)
4694de189feSMasami Hiramatsu 		free(pp->probes[i]);
4705660ce34SJulia Lawall 	memset(pp, 0, sizeof(*pp));
4714de189feSMasami Hiramatsu }
4724de189feSMasami Hiramatsu 
473278498d4SMasami Hiramatsu /* Show an event */
474af663d75SMasami Hiramatsu static void show_perf_probe_event(const char *event, const char *place,
475af663d75SMasami Hiramatsu 				  struct probe_point *pp)
476278498d4SMasami Hiramatsu {
4777e990a51SMasami Hiramatsu 	int i, ret;
478278498d4SMasami Hiramatsu 	char buf[128];
479278498d4SMasami Hiramatsu 
480af663d75SMasami Hiramatsu 	ret = e_snprintf(buf, 128, "%s:%s", pp->group, event);
4817e990a51SMasami Hiramatsu 	if (ret < 0)
4827e990a51SMasami Hiramatsu 		die("Failed to copy event: %s", strerror(-ret));
483278498d4SMasami Hiramatsu 	printf("  %-40s (on %s", buf, place);
484278498d4SMasami Hiramatsu 
485278498d4SMasami Hiramatsu 	if (pp->nr_args > 0) {
486278498d4SMasami Hiramatsu 		printf(" with");
487278498d4SMasami Hiramatsu 		for (i = 0; i < pp->nr_args; i++)
488278498d4SMasami Hiramatsu 			printf(" %s", pp->args[i]);
489278498d4SMasami Hiramatsu 	}
490278498d4SMasami Hiramatsu 	printf(")\n");
491278498d4SMasami Hiramatsu }
492278498d4SMasami Hiramatsu 
4934de189feSMasami Hiramatsu /* List up current perf-probe events */
4944de189feSMasami Hiramatsu void show_perf_probe_events(void)
4954de189feSMasami Hiramatsu {
4967ef17aafSMasami Hiramatsu 	int fd;
4974de189feSMasami Hiramatsu 	struct probe_point pp;
4984de189feSMasami Hiramatsu 	struct strlist *rawlist;
4994de189feSMasami Hiramatsu 	struct str_node *ent;
5004de189feSMasami Hiramatsu 
50172041334SMasami Hiramatsu 	setup_pager();
502388c3aabSMasami Hiramatsu 	memset(&pp, 0, sizeof(pp));
50372041334SMasami Hiramatsu 
5044de189feSMasami Hiramatsu 	fd = open_kprobe_events(O_RDONLY, 0);
5054de189feSMasami Hiramatsu 	rawlist = get_trace_kprobe_event_rawlist(fd);
5064de189feSMasami Hiramatsu 	close(fd);
5074de189feSMasami Hiramatsu 
508adf365f4SMasami Hiramatsu 	strlist__for_each(ent, rawlist) {
509af663d75SMasami Hiramatsu 		parse_trace_kprobe_event(ent->s, &pp);
510278498d4SMasami Hiramatsu 		/* Synthesize only event probe point */
5117ef17aafSMasami Hiramatsu 		synthesize_perf_probe_point(&pp);
512278498d4SMasami Hiramatsu 		/* Show an event */
513af663d75SMasami Hiramatsu 		show_perf_probe_event(pp.event, pp.probes[0], &pp);
5144de189feSMasami Hiramatsu 		clear_probe_point(&pp);
5154de189feSMasami Hiramatsu 	}
5164de189feSMasami Hiramatsu 
5174de189feSMasami Hiramatsu 	strlist__delete(rawlist);
5184de189feSMasami Hiramatsu }
5194de189feSMasami Hiramatsu 
520b498ce1fSMasami Hiramatsu /* Get current perf-probe event names */
521fa28244dSMasami Hiramatsu static struct strlist *get_perf_event_names(int fd, bool include_group)
522b498ce1fSMasami Hiramatsu {
523fa28244dSMasami Hiramatsu 	char buf[128];
524b498ce1fSMasami Hiramatsu 	struct strlist *sl, *rawlist;
525b498ce1fSMasami Hiramatsu 	struct str_node *ent;
526af663d75SMasami Hiramatsu 	struct probe_point pp;
527b498ce1fSMasami Hiramatsu 
528af663d75SMasami Hiramatsu 	memset(&pp, 0, sizeof(pp));
529b498ce1fSMasami Hiramatsu 	rawlist = get_trace_kprobe_event_rawlist(fd);
530b498ce1fSMasami Hiramatsu 
531e1d2017bSMasami Hiramatsu 	sl = strlist__new(true, NULL);
532adf365f4SMasami Hiramatsu 	strlist__for_each(ent, rawlist) {
533af663d75SMasami Hiramatsu 		parse_trace_kprobe_event(ent->s, &pp);
534fa28244dSMasami Hiramatsu 		if (include_group) {
535af663d75SMasami Hiramatsu 			if (e_snprintf(buf, 128, "%s:%s", pp.group,
536af663d75SMasami Hiramatsu 				       pp.event) < 0)
537fa28244dSMasami Hiramatsu 				die("Failed to copy group:event name.");
538fa28244dSMasami Hiramatsu 			strlist__add(sl, buf);
539fa28244dSMasami Hiramatsu 		} else
540af663d75SMasami Hiramatsu 			strlist__add(sl, pp.event);
541af663d75SMasami Hiramatsu 		clear_probe_point(&pp);
542b498ce1fSMasami Hiramatsu 	}
543b498ce1fSMasami Hiramatsu 
544b498ce1fSMasami Hiramatsu 	strlist__delete(rawlist);
545b498ce1fSMasami Hiramatsu 
546b498ce1fSMasami Hiramatsu 	return sl;
547b498ce1fSMasami Hiramatsu }
548b498ce1fSMasami Hiramatsu 
549a9b495b0SMasami Hiramatsu static void write_trace_kprobe_event(int fd, const char *buf)
55050656eecSMasami Hiramatsu {
55150656eecSMasami Hiramatsu 	int ret;
55250656eecSMasami Hiramatsu 
553fa28244dSMasami Hiramatsu 	pr_debug("Writing event: %s\n", buf);
55450656eecSMasami Hiramatsu 	ret = write(fd, buf, strlen(buf));
55550656eecSMasami Hiramatsu 	if (ret <= 0)
556fa28244dSMasami Hiramatsu 		die("Failed to write event: %s", strerror(errno));
55750656eecSMasami Hiramatsu }
55850656eecSMasami Hiramatsu 
559b498ce1fSMasami Hiramatsu static void get_new_event_name(char *buf, size_t len, const char *base,
560d761b08bSMasami Hiramatsu 			       struct strlist *namelist, bool allow_suffix)
561b498ce1fSMasami Hiramatsu {
562b498ce1fSMasami Hiramatsu 	int i, ret;
56317f88fcdSMasami Hiramatsu 
56417f88fcdSMasami Hiramatsu 	/* Try no suffix */
56517f88fcdSMasami Hiramatsu 	ret = e_snprintf(buf, len, "%s", base);
56617f88fcdSMasami Hiramatsu 	if (ret < 0)
56717f88fcdSMasami Hiramatsu 		die("snprintf() failed: %s", strerror(-ret));
56817f88fcdSMasami Hiramatsu 	if (!strlist__has_entry(namelist, buf))
56917f88fcdSMasami Hiramatsu 		return;
57017f88fcdSMasami Hiramatsu 
571d761b08bSMasami Hiramatsu 	if (!allow_suffix) {
572d761b08bSMasami Hiramatsu 		pr_warning("Error: event \"%s\" already exists. "
573d761b08bSMasami Hiramatsu 			   "(Use -f to force duplicates.)\n", base);
574d761b08bSMasami Hiramatsu 		die("Can't add new event.");
575d761b08bSMasami Hiramatsu 	}
576d761b08bSMasami Hiramatsu 
57717f88fcdSMasami Hiramatsu 	/* Try to add suffix */
57817f88fcdSMasami Hiramatsu 	for (i = 1; i < MAX_EVENT_INDEX; i++) {
579b498ce1fSMasami Hiramatsu 		ret = e_snprintf(buf, len, "%s_%d", base, i);
580b498ce1fSMasami Hiramatsu 		if (ret < 0)
581b498ce1fSMasami Hiramatsu 			die("snprintf() failed: %s", strerror(-ret));
582b498ce1fSMasami Hiramatsu 		if (!strlist__has_entry(namelist, buf))
583b498ce1fSMasami Hiramatsu 			break;
584b498ce1fSMasami Hiramatsu 	}
585b498ce1fSMasami Hiramatsu 	if (i == MAX_EVENT_INDEX)
586b498ce1fSMasami Hiramatsu 		die("Too many events are on the same function.");
587b498ce1fSMasami Hiramatsu }
588b498ce1fSMasami Hiramatsu 
589d761b08bSMasami Hiramatsu void add_trace_kprobe_events(struct probe_point *probes, int nr_probes,
590d761b08bSMasami Hiramatsu 			     bool force_add)
59150656eecSMasami Hiramatsu {
59250656eecSMasami Hiramatsu 	int i, j, fd;
59350656eecSMasami Hiramatsu 	struct probe_point *pp;
59450656eecSMasami Hiramatsu 	char buf[MAX_CMDLEN];
595b498ce1fSMasami Hiramatsu 	char event[64];
596b498ce1fSMasami Hiramatsu 	struct strlist *namelist;
597d761b08bSMasami Hiramatsu 	bool allow_suffix;
59850656eecSMasami Hiramatsu 
599b498ce1fSMasami Hiramatsu 	fd = open_kprobe_events(O_RDWR, O_APPEND);
600b498ce1fSMasami Hiramatsu 	/* Get current event names */
601fa28244dSMasami Hiramatsu 	namelist = get_perf_event_names(fd, false);
60250656eecSMasami Hiramatsu 
60350656eecSMasami Hiramatsu 	for (j = 0; j < nr_probes; j++) {
60450656eecSMasami Hiramatsu 		pp = probes + j;
605af663d75SMasami Hiramatsu 		if (!pp->event)
606*31facc5fSMasami Hiramatsu 			pp->event = xstrdup(pp->function);
607af663d75SMasami Hiramatsu 		if (!pp->group)
608*31facc5fSMasami Hiramatsu 			pp->group = xstrdup(PERFPROBE_GROUP);
609d761b08bSMasami Hiramatsu 		/* If force_add is true, suffix search is allowed */
610d761b08bSMasami Hiramatsu 		allow_suffix = force_add;
61150656eecSMasami Hiramatsu 		for (i = 0; i < pp->found; i++) {
612b498ce1fSMasami Hiramatsu 			/* Get an unused new event name */
613d761b08bSMasami Hiramatsu 			get_new_event_name(event, 64, pp->event, namelist,
614d761b08bSMasami Hiramatsu 					   allow_suffix);
615b498ce1fSMasami Hiramatsu 			snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n",
61650656eecSMasami Hiramatsu 				 pp->retprobe ? 'r' : 'p',
617af663d75SMasami Hiramatsu 				 pp->group, event,
61850656eecSMasami Hiramatsu 				 pp->probes[i]);
61950656eecSMasami Hiramatsu 			write_trace_kprobe_event(fd, buf);
620a9b495b0SMasami Hiramatsu 			printf("Added new event:\n");
621a9b495b0SMasami Hiramatsu 			/* Get the first parameter (probe-point) */
622a9b495b0SMasami Hiramatsu 			sscanf(pp->probes[i], "%s", buf);
623af663d75SMasami Hiramatsu 			show_perf_probe_event(event, buf, pp);
624b498ce1fSMasami Hiramatsu 			/* Add added event name to namelist */
625b498ce1fSMasami Hiramatsu 			strlist__add(namelist, event);
626d761b08bSMasami Hiramatsu 			/*
627d761b08bSMasami Hiramatsu 			 * Probes after the first probe which comes from same
628d761b08bSMasami Hiramatsu 			 * user input are always allowed to add suffix, because
629d761b08bSMasami Hiramatsu 			 * there might be several addresses corresponding to
630d761b08bSMasami Hiramatsu 			 * one code line.
631d761b08bSMasami Hiramatsu 			 */
632d761b08bSMasami Hiramatsu 			allow_suffix = true;
63350656eecSMasami Hiramatsu 		}
63450656eecSMasami Hiramatsu 	}
635a9b495b0SMasami Hiramatsu 	/* Show how to use the event. */
636a9b495b0SMasami Hiramatsu 	printf("\nYou can now use it on all perf tools, such as:\n\n");
637a9b495b0SMasami Hiramatsu 	printf("\tperf record -e %s:%s -a sleep 1\n\n", PERFPROBE_GROUP, event);
638a9b495b0SMasami Hiramatsu 
639e1d2017bSMasami Hiramatsu 	strlist__delete(namelist);
64050656eecSMasami Hiramatsu 	close(fd);
64150656eecSMasami Hiramatsu }
642fa28244dSMasami Hiramatsu 
643bbbb521bSMasami Hiramatsu static void __del_trace_kprobe_event(int fd, struct str_node *ent)
644bbbb521bSMasami Hiramatsu {
645bbbb521bSMasami Hiramatsu 	char *p;
646bbbb521bSMasami Hiramatsu 	char buf[128];
647bbbb521bSMasami Hiramatsu 
648bbbb521bSMasami Hiramatsu 	/* Convert from perf-probe event to trace-kprobe event */
649bbbb521bSMasami Hiramatsu 	if (e_snprintf(buf, 128, "-:%s", ent->s) < 0)
650bbbb521bSMasami Hiramatsu 		die("Failed to copy event.");
651bbbb521bSMasami Hiramatsu 	p = strchr(buf + 2, ':');
652bbbb521bSMasami Hiramatsu 	if (!p)
653bbbb521bSMasami Hiramatsu 		die("Internal error: %s should have ':' but not.", ent->s);
654bbbb521bSMasami Hiramatsu 	*p = '/';
655bbbb521bSMasami Hiramatsu 
656bbbb521bSMasami Hiramatsu 	write_trace_kprobe_event(fd, buf);
657bbbb521bSMasami Hiramatsu 	printf("Remove event: %s\n", ent->s);
658bbbb521bSMasami Hiramatsu }
659bbbb521bSMasami Hiramatsu 
660fa28244dSMasami Hiramatsu static void del_trace_kprobe_event(int fd, const char *group,
661fa28244dSMasami Hiramatsu 				   const char *event, struct strlist *namelist)
662fa28244dSMasami Hiramatsu {
663fa28244dSMasami Hiramatsu 	char buf[128];
664bbbb521bSMasami Hiramatsu 	struct str_node *ent, *n;
665bbbb521bSMasami Hiramatsu 	int found = 0;
666fa28244dSMasami Hiramatsu 
667fa28244dSMasami Hiramatsu 	if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
668fa28244dSMasami Hiramatsu 		die("Failed to copy event.");
669fa28244dSMasami Hiramatsu 
670bbbb521bSMasami Hiramatsu 	if (strpbrk(buf, "*?")) { /* Glob-exp */
671bbbb521bSMasami Hiramatsu 		strlist__for_each_safe(ent, n, namelist)
672bbbb521bSMasami Hiramatsu 			if (strglobmatch(ent->s, buf)) {
673bbbb521bSMasami Hiramatsu 				found++;
674bbbb521bSMasami Hiramatsu 				__del_trace_kprobe_event(fd, ent);
6753e340590SMasami Hiramatsu 				strlist__remove(namelist, ent);
676fa28244dSMasami Hiramatsu 			}
677bbbb521bSMasami Hiramatsu 	} else {
678bbbb521bSMasami Hiramatsu 		ent = strlist__find(namelist, buf);
679bbbb521bSMasami Hiramatsu 		if (ent) {
680bbbb521bSMasami Hiramatsu 			found++;
681bbbb521bSMasami Hiramatsu 			__del_trace_kprobe_event(fd, ent);
682bbbb521bSMasami Hiramatsu 			strlist__remove(namelist, ent);
683bbbb521bSMasami Hiramatsu 		}
684bbbb521bSMasami Hiramatsu 	}
685bbbb521bSMasami Hiramatsu 	if (found == 0)
686bbbb521bSMasami Hiramatsu 		pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf);
687bbbb521bSMasami Hiramatsu }
688fa28244dSMasami Hiramatsu 
689fa28244dSMasami Hiramatsu void del_trace_kprobe_events(struct strlist *dellist)
690fa28244dSMasami Hiramatsu {
691fa28244dSMasami Hiramatsu 	int fd;
692fa28244dSMasami Hiramatsu 	const char *group, *event;
693fa28244dSMasami Hiramatsu 	char *p, *str;
694fa28244dSMasami Hiramatsu 	struct str_node *ent;
695fa28244dSMasami Hiramatsu 	struct strlist *namelist;
696fa28244dSMasami Hiramatsu 
697fa28244dSMasami Hiramatsu 	fd = open_kprobe_events(O_RDWR, O_APPEND);
698fa28244dSMasami Hiramatsu 	/* Get current event names */
699fa28244dSMasami Hiramatsu 	namelist = get_perf_event_names(fd, true);
700fa28244dSMasami Hiramatsu 
701adf365f4SMasami Hiramatsu 	strlist__for_each(ent, dellist) {
702*31facc5fSMasami Hiramatsu 		str = xstrdup(ent->s);
703bbbb521bSMasami Hiramatsu 		pr_debug("Parsing: %s\n", str);
704fa28244dSMasami Hiramatsu 		p = strchr(str, ':');
705fa28244dSMasami Hiramatsu 		if (p) {
706fa28244dSMasami Hiramatsu 			group = str;
707fa28244dSMasami Hiramatsu 			*p = '\0';
708fa28244dSMasami Hiramatsu 			event = p + 1;
709fa28244dSMasami Hiramatsu 		} else {
710bbbb521bSMasami Hiramatsu 			group = "*";
711fa28244dSMasami Hiramatsu 			event = str;
712fa28244dSMasami Hiramatsu 		}
713bbbb521bSMasami Hiramatsu 		pr_debug("Group: %s, Event: %s\n", group, event);
714fa28244dSMasami Hiramatsu 		del_trace_kprobe_event(fd, group, event, namelist);
715fa28244dSMasami Hiramatsu 		free(str);
716fa28244dSMasami Hiramatsu 	}
717fa28244dSMasami Hiramatsu 	strlist__delete(namelist);
718fa28244dSMasami Hiramatsu 	close(fd);
719fa28244dSMasami Hiramatsu }
720fa28244dSMasami Hiramatsu 
721631c9defSMasami Hiramatsu #define LINEBUF_SIZE 256
7225c8d1cbbSMasami Hiramatsu #define NR_ADDITIONAL_LINES 2
723631c9defSMasami Hiramatsu 
724631c9defSMasami Hiramatsu static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num)
725631c9defSMasami Hiramatsu {
726631c9defSMasami Hiramatsu 	char buf[LINEBUF_SIZE];
727631c9defSMasami Hiramatsu 	const char *color = PERF_COLOR_BLUE;
728631c9defSMasami Hiramatsu 
729631c9defSMasami Hiramatsu 	if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
730631c9defSMasami Hiramatsu 		goto error;
731631c9defSMasami Hiramatsu 	if (!skip) {
732631c9defSMasami Hiramatsu 		if (show_num)
733631c9defSMasami Hiramatsu 			fprintf(stdout, "%7u  %s", l, buf);
734631c9defSMasami Hiramatsu 		else
735631c9defSMasami Hiramatsu 			color_fprintf(stdout, color, "         %s", buf);
736631c9defSMasami Hiramatsu 	}
737631c9defSMasami Hiramatsu 
738631c9defSMasami Hiramatsu 	while (strlen(buf) == LINEBUF_SIZE - 1 &&
739631c9defSMasami Hiramatsu 	       buf[LINEBUF_SIZE - 2] != '\n') {
740631c9defSMasami Hiramatsu 		if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
741631c9defSMasami Hiramatsu 			goto error;
742631c9defSMasami Hiramatsu 		if (!skip) {
743631c9defSMasami Hiramatsu 			if (show_num)
744631c9defSMasami Hiramatsu 				fprintf(stdout, "%s", buf);
745631c9defSMasami Hiramatsu 			else
746631c9defSMasami Hiramatsu 				color_fprintf(stdout, color, "%s", buf);
747631c9defSMasami Hiramatsu 		}
748631c9defSMasami Hiramatsu 	}
749631c9defSMasami Hiramatsu 	return;
750631c9defSMasami Hiramatsu error:
751631c9defSMasami Hiramatsu 	if (feof(fp))
752631c9defSMasami Hiramatsu 		die("Source file is shorter than expected.");
753631c9defSMasami Hiramatsu 	else
754631c9defSMasami Hiramatsu 		die("File read error: %s", strerror(errno));
755631c9defSMasami Hiramatsu }
756631c9defSMasami Hiramatsu 
757631c9defSMasami Hiramatsu void show_line_range(struct line_range *lr)
758631c9defSMasami Hiramatsu {
759631c9defSMasami Hiramatsu 	unsigned int l = 1;
760631c9defSMasami Hiramatsu 	struct line_node *ln;
761631c9defSMasami Hiramatsu 	FILE *fp;
762631c9defSMasami Hiramatsu 
763631c9defSMasami Hiramatsu 	setup_pager();
764631c9defSMasami Hiramatsu 
765631c9defSMasami Hiramatsu 	if (lr->function)
766631c9defSMasami Hiramatsu 		fprintf(stdout, "<%s:%d>\n", lr->function,
767631c9defSMasami Hiramatsu 			lr->start - lr->offset);
768631c9defSMasami Hiramatsu 	else
769631c9defSMasami Hiramatsu 		fprintf(stdout, "<%s:%d>\n", lr->file, lr->start);
770631c9defSMasami Hiramatsu 
771631c9defSMasami Hiramatsu 	fp = fopen(lr->path, "r");
772631c9defSMasami Hiramatsu 	if (fp == NULL)
773631c9defSMasami Hiramatsu 		die("Failed to open %s: %s", lr->path, strerror(errno));
774631c9defSMasami Hiramatsu 	/* Skip to starting line number */
775631c9defSMasami Hiramatsu 	while (l < lr->start)
776631c9defSMasami Hiramatsu 		show_one_line(fp, l++, true, false);
777631c9defSMasami Hiramatsu 
778631c9defSMasami Hiramatsu 	list_for_each_entry(ln, &lr->line_list, list) {
779631c9defSMasami Hiramatsu 		while (ln->line > l)
780631c9defSMasami Hiramatsu 			show_one_line(fp, (l++) - lr->offset, false, false);
781631c9defSMasami Hiramatsu 		show_one_line(fp, (l++) - lr->offset, false, true);
782631c9defSMasami Hiramatsu 	}
7835c8d1cbbSMasami Hiramatsu 
7845c8d1cbbSMasami Hiramatsu 	if (lr->end == INT_MAX)
7855c8d1cbbSMasami Hiramatsu 		lr->end = l + NR_ADDITIONAL_LINES;
7865c8d1cbbSMasami Hiramatsu 	while (l < lr->end && !feof(fp))
7875c8d1cbbSMasami Hiramatsu 		show_one_line(fp, (l++) - lr->offset, false, false);
7885c8d1cbbSMasami Hiramatsu 
789631c9defSMasami Hiramatsu 	fclose(fp);
790631c9defSMasami Hiramatsu }
791