diff options
Diffstat (limited to 'tools/perf/util/probe-event.c')
| -rw-r--r-- | tools/perf/util/probe-event.c | 616 | 
1 files changed, 272 insertions, 344 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 381f23a443c7..c6f9af78f6f5 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -45,6 +45,7 @@  #include "trace-event.h"	/* For __maybe_unused */  #include "probe-event.h"  #include "probe-finder.h" +#include "probe-file.h"  #include "session.h"  #define MAX_CMDLEN 256 @@ -55,11 +56,7 @@ struct probe_conf probe_conf;  #define semantic_error(msg ...) pr_err("Semantic error :" msg) -/* If there is no space to write, returns -E2BIG. */ -static int e_snprintf(char *str, size_t size, const char *format, ...) -	__attribute__((format(printf, 3, 4))); - -static int e_snprintf(char *str, size_t size, const char *format, ...) +int e_snprintf(char *str, size_t size, const char *format, ...)  {  	int ret;  	va_list ap; @@ -72,7 +69,6 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)  }  static char *synthesize_perf_probe_point(struct perf_probe_point *pp); -static void clear_probe_trace_event(struct probe_trace_event *tev);  static struct machine *host_machine;  /* Initialize symbol maps and path of vmlinux/modules */ @@ -274,12 +270,13 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso)  	int ret = 0;  	if (module) { -		list_for_each_entry(dso, &host_machine->dsos.head, node) { -			if (!dso->kernel) -				continue; -			if (strncmp(dso->short_name + 1, module, -				    dso->short_name_len - 2) == 0) -				goto found; +		char module_name[128]; + +		snprintf(module_name, sizeof(module_name), "[%s]", module); +		map = map_groups__find_by_name(&host_machine->kmaps, MAP__FUNCTION, module_name); +		if (map) { +			dso = map->dso; +			goto found;  		}  		pr_debug("Failed to find module %s.\n", module);  		return -ENOENT; @@ -519,7 +516,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,  		if (ret < 0)  			goto error;  		addr += stext; -	} else { +	} else if (tp->symbol) {  		addr = kernel_get_symbol_address_by_name(tp->symbol, false);  		if (addr == 0)  			goto error; @@ -709,9 +706,10 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,  	}  	/* Error path : ntevs < 0 */  	pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); -	if (ntevs == -EBADF) { -		pr_warning("Warning: No dwarf info found in the vmlinux - " -			"please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); +	if (ntevs < 0) { +		if (ntevs == -EBADF) +			pr_warning("Warning: No dwarf info found in the vmlinux - " +				"please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");  		if (!need_dwarf) {  			pr_debug("Trying to use symbols.\n");  			return 0; @@ -1197,15 +1195,37 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)  		*ptr++ = '\0';  	} -	tmp = strdup(arg); -	if (tmp == NULL) -		return -ENOMEM; +	if (arg[0] == '\0') +		tmp = NULL; +	else { +		tmp = strdup(arg); +		if (tmp == NULL) +			return -ENOMEM; +	}  	if (file_spec)  		pp->file = tmp; -	else +	else {  		pp->function = tmp; +		/* +		 * Keep pp->function even if this is absolute address, +		 * so it can mark whether abs_address is valid. +		 * Which make 'perf probe lib.bin 0x0' possible. +		 * +		 * Note that checking length of tmp is not needed +		 * because when we access tmp[1] we know tmp[0] is '0', +		 * so tmp[1] should always valid (but could be '\0'). +		 */ +		if (tmp && !strncmp(tmp, "0x", 2)) { +			pp->abs_address = strtoul(pp->function, &tmp, 0); +			if (*tmp != '\0') { +				semantic_error("Invalid absolute address.\n"); +				return -EINVAL; +			} +		} +	} +  	/* Parse other options */  	while (ptr) {  		arg = ptr; @@ -1467,8 +1487,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)  }  /* Parse probe_events event into struct probe_point */ -static int parse_probe_trace_command(const char *cmd, -				     struct probe_trace_event *tev) +int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)  {  	struct probe_trace_point *tp = &tev->point;  	char pr; @@ -1523,9 +1542,31 @@ static int parse_probe_trace_command(const char *cmd,  	} else  		p = argv[1];  	fmt1_str = strtok_r(p, "+", &fmt); -	if (fmt1_str[0] == '0')	/* only the address started with 0x */ -		tp->address = strtoul(fmt1_str, NULL, 0); -	else { +	/* only the address started with 0x */ +	if (fmt1_str[0] == '0')	{ +		/* +		 * Fix a special case: +		 * if address == 0, kernel reports something like: +		 * p:probe_libc/abs_0 /lib/libc-2.18.so:0x          (null) arg1=%ax +		 * Newer kernel may fix that, but we want to +		 * support old kernel also. +		 */ +		if (strcmp(fmt1_str, "0x") == 0) { +			if (!argv[2] || strcmp(argv[2], "(null)")) { +				ret = -EINVAL; +				goto out; +			} +			tp->address = 0; + +			free(argv[2]); +			for (i = 2; argv[i + 1] != NULL; i++) +				argv[i] = argv[i + 1]; + +			argv[i] = NULL; +			argc -= 1; +		} else +			tp->address = strtoul(fmt1_str, NULL, 0); +	} else {  		/* Only the symbol-based probe has offset */  		tp->symbol = strdup(fmt1_str);  		if (tp->symbol == NULL) { @@ -1782,14 +1823,29 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)  	if (len <= 0)  		goto error; -	/* Uprobes must have tp->address and tp->module */ -	if (tev->uprobes && (!tp->address || !tp->module)) +	/* Uprobes must have tp->module */ +	if (tev->uprobes && !tp->module)  		goto error; +	/* +	 * If tp->address == 0, then this point must be a +	 * absolute address uprobe. +	 * try_to_find_absolute_address() should have made +	 * tp->symbol to "0x0". +	 */ +	if (tev->uprobes && !tp->address) { +		if (!tp->symbol || strcmp(tp->symbol, "0x0")) +			goto error; +	}  	/* Use the tp->address for uprobes */  	if (tev->uprobes)  		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",  				 tp->module, tp->address); +	else if (!strncmp(tp->symbol, "0x", 2)) +		/* Absolute address. See try_to_find_absolute_address() */ +		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s0x%lx", +				 tp->module ?: "", tp->module ? ":" : "", +				 tp->address);  	else  		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",  				 tp->module ?: "", tp->module ? ":" : "", @@ -1819,17 +1875,17 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,  {  	struct symbol *sym = NULL;  	struct map *map; -	u64 addr; +	u64 addr = tp->address;  	int ret = -ENOENT;  	if (!is_kprobe) {  		map = dso__new_map(tp->module);  		if (!map)  			goto out; -		addr = tp->address;  		sym = map__find_symbol(map, addr, NULL);  	} else { -		addr = kernel_get_symbol_address_by_name(tp->symbol, true); +		if (tp->symbol) +			addr = kernel_get_symbol_address_by_name(tp->symbol, true);  		if (addr) {  			addr += tp->offset;  			sym = __find_kernel_function(addr, &map); @@ -1852,8 +1908,8 @@ out:  }  static int convert_to_perf_probe_point(struct probe_trace_point *tp, -					struct perf_probe_point *pp, -					bool is_kprobe) +				       struct perf_probe_point *pp, +				       bool is_kprobe)  {  	char buf[128];  	int ret; @@ -1870,7 +1926,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,  	if (tp->symbol) {  		pp->function = strdup(tp->symbol);  		pp->offset = tp->offset; -	} else if (!tp->module && !is_kprobe) { +	} else {  		ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);  		if (ret < 0)  			return ret; @@ -1951,7 +2007,7 @@ void clear_perf_probe_event(struct perf_probe_event *pev)  	memset(pev, 0, sizeof(*pev));  } -static void clear_probe_trace_event(struct probe_trace_event *tev) +void clear_probe_trace_event(struct probe_trace_event *tev)  {  	struct probe_trace_arg_ref *ref, *next;  	int i; @@ -1976,119 +2032,6 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)  	memset(tev, 0, sizeof(*tev));  } -static void print_open_warning(int err, bool is_kprobe) -{ -	char sbuf[STRERR_BUFSIZE]; - -	if (err == -ENOENT) { -		const char *config; - -		if (!is_kprobe) -			config = "CONFIG_UPROBE_EVENTS"; -		else -			config = "CONFIG_KPROBE_EVENTS"; - -		pr_warning("%cprobe_events file does not exist" -			   " - please rebuild kernel with %s.\n", -			   is_kprobe ? 'k' : 'u', config); -	} else if (err == -ENOTSUP) -		pr_warning("Tracefs or debugfs is not mounted.\n"); -	else -		pr_warning("Failed to open %cprobe_events: %s\n", -			   is_kprobe ? 'k' : 'u', -			   strerror_r(-err, sbuf, sizeof(sbuf))); -} - -static void print_both_open_warning(int kerr, int uerr) -{ -	/* Both kprobes and uprobes are disabled, warn it. */ -	if (kerr == -ENOTSUP && uerr == -ENOTSUP) -		pr_warning("Tracefs or debugfs is not mounted.\n"); -	else if (kerr == -ENOENT && uerr == -ENOENT) -		pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS " -			   "or/and CONFIG_UPROBE_EVENTS.\n"); -	else { -		char sbuf[STRERR_BUFSIZE]; -		pr_warning("Failed to open kprobe events: %s.\n", -			   strerror_r(-kerr, sbuf, sizeof(sbuf))); -		pr_warning("Failed to open uprobe events: %s.\n", -			   strerror_r(-uerr, sbuf, sizeof(sbuf))); -	} -} - -static int open_probe_events(const char *trace_file, bool readwrite) -{ -	char buf[PATH_MAX]; -	const char *__debugfs; -	const char *tracing_dir = ""; -	int ret; - -	__debugfs = tracefs_find_mountpoint(); -	if (__debugfs == NULL) { -		tracing_dir = "tracing/"; - -		__debugfs = debugfs_find_mountpoint(); -		if (__debugfs == NULL) -			return -ENOTSUP; -	} - -	ret = e_snprintf(buf, PATH_MAX, "%s/%s%s", -			 __debugfs, tracing_dir, trace_file); -	if (ret >= 0) { -		pr_debug("Opening %s write=%d\n", buf, readwrite); -		if (readwrite && !probe_event_dry_run) -			ret = open(buf, O_RDWR | O_APPEND, 0); -		else -			ret = open(buf, O_RDONLY, 0); - -		if (ret < 0) -			ret = -errno; -	} -	return ret; -} - -static int open_kprobe_events(bool readwrite) -{ -	return open_probe_events("kprobe_events", readwrite); -} - -static int open_uprobe_events(bool readwrite) -{ -	return open_probe_events("uprobe_events", readwrite); -} - -/* Get raw string list of current kprobe_events  or uprobe_events */ -static struct strlist *get_probe_trace_command_rawlist(int fd) -{ -	int ret, idx; -	FILE *fp; -	char buf[MAX_CMDLEN]; -	char *p; -	struct strlist *sl; - -	sl = strlist__new(true, NULL); - -	fp = fdopen(dup(fd), "r"); -	while (!feof(fp)) { -		p = fgets(buf, MAX_CMDLEN, fp); -		if (!p) -			break; - -		idx = strlen(p) - 1; -		if (p[idx] == '\n') -			p[idx] = '\0'; -		ret = strlist__add(sl, buf); -		if (ret < 0) { -			pr_debug("strlist__add failed (%d)\n", ret); -			strlist__delete(sl); -			return NULL; -		} -	} -	fclose(fp); - -	return sl; -} -  struct kprobe_blacklist_node {  	struct list_head list;  	unsigned long start; @@ -2284,7 +2227,7 @@ static int __show_perf_probe_events(int fd, bool is_kprobe,  	memset(&tev, 0, sizeof(tev));  	memset(&pev, 0, sizeof(pev)); -	rawlist = get_probe_trace_command_rawlist(fd); +	rawlist = probe_file__get_rawlist(fd);  	if (!rawlist)  		return -ENOMEM; @@ -2325,89 +2268,20 @@ int show_perf_probe_events(struct strfilter *filter)  	if (ret < 0)  		return ret; -	kp_fd = open_kprobe_events(false); -	if (kp_fd >= 0) { -		ret = __show_perf_probe_events(kp_fd, true, filter); -		close(kp_fd); -		if (ret < 0) -			goto out; -	} - -	up_fd = open_uprobe_events(false); -	if (kp_fd < 0 && up_fd < 0) { -		print_both_open_warning(kp_fd, up_fd); -		ret = kp_fd; -		goto out; -	} +	ret = probe_file__open_both(&kp_fd, &up_fd, 0); +	if (ret < 0) +		return ret; -	if (up_fd >= 0) { +	if (kp_fd >= 0) +		ret = __show_perf_probe_events(kp_fd, true, filter); +	if (up_fd >= 0 && ret >= 0)  		ret = __show_perf_probe_events(up_fd, false, filter); +	if (kp_fd > 0) +		close(kp_fd); +	if (up_fd > 0)  		close(up_fd); -	} -out:  	exit_symbol_maps(); -	return ret; -} - -/* Get current perf-probe event names */ -static struct strlist *get_probe_trace_event_names(int fd, bool include_group) -{ -	char buf[128]; -	struct strlist *sl, *rawlist; -	struct str_node *ent; -	struct probe_trace_event tev; -	int ret = 0; - -	memset(&tev, 0, sizeof(tev)); -	rawlist = get_probe_trace_command_rawlist(fd); -	if (!rawlist) -		return NULL; -	sl = strlist__new(true, NULL); -	strlist__for_each(ent, rawlist) { -		ret = parse_probe_trace_command(ent->s, &tev); -		if (ret < 0) -			break; -		if (include_group) { -			ret = e_snprintf(buf, 128, "%s:%s", tev.group, -					tev.event); -			if (ret >= 0) -				ret = strlist__add(sl, buf); -		} else -			ret = strlist__add(sl, tev.event); -		clear_probe_trace_event(&tev); -		if (ret < 0) -			break; -	} -	strlist__delete(rawlist); - -	if (ret < 0) { -		strlist__delete(sl); -		return NULL; -	} -	return sl; -} - -static int write_probe_trace_event(int fd, struct probe_trace_event *tev) -{ -	int ret = 0; -	char *buf = synthesize_probe_trace_command(tev); -	char sbuf[STRERR_BUFSIZE]; - -	if (!buf) { -		pr_debug("Failed to synthesize probe trace event.\n"); -		return -EINVAL; -	} -	pr_debug("Writing event: %s\n", buf); -	if (!probe_event_dry_run) { -		ret = write(fd, buf, strlen(buf)); -		if (ret <= 0) { -			ret = -errno; -			pr_warning("Failed to write event: %s\n", -				   strerror_r(errno, sbuf, sizeof(sbuf))); -		} -	} -	free(buf);  	return ret;  } @@ -2478,36 +2352,69 @@ out:  	free(buf);  } +/* Set new name from original perf_probe_event and namelist */ +static int probe_trace_event__set_name(struct probe_trace_event *tev, +				       struct perf_probe_event *pev, +				       struct strlist *namelist, +				       bool allow_suffix) +{ +	const char *event, *group; +	char buf[64]; +	int ret; + +	if (pev->event) +		event = pev->event; +	else +		if (pev->point.function && +			(strncmp(pev->point.function, "0x", 2) != 0) && +			!strisglob(pev->point.function)) +			event = pev->point.function; +		else +			event = tev->point.realname; +	if (pev->group) +		group = pev->group; +	else +		group = PERFPROBE_GROUP; + +	/* Get an unused new event name */ +	ret = get_new_event_name(buf, 64, event, +				 namelist, allow_suffix); +	if (ret < 0) +		return ret; + +	event = buf; + +	tev->event = strdup(event); +	tev->group = strdup(group); +	if (tev->event == NULL || tev->group == NULL) +		return -ENOMEM; + +	/* Add added event name to namelist */ +	strlist__add(namelist, event); +	return 0; +} +  static int __add_probe_trace_events(struct perf_probe_event *pev,  				     struct probe_trace_event *tevs,  				     int ntevs, bool allow_suffix)  {  	int i, fd, ret;  	struct probe_trace_event *tev = NULL; -	char buf[64];  	const char *event = NULL, *group = NULL;  	struct strlist *namelist; -	bool safename; -	if (pev->uprobes) -		fd = open_uprobe_events(true); -	else -		fd = open_kprobe_events(true); - -	if (fd < 0) { -		print_open_warning(fd, !pev->uprobes); +	fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0)); +	if (fd < 0)  		return fd; -	}  	/* Get current event names */ -	namelist = get_probe_trace_event_names(fd, false); +	namelist = probe_file__get_namelist(fd);  	if (!namelist) {  		pr_debug("Failed to get current event list.\n");  		ret = -ENOMEM;  		goto close_out;  	} -	safename = (pev->point.function && !strisglob(pev->point.function));  	ret = 0;  	pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");  	for (i = 0; i < ntevs; i++) { @@ -2516,36 +2423,15 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,  		if (!tev->point.symbol)  			continue; -		if (pev->event) -			event = pev->event; -		else -			if (safename) -				event = pev->point.function; -			else -				event = tev->point.realname; -		if (pev->group) -			group = pev->group; -		else -			group = PERFPROBE_GROUP; - -		/* Get an unused new event name */ -		ret = get_new_event_name(buf, 64, event, -					 namelist, allow_suffix); +		/* Set new name for tev (and update namelist) */ +		ret = probe_trace_event__set_name(tev, pev, namelist, +						  allow_suffix);  		if (ret < 0)  			break; -		event = buf; -		tev->event = strdup(event); -		tev->group = strdup(group); -		if (tev->event == NULL || tev->group == NULL) { -			ret = -ENOMEM; -			break; -		} -		ret = write_probe_trace_event(fd, tev); +		ret = probe_file__add_event(fd, tev);  		if (ret < 0)  			break; -		/* Add added event name to namelist */ -		strlist__add(namelist, event);  		/* We use tev's name for showing new events */  		show_perf_probe_event(tev->group, tev->event, pev, @@ -2748,6 +2634,98 @@ err_out:  	goto out;  } +static int try_to_find_absolute_address(struct perf_probe_event *pev, +					struct probe_trace_event **tevs) +{ +	struct perf_probe_point *pp = &pev->point; +	struct probe_trace_event *tev; +	struct probe_trace_point *tp; +	int i, err; + +	if (!(pev->point.function && !strncmp(pev->point.function, "0x", 2))) +		return -EINVAL; +	if (perf_probe_event_need_dwarf(pev)) +		return -EINVAL; + +	/* +	 * This is 'perf probe /lib/libc.so 0xabcd'. Try to probe at +	 * absolute address. +	 * +	 * Only one tev can be generated by this. +	 */ +	*tevs = zalloc(sizeof(*tev)); +	if (!*tevs) +		return -ENOMEM; + +	tev = *tevs; +	tp = &tev->point; + +	/* +	 * Don't use tp->offset, use address directly, because +	 * in synthesize_probe_trace_command() address cannot be +	 * zero. +	 */ +	tp->address = pev->point.abs_address; +	tp->retprobe = pp->retprobe; +	tev->uprobes = pev->uprobes; + +	err = -ENOMEM; +	/* +	 * Give it a '0x' leading symbol name. +	 * In __add_probe_trace_events, a NULL symbol is interpreted as +	 * invalud. +	 */ +	if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0) +		goto errout; + +	/* For kprobe, check range */ +	if ((!tev->uprobes) && +	    (kprobe_warn_out_range(tev->point.symbol, +				   tev->point.address))) { +		err = -EACCES; +		goto errout; +	} + +	if (asprintf(&tp->realname, "abs_%lx", tp->address) < 0) +		goto errout; + +	if (pev->target) { +		tp->module = strdup(pev->target); +		if (!tp->module) +			goto errout; +	} + +	if (tev->group) { +		tev->group = strdup(pev->group); +		if (!tev->group) +			goto errout; +	} + +	if (pev->event) { +		tev->event = strdup(pev->event); +		if (!tev->event) +			goto errout; +	} + +	tev->nargs = pev->nargs; +	tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); +	if (!tev->args) { +		err = -ENOMEM; +		goto errout; +	} +	for (i = 0; i < tev->nargs; i++) +		copy_to_probe_trace_arg(&tev->args[i], &pev->args[i]); + +	return 1; + +errout: +	if (*tevs) { +		clear_probe_trace_events(*tevs, 1); +		*tevs = NULL; +	} +	return err; +} +  bool __weak arch__prefers_symtab(void) { return false; }  static int convert_to_probe_trace_events(struct perf_probe_event *pev, @@ -2764,6 +2742,10 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,  		}  	} +	ret = try_to_find_absolute_address(pev, tevs); +	if (ret > 0) +		return ret; +  	if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {  		ret = find_probe_trace_events_from_map(pev, tevs);  		if (ret > 0) @@ -2838,68 +2820,9 @@ end:  	return ret;  } -static int __del_trace_probe_event(int fd, struct str_node *ent) -{ -	char *p; -	char buf[128]; -	int ret; - -	/* Convert from perf-probe event to trace-probe event */ -	ret = e_snprintf(buf, 128, "-:%s", ent->s); -	if (ret < 0) -		goto error; - -	p = strchr(buf + 2, ':'); -	if (!p) { -		pr_debug("Internal error: %s should have ':' but not.\n", -			 ent->s); -		ret = -ENOTSUP; -		goto error; -	} -	*p = '/'; - -	pr_debug("Writing event: %s\n", buf); -	ret = write(fd, buf, strlen(buf)); -	if (ret < 0) { -		ret = -errno; -		goto error; -	} - -	pr_info("Removed event: %s\n", ent->s); -	return 0; -error: -	pr_warning("Failed to delete event: %s\n", -		   strerror_r(-ret, buf, sizeof(buf))); -	return ret; -} - -static int del_trace_probe_events(int fd, struct strfilter *filter, -				  struct strlist *namelist) -{ -	struct str_node *ent; -	const char *p; -	int ret = -ENOENT; - -	if (!namelist) -		return -ENOENT; - -	strlist__for_each(ent, namelist) { -		p = strchr(ent->s, ':'); -		if ((p && strfilter__compare(filter, p + 1)) || -		    strfilter__compare(filter, ent->s)) { -			ret = __del_trace_probe_event(fd, ent); -			if (ret < 0) -				break; -		} -	} - -	return ret; -} -  int del_perf_probe_events(struct strfilter *filter)  {  	int ret, ret2, ufd = -1, kfd = -1; -	struct strlist *namelist = NULL, *unamelist = NULL;  	char *str = strfilter__string(filter);  	if (!str) @@ -2908,25 +2831,15 @@ int del_perf_probe_events(struct strfilter *filter)  	pr_debug("Delete filter: \'%s\'\n", str);  	/* Get current event names */ -	kfd = open_kprobe_events(true); -	if (kfd >= 0) -		namelist = get_probe_trace_event_names(kfd, true); - -	ufd = open_uprobe_events(true); -	if (ufd >= 0) -		unamelist = get_probe_trace_event_names(ufd, true); - -	if (kfd < 0 && ufd < 0) { -		print_both_open_warning(kfd, ufd); -		ret = kfd; -		goto error; -	} +	ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW); +	if (ret < 0) +		goto out; -	ret = del_trace_probe_events(kfd, filter, namelist); +	ret = probe_file__del_events(kfd, filter);  	if (ret < 0 && ret != -ENOENT)  		goto error; -	ret2 = del_trace_probe_events(ufd, filter, unamelist); +	ret2 = probe_file__del_events(ufd, filter);  	if (ret2 < 0 && ret2 != -ENOENT) {  		ret = ret2;  		goto error; @@ -2937,15 +2850,11 @@ int del_perf_probe_events(struct strfilter *filter)  	ret = 0;  error: -	if (kfd >= 0) { -		strlist__delete(namelist); +	if (kfd >= 0)  		close(kfd); -	} - -	if (ufd >= 0) { -		strlist__delete(unamelist); +	if (ufd >= 0)  		close(ufd); -	} +out:  	free(str);  	return ret; @@ -3007,3 +2916,22 @@ end:  	return ret;  } +int copy_to_probe_trace_arg(struct probe_trace_arg *tvar, +			    struct perf_probe_arg *pvar) +{ +	tvar->value = strdup(pvar->var); +	if (tvar->value == NULL) +		return -ENOMEM; +	if (pvar->type) { +		tvar->type = strdup(pvar->type); +		if (tvar->type == NULL) +			return -ENOMEM; +	} +	if (pvar->name) { +		tvar->name = strdup(pvar->name); +		if (tvar->name == NULL) +			return -ENOMEM; +	} else +		tvar->name = NULL; +	return 0; +}  | 
