summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r--tools/perf/util/symbol.c113
1 files changed, 95 insertions, 18 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e7a98db..5909ee4 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -18,6 +18,7 @@
#include "symbol.h"
#include "strlist.h"
#include "intlist.h"
+#include "namespaces.h"
#include "header.h"
#include "path.h"
#include "sane_ctype.h"
@@ -52,6 +53,7 @@ static enum dso_binary_type binary_type_symtab[] = {
DSO_BINARY_TYPE__JAVA_JIT,
DSO_BINARY_TYPE__DEBUGLINK,
DSO_BINARY_TYPE__BUILD_ID_CACHE,
+ DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
@@ -231,7 +233,8 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
goto out_unlock;
for (next = map__next(curr); next; next = map__next(curr)) {
- curr->end = next->start;
+ if (!curr->end)
+ curr->end = next->start;
curr = next;
}
@@ -239,7 +242,8 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
* We still haven't the actual symbols, so guess the
* last map final address.
*/
- curr->end = ~0ULL;
+ if (!curr->end)
+ curr->end = ~0ULL;
out_unlock:
pthread_rwlock_unlock(&maps->lock);
@@ -550,7 +554,7 @@ void dso__sort_by_name(struct dso *dso, enum map_type type)
int modules__parse(const char *filename, void *arg,
int (*process_module)(void *arg, const char *name,
- u64 start))
+ u64 start, u64 size))
{
char *line = NULL;
size_t n;
@@ -563,8 +567,8 @@ int modules__parse(const char *filename, void *arg,
while (1) {
char name[PATH_MAX];
- u64 start;
- char *sep;
+ u64 start, size;
+ char *sep, *endptr;
ssize_t line_len;
line_len = getline(&line, &n, file);
@@ -596,7 +600,11 @@ int modules__parse(const char *filename, void *arg,
scnprintf(name, sizeof(name), "[%s]", line);
- err = process_module(arg, name, start);
+ size = strtoul(sep + 1, &endptr, 0);
+ if (*endptr != ' ' && *endptr != '\t')
+ continue;
+
+ err = process_module(arg, name, start, size);
if (err)
break;
}
@@ -943,7 +951,8 @@ static struct module_info *find_module(const char *name,
return NULL;
}
-static int __read_proc_modules(void *arg, const char *name, u64 start)
+static int __read_proc_modules(void *arg, const char *name, u64 start,
+ u64 size __maybe_unused)
{
struct rb_root *modules = arg;
struct module_info *mi;
@@ -1325,14 +1334,15 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
return __dso__load_kallsyms(dso, filename, map, false);
}
-static int dso__load_perf_map(struct dso *dso, struct map *map)
+static int dso__load_perf_map(const char *map_path, struct dso *dso,
+ struct map *map)
{
char *line = NULL;
size_t n;
FILE *file;
int nr_syms = 0;
- file = fopen(dso->long_name, "r");
+ file = fopen(map_path, "r");
if (file == NULL)
goto out_failure;
@@ -1416,6 +1426,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
return kmod && dso->symtab_type == type;
case DSO_BINARY_TYPE__BUILD_ID_CACHE:
+ case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
return true;
case DSO_BINARY_TYPE__NOT_FOUND:
@@ -1424,6 +1435,44 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
}
}
+/* Checks for the existence of the perf-<pid>.map file in two different
+ * locations. First, if the process is a separate mount namespace, check in
+ * that namespace using the pid of the innermost pid namespace. If's not in a
+ * namespace, or the file can't be found there, try in the mount namespace of
+ * the tracing process using our view of its pid.
+ */
+static int dso__find_perf_map(char *filebuf, size_t bufsz,
+ struct nsinfo **nsip)
+{
+ struct nscookie nsc;
+ struct nsinfo *nsi;
+ struct nsinfo *nnsi;
+ int rc = -1;
+
+ nsi = *nsip;
+
+ if (nsi->need_setns) {
+ snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nsi->nstgid);
+ nsinfo__mountns_enter(nsi, &nsc);
+ rc = access(filebuf, R_OK);
+ nsinfo__mountns_exit(&nsc);
+ if (rc == 0)
+ return rc;
+ }
+
+ nnsi = nsinfo__copy(nsi);
+ if (nnsi) {
+ nsinfo__put(nsi);
+
+ nnsi->need_setns = false;
+ snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nnsi->tgid);
+ *nsip = nnsi;
+ rc = 0;
+ }
+
+ return rc;
+}
+
int dso__load(struct dso *dso, struct map *map)
{
char *name;
@@ -1435,8 +1484,21 @@ int dso__load(struct dso *dso, struct map *map)
struct symsrc ss_[2];
struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
bool kmod;
+ bool perfmap;
unsigned char build_id[BUILD_ID_SIZE];
+ struct nscookie nsc;
+ char newmapname[PATH_MAX];
+ const char *map_path = dso->long_name;
+
+ perfmap = strncmp(dso->name, "/tmp/perf-", 10) == 0;
+ if (perfmap) {
+ if (dso->nsinfo && (dso__find_perf_map(newmapname,
+ sizeof(newmapname), &dso->nsinfo) == 0)) {
+ map_path = newmapname;
+ }
+ }
+ nsinfo__mountns_enter(dso->nsinfo, &nsc);
pthread_mutex_lock(&dso->lock);
/* check again under the dso->lock */
@@ -1461,19 +1523,19 @@ int dso__load(struct dso *dso, struct map *map)
dso->adjust_symbols = 0;
- if (strncmp(dso->name, "/tmp/perf-", 10) == 0) {
+ if (perfmap) {
struct stat st;
- if (lstat(dso->name, &st) < 0)
+ if (lstat(map_path, &st) < 0)
goto out;
if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) {
pr_warning("File %s not owned by current user or root, "
- "ignoring it (use -f to override).\n", dso->name);
+ "ignoring it (use -f to override).\n", map_path);
goto out;
}
- ret = dso__load_perf_map(dso, map);
+ ret = dso__load_perf_map(map_path, dso, map);
dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
DSO_BINARY_TYPE__NOT_FOUND;
goto out;
@@ -1511,9 +1573,15 @@ int dso__load(struct dso *dso, struct map *map)
for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) {
struct symsrc *ss = &ss_[ss_pos];
bool next_slot = false;
+ bool is_reg;
+ bool nsexit;
+ int sirc;
enum dso_binary_type symtab_type = binary_type_symtab[i];
+ nsexit = (symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE ||
+ symtab_type == DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO);
+
if (!dso__is_compatible_symtab_type(dso, kmod, symtab_type))
continue;
@@ -1521,12 +1589,20 @@ int dso__load(struct dso *dso, struct map *map)
root_dir, name, PATH_MAX))
continue;
- if (!is_regular_file(name))
- continue;
+ if (nsexit)
+ nsinfo__mountns_exit(&nsc);
+
+ is_reg = is_regular_file(name);
+ sirc = symsrc__init(ss, dso, name, symtab_type);
- /* Name is now the name of the next image to try */
- if (symsrc__init(ss, dso, name, symtab_type) < 0)
+ if (nsexit)
+ nsinfo__mountns_enter(dso->nsinfo, &nsc);
+
+ if (!is_reg || sirc < 0) {
+ if (sirc >= 0)
+ symsrc__destroy(ss);
continue;
+ }
if (!syms_ss && symsrc__has_symtab(ss)) {
syms_ss = ss;
@@ -1584,6 +1660,7 @@ out_free:
out:
dso__set_loaded(dso, map->type);
pthread_mutex_unlock(&dso->lock);
+ nsinfo__mountns_exit(&nsc);
return ret;
}
@@ -1660,7 +1737,7 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map)
}
if (!symbol_conf.ignore_vmlinux_buildid)
- filename = dso__build_id_filename(dso, NULL, 0);
+ filename = dso__build_id_filename(dso, NULL, 0, false);
if (filename != NULL) {
err = dso__load_vmlinux(dso, map, filename, true);
if (err > 0)
OpenPOWER on IntegriCloud