Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1de7b8bf authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Arnaldo Carvalho de Melo
Browse files

perf probe: Search SDT/cached event from all probe caches



Search SDT/cached event from all probe caches if user doesn't pass any
binary. With this, we don't have to specify target binary for SDT and
named cached events (which start with %).

E.g. without this, a target binary must be passed with -x.

  # perf probe -x /usr/lib64/libc-2.20.so -a %sdt_libc:\*

With this change, we don't need it anymore.

  # perf probe -a %sdt_libc:\*

Signed-off-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/146831792812.17065.2353705982669445313.stgit@devbox


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 42bba263
Loading
Loading
Loading
Loading
+86 −19
Original line number Diff line number Diff line
@@ -2557,41 +2557,60 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
	return 0;
}

static int __add_probe_trace_events(struct perf_probe_event *pev,
				     struct probe_trace_event *tevs,
				     int ntevs, bool allow_suffix)
static int __open_probe_file_and_namelist(bool uprobe,
					  struct strlist **namelist)
{
	int i, fd, ret;
	struct probe_trace_event *tev = NULL;
	struct probe_cache *cache = NULL;
	struct strlist *namelist;
	int fd;

	fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0));
	fd = probe_file__open(PF_FL_RW | (uprobe ? PF_FL_UPROBE : 0));
	if (fd < 0)
		return fd;

	/* Get current event names */
	namelist = probe_file__get_namelist(fd);
	if (!namelist) {
	*namelist = probe_file__get_namelist(fd);
	if (!(*namelist)) {
		pr_debug("Failed to get current event list.\n");
		ret = -ENOMEM;
		goto close_out;
		close(fd);
		return -ENOMEM;
	}
	return fd;
}

static int __add_probe_trace_events(struct perf_probe_event *pev,
				     struct probe_trace_event *tevs,
				     int ntevs, bool allow_suffix)
{
	int i, fd[2] = {-1, -1}, up, ret;
	struct probe_trace_event *tev = NULL;
	struct probe_cache *cache = NULL;
	struct strlist *namelist[2] = {NULL, NULL};

	up = pev->uprobes ? 1 : 0;
	fd[up] = __open_probe_file_and_namelist(up, &namelist[up]);
	if (fd[up] < 0)
		return fd[up];

	ret = 0;
	for (i = 0; i < ntevs; i++) {
		tev = &tevs[i];
		up = tev->uprobes ? 1 : 0;
		if (fd[up] == -1) {	/* Open the kprobe/uprobe_events */
			fd[up] = __open_probe_file_and_namelist(up,
								&namelist[up]);
			if (fd[up] < 0)
				goto close_out;
		}
		/* Skip if the symbol is out of .text or blacklisted */
		if (!tev->point.symbol && !pev->uprobes)
			continue;

		/* Set new name for tev (and update namelist) */
		ret = probe_trace_event__set_name(tev, pev, namelist,
		ret = probe_trace_event__set_name(tev, pev, namelist[up],
						  allow_suffix);
		if (ret < 0)
			break;

		ret = probe_file__add_event(fd, tev);
		ret = probe_file__add_event(fd[up], tev);
		if (ret < 0)
			break;

@@ -2614,9 +2633,12 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
		probe_cache__delete(cache);
	}

	strlist__delete(namelist);
close_out:
	close(fd);
	for (up = 0; up < 2; up++) {
		strlist__delete(namelist[up]);
		if (fd[up] >= 0)
			close(fd[up]);
	}
	return ret;
}

@@ -2989,6 +3011,48 @@ static int find_cached_events(struct perf_probe_event *pev,
	return ret;
}

/* Try to find probe_trace_event from all probe caches */
static int find_cached_events_all(struct perf_probe_event *pev,
				   struct probe_trace_event **tevs)
{
	struct probe_trace_event *tmp_tevs = NULL;
	struct strlist *bidlist;
	struct str_node *nd;
	char *pathname;
	int ntevs = 0;
	int ret;

	/* Get the buildid list of all valid caches */
	bidlist = build_id_cache__list_all(true);
	if (!bidlist) {
		ret = -errno;
		pr_debug("Failed to get buildids: %d\n", ret);
		return ret;
	}

	ret = 0;
	strlist__for_each_entry(nd, bidlist) {
		pathname = build_id_cache__origname(nd->s);
		ret = find_cached_events(pev, &tmp_tevs, pathname);
		/* In the case of cnt == 0, we just skip it */
		if (ret > 0)
			ret = concat_probe_trace_events(tevs, &ntevs,
							&tmp_tevs, ret);
		free(pathname);
		if (ret < 0)
			break;
	}
	strlist__delete(bidlist);

	if (ret < 0) {
		clear_probe_trace_events(*tevs, ntevs);
		zfree(tevs);
	} else
		ret = ntevs;

	return ret;
}

static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
					      struct probe_trace_event **tevs)
{
@@ -2998,10 +3062,13 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
	struct str_node *node;
	int ret, i;

	if (pev->sdt)
	if (pev->sdt) {
		/* For SDT/cached events, we use special search functions */
		if (!pev->target)
			return find_cached_events_all(pev, tevs);
		else
			return find_cached_events(pev, tevs, pev->target);

	}
	cache = probe_cache__new(pev->target);
	if (!cache)
		return 0;