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;
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;
}
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)
{
struct str_node *node;
int ret, i;
- if (pev->sdt)
+ if (pev->sdt) {
/* 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);
if (!cache)
return 0;