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

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@devboxSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 42bba263
...@@ -2557,41 +2557,60 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev, ...@@ -2557,41 +2557,60 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
return 0; return 0;
} }
static int __add_probe_trace_events(struct perf_probe_event *pev, static int __open_probe_file_and_namelist(bool uprobe,
struct probe_trace_event *tevs, struct strlist **namelist)
int ntevs, bool allow_suffix)
{ {
int i, fd, ret; int fd;
struct probe_trace_event *tev = NULL;
struct probe_cache *cache = NULL;
struct strlist *namelist;
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) if (fd < 0)
return fd; return fd;
/* Get current event names */ /* Get current event names */
namelist = probe_file__get_namelist(fd); *namelist = probe_file__get_namelist(fd);
if (!namelist) { if (!(*namelist)) {
pr_debug("Failed to get current event list.\n"); pr_debug("Failed to get current event list.\n");
ret = -ENOMEM; close(fd);
goto close_out; 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; ret = 0;
for (i = 0; i < ntevs; i++) { for (i = 0; i < ntevs; i++) {
tev = &tevs[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 */ /* Skip if the symbol is out of .text or blacklisted */
if (!tev->point.symbol && !pev->uprobes) if (!tev->point.symbol && !pev->uprobes)
continue; continue;
/* Set new name for tev (and update namelist) */ /* 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); allow_suffix);
if (ret < 0) if (ret < 0)
break; break;
ret = probe_file__add_event(fd, tev); ret = probe_file__add_event(fd[up], tev);
if (ret < 0) if (ret < 0)
break; break;
...@@ -2614,9 +2633,12 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, ...@@ -2614,9 +2633,12 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
probe_cache__delete(cache); probe_cache__delete(cache);
} }
strlist__delete(namelist);
close_out: close_out:
close(fd); for (up = 0; up < 2; up++) {
strlist__delete(namelist[up]);
if (fd[up] >= 0)
close(fd[up]);
}
return ret; return ret;
} }
...@@ -2989,6 +3011,48 @@ static int find_cached_events(struct perf_probe_event *pev, ...@@ -2989,6 +3011,48 @@ static int find_cached_events(struct perf_probe_event *pev,
return ret; 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, static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
struct probe_trace_event **tevs) struct probe_trace_event **tevs)
{ {
...@@ -2998,10 +3062,13 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev, ...@@ -2998,10 +3062,13 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
struct str_node *node; struct str_node *node;
int ret, i; int ret, i;
if (pev->sdt) if (pev->sdt) {
/* For SDT/cached events, we use special search functions */ /* For SDT/cached events, we use special search functions */
return find_cached_events(pev, tevs, pev->target); 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); cache = probe_cache__new(pev->target);
if (!cache) if (!cache)
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment