summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/machine.c4
-rw-r--r--tools/perf/util/map.c23
-rw-r--r--tools/perf/util/map.h2
-rw-r--r--tools/perf/util/namespaces.c83
-rw-r--r--tools/perf/util/namespaces.h5
-rw-r--r--tools/perf/util/symbol.c70
6 files changed, 160 insertions, 27 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 2e9eb6aa3ce2..246b441110a1 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1392,7 +1392,7 @@ int machine__process_mmap2_event(struct machine *machine,
1392 1392
1393 map = map__new(machine, event->mmap2.start, 1393 map = map__new(machine, event->mmap2.start,
1394 event->mmap2.len, event->mmap2.pgoff, 1394 event->mmap2.len, event->mmap2.pgoff,
1395 event->mmap2.pid, event->mmap2.maj, 1395 event->mmap2.maj,
1396 event->mmap2.min, event->mmap2.ino, 1396 event->mmap2.min, event->mmap2.ino,
1397 event->mmap2.ino_generation, 1397 event->mmap2.ino_generation,
1398 event->mmap2.prot, 1398 event->mmap2.prot,
@@ -1450,7 +1450,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
1450 1450
1451 map = map__new(machine, event->mmap.start, 1451 map = map__new(machine, event->mmap.start,
1452 event->mmap.len, event->mmap.pgoff, 1452 event->mmap.len, event->mmap.pgoff,
1453 event->mmap.pid, 0, 0, 0, 0, 0, 0, 1453 0, 0, 0, 0, 0, 0,
1454 event->mmap.filename, 1454 event->mmap.filename,
1455 type, thread); 1455 type, thread);
1456 1456
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 5dc60ca5a294..bdaa0a4edc17 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -146,11 +146,13 @@ void map__init(struct map *map, enum map_type type,
146} 146}
147 147
148struct map *map__new(struct machine *machine, u64 start, u64 len, 148struct map *map__new(struct machine *machine, u64 start, u64 len,
149 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, 149 u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
150 u64 ino_gen, u32 prot, u32 flags, char *filename, 150 u64 ino_gen, u32 prot, u32 flags, char *filename,
151 enum map_type type, struct thread *thread) 151 enum map_type type, struct thread *thread)
152{ 152{
153 struct map *map = malloc(sizeof(*map)); 153 struct map *map = malloc(sizeof(*map));
154 struct nsinfo *nsi = NULL;
155 struct nsinfo *nnsi;
154 156
155 if (map != NULL) { 157 if (map != NULL) {
156 char newfilename[PATH_MAX]; 158 char newfilename[PATH_MAX];
@@ -168,9 +170,11 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
168 map->ino_generation = ino_gen; 170 map->ino_generation = ino_gen;
169 map->prot = prot; 171 map->prot = prot;
170 map->flags = flags; 172 map->flags = flags;
173 nsi = nsinfo__get(thread->nsinfo);
171 174
172 if ((anon || no_dso) && type == MAP__FUNCTION) { 175 if ((anon || no_dso) && nsi && type == MAP__FUNCTION) {
173 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); 176 snprintf(newfilename, sizeof(newfilename),
177 "/tmp/perf-%d.map", nsi->pid);
174 filename = newfilename; 178 filename = newfilename;
175 } 179 }
176 180
@@ -180,6 +184,16 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
180 } 184 }
181 185
182 if (vdso) { 186 if (vdso) {
187 /* The vdso maps are always on the host and not the
188 * container. Ensure that we don't use setns to look
189 * them up.
190 */
191 nnsi = nsinfo__copy(nsi);
192 if (nnsi) {
193 nsinfo__put(nsi);
194 nnsi->need_setns = false;
195 nsi = nnsi;
196 }
183 pgoff = 0; 197 pgoff = 0;
184 dso = machine__findnew_vdso(machine, thread); 198 dso = machine__findnew_vdso(machine, thread);
185 } else 199 } else
@@ -201,11 +215,12 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
201 if (type != MAP__FUNCTION) 215 if (type != MAP__FUNCTION)
202 dso__set_loaded(dso, map->type); 216 dso__set_loaded(dso, map->type);
203 } 217 }
204 dso->nsinfo = nsinfo__get(thread->nsinfo); 218 dso->nsinfo = nsi;
205 dso__put(dso); 219 dso__put(dso);
206 } 220 }
207 return map; 221 return map;
208out_delete: 222out_delete:
223 nsinfo__put(nsi);
209 free(map); 224 free(map);
210 return NULL; 225 return NULL;
211} 226}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index f9e8ac8a52cd..73aacf7a7dc4 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -141,7 +141,7 @@ struct thread;
141void map__init(struct map *map, enum map_type type, 141void map__init(struct map *map, enum map_type type,
142 u64 start, u64 end, u64 pgoff, struct dso *dso); 142 u64 start, u64 end, u64 pgoff, struct dso *dso);
143struct map *map__new(struct machine *machine, u64 start, u64 len, 143struct map *map__new(struct machine *machine, u64 start, u64 len,
144 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, 144 u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
145 u64 ino_gen, u32 prot, u32 flags, 145 u64 ino_gen, u32 prot, u32 flags,
146 char *filename, enum map_type type, struct thread *thread); 146 char *filename, enum map_type type, struct thread *thread);
147struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 147struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index bcc6bb19cf10..fc5f398779a4 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -40,18 +40,23 @@ void namespaces__free(struct namespaces *namespaces)
40 free(namespaces); 40 free(namespaces);
41} 41}
42 42
43void nsinfo__init(struct nsinfo *nsi) 43int nsinfo__init(struct nsinfo *nsi)
44{ 44{
45 char oldns[PATH_MAX]; 45 char oldns[PATH_MAX];
46 char spath[PATH_MAX];
46 char *newns = NULL; 47 char *newns = NULL;
48 char *statln = NULL;
47 struct stat old_stat; 49 struct stat old_stat;
48 struct stat new_stat; 50 struct stat new_stat;
51 FILE *f = NULL;
52 size_t linesz = 0;
53 int rv = -1;
49 54
50 if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX) 55 if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
51 return; 56 return rv;
52 57
53 if (asprintf(&newns, "/proc/%d/ns/mnt", nsi->pid) == -1) 58 if (asprintf(&newns, "/proc/%d/ns/mnt", nsi->pid) == -1)
54 return; 59 return rv;
55 60
56 if (stat(oldns, &old_stat) < 0) 61 if (stat(oldns, &old_stat) < 0)
57 goto out; 62 goto out;
@@ -68,24 +73,89 @@ void nsinfo__init(struct nsinfo *nsi)
68 newns = NULL; 73 newns = NULL;
69 } 74 }
70 75
76 /* If we're dealing with a process that is in a different PID namespace,
77 * attempt to work out the innermost tgid for the process.
78 */
79 if (snprintf(spath, PATH_MAX, "/proc/%d/status", nsi->pid) >= PATH_MAX)
80 goto out;
81
82 f = fopen(spath, "r");
83 if (f == NULL)
84 goto out;
85
86 while (getline(&statln, &linesz, f) != -1) {
87 /* Use tgid if CONFIG_PID_NS is not defined. */
88 if (strstr(statln, "Tgid:") != NULL) {
89 nsi->tgid = (pid_t)strtol(strrchr(statln, '\t'),
90 NULL, 10);
91 nsi->nstgid = nsi->tgid;
92 }
93
94 if (strstr(statln, "NStgid:") != NULL) {
95 nsi->nstgid = (pid_t)strtol(strrchr(statln, '\t'),
96 NULL, 10);
97 break;
98 }
99 }
100 rv = 0;
101
71out: 102out:
103 if (f != NULL)
104 (void) fclose(f);
105 free(statln);
72 free(newns); 106 free(newns);
107 return rv;
73} 108}
74 109
75struct nsinfo *nsinfo__new(pid_t pid) 110struct nsinfo *nsinfo__new(pid_t pid)
76{ 111{
77 struct nsinfo *nsi = calloc(1, sizeof(*nsi)); 112 struct nsinfo *nsi;
78 113
114 if (pid == 0)
115 return NULL;
116
117 nsi = calloc(1, sizeof(*nsi));
79 if (nsi != NULL) { 118 if (nsi != NULL) {
80 nsi->pid = pid; 119 nsi->pid = pid;
120 nsi->tgid = pid;
121 nsi->nstgid = pid;
81 nsi->need_setns = false; 122 nsi->need_setns = false;
82 nsinfo__init(nsi); 123 /* Init may fail if the process exits while we're trying to look
124 * at its proc information. In that case, save the pid but
125 * don't try to enter the namespace.
126 */
127 if (nsinfo__init(nsi) == -1)
128 nsi->need_setns = false;
129
83 refcount_set(&nsi->refcnt, 1); 130 refcount_set(&nsi->refcnt, 1);
84 } 131 }
85 132
86 return nsi; 133 return nsi;
87} 134}
88 135
136struct nsinfo *nsinfo__copy(struct nsinfo *nsi)
137{
138 struct nsinfo *nnsi;
139
140 nnsi = calloc(1, sizeof(*nnsi));
141 if (nnsi != NULL) {
142 nnsi->pid = nsi->pid;
143 nnsi->tgid = nsi->tgid;
144 nnsi->nstgid = nsi->nstgid;
145 nnsi->need_setns = nsi->need_setns;
146 if (nsi->mntns_path) {
147 nnsi->mntns_path = strdup(nsi->mntns_path);
148 if (!nnsi->mntns_path) {
149 free(nnsi);
150 return NULL;
151 }
152 }
153 refcount_set(&nnsi->refcnt, 1);
154 }
155
156 return nnsi;
157}
158
89void nsinfo__delete(struct nsinfo *nsi) 159void nsinfo__delete(struct nsinfo *nsi)
90{ 160{
91 zfree(&nsi->mntns_path); 161 zfree(&nsi->mntns_path);
@@ -105,7 +175,8 @@ void nsinfo__put(struct nsinfo *nsi)
105 nsinfo__delete(nsi); 175 nsinfo__delete(nsi);
106} 176}
107 177
108void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc) 178void nsinfo__mountns_enter(struct nsinfo *nsi,
179 struct nscookie *nc)
109{ 180{
110 char curpath[PATH_MAX]; 181 char curpath[PATH_MAX];
111 int oldns = -1; 182 int oldns = -1;
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
index b20f6ead7b2d..f19aa41119ae 100644
--- a/tools/perf/util/namespaces.h
+++ b/tools/perf/util/namespaces.h
@@ -26,6 +26,8 @@ void namespaces__free(struct namespaces *namespaces);
26 26
27struct nsinfo { 27struct nsinfo {
28 pid_t pid; 28 pid_t pid;
29 pid_t tgid;
30 pid_t nstgid;
29 bool need_setns; 31 bool need_setns;
30 char *mntns_path; 32 char *mntns_path;
31 refcount_t refcnt; 33 refcount_t refcnt;
@@ -36,8 +38,9 @@ struct nscookie {
36 int newns; 38 int newns;
37}; 39};
38 40
39void nsinfo__init(struct nsinfo *nsi); 41int nsinfo__init(struct nsinfo *nsi);
40struct nsinfo *nsinfo__new(pid_t pid); 42struct nsinfo *nsinfo__new(pid_t pid);
43struct nsinfo *nsinfo__copy(struct nsinfo *nsi);
41void nsinfo__delete(struct nsinfo *nsi); 44void nsinfo__delete(struct nsinfo *nsi);
42 45
43struct nsinfo *nsinfo__get(struct nsinfo *nsi); 46struct nsinfo *nsinfo__get(struct nsinfo *nsi);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 60a9eaa372ef..21c97cc41cfc 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -19,7 +19,6 @@
19#include "strlist.h" 19#include "strlist.h"
20#include "intlist.h" 20#include "intlist.h"
21#include "namespaces.h" 21#include "namespaces.h"
22#include "vdso.h"
23#include "header.h" 22#include "header.h"
24#include "path.h" 23#include "path.h"
25#include "sane_ctype.h" 24#include "sane_ctype.h"
@@ -1327,14 +1326,15 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
1327 return __dso__load_kallsyms(dso, filename, map, false); 1326 return __dso__load_kallsyms(dso, filename, map, false);
1328} 1327}
1329 1328
1330static int dso__load_perf_map(struct dso *dso, struct map *map) 1329static int dso__load_perf_map(const char *map_path, struct dso *dso,
1330 struct map *map)
1331{ 1331{
1332 char *line = NULL; 1332 char *line = NULL;
1333 size_t n; 1333 size_t n;
1334 FILE *file; 1334 FILE *file;
1335 int nr_syms = 0; 1335 int nr_syms = 0;
1336 1336
1337 file = fopen(dso->long_name, "r"); 1337 file = fopen(map_path, "r");
1338 if (file == NULL) 1338 if (file == NULL)
1339 goto out_failure; 1339 goto out_failure;
1340 1340
@@ -1426,6 +1426,45 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1426 } 1426 }
1427} 1427}
1428 1428
1429/* Checks for the existence of the perf-<pid>.map file in two different
1430 * locations. First, if the process is a separate mount namespace, check in
1431 * that namespace using the pid of the innermost pid namespace. If's not in a
1432 * namespace, or the file can't be found there, try in the mount namespace of
1433 * the tracing process using our view of its pid.
1434 */
1435static int dso__find_perf_map(char *filebuf, size_t bufsz,
1436 struct nsinfo **nsip)
1437{
1438 struct nscookie nsc;
1439 struct nsinfo *nsi;
1440 struct nsinfo *nnsi;
1441 int rc = -1;
1442
1443 nsi = *nsip;
1444
1445 if (nsi->need_setns) {
1446 snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nsi->nstgid);
1447 nsinfo__mountns_enter(nsi, &nsc);
1448 rc = access(filebuf, R_OK);
1449 nsinfo__mountns_exit(&nsc);
1450 if (rc == 0)
1451 return rc;
1452 }
1453
1454 nnsi = nsinfo__copy(nsi);
1455 if (nnsi) {
1456 nsinfo__put(nsi);
1457
1458 nnsi->need_setns = false;
1459 snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nnsi->tgid);
1460 *nsip = nnsi;
1461 rc = 0;
1462 }
1463
1464 return rc;
1465}
1466
1467
1429int dso__load(struct dso *dso, struct map *map) 1468int dso__load(struct dso *dso, struct map *map)
1430{ 1469{
1431 char *name; 1470 char *name;
@@ -1437,18 +1476,23 @@ int dso__load(struct dso *dso, struct map *map)
1437 struct symsrc ss_[2]; 1476 struct symsrc ss_[2];
1438 struct symsrc *syms_ss = NULL, *runtime_ss = NULL; 1477 struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
1439 bool kmod; 1478 bool kmod;
1479 bool perfmap;
1440 unsigned char build_id[BUILD_ID_SIZE]; 1480 unsigned char build_id[BUILD_ID_SIZE];
1441 struct nscookie nsc; 1481 struct nscookie nsc;
1482 char newmapname[PATH_MAX];
1483 const char *map_path = dso->long_name;
1484
1485 perfmap = strncmp(dso->name, "/tmp/perf-", 10) == 0;
1486 if (perfmap) {
1487 if (dso->nsinfo && (dso__find_perf_map(newmapname,
1488 sizeof(newmapname), &dso->nsinfo) == 0)) {
1489 map_path = newmapname;
1490 }
1491 }
1442 1492
1443 nsinfo__mountns_enter(dso->nsinfo, &nsc); 1493 nsinfo__mountns_enter(dso->nsinfo, &nsc);
1444 pthread_mutex_lock(&dso->lock); 1494 pthread_mutex_lock(&dso->lock);
1445 1495
1446 /* The vdso files always live in the host container, so don't go looking
1447 * for them in the container's mount namespace.
1448 */
1449 if (dso__is_vdso(dso))
1450 nsinfo__mountns_exit(&nsc);
1451
1452 /* check again under the dso->lock */ 1496 /* check again under the dso->lock */
1453 if (dso__loaded(dso, map->type)) { 1497 if (dso__loaded(dso, map->type)) {
1454 ret = 1; 1498 ret = 1;
@@ -1471,19 +1515,19 @@ int dso__load(struct dso *dso, struct map *map)
1471 1515
1472 dso->adjust_symbols = 0; 1516 dso->adjust_symbols = 0;
1473 1517
1474 if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { 1518 if (perfmap) {
1475 struct stat st; 1519 struct stat st;
1476 1520
1477 if (lstat(dso->name, &st) < 0) 1521 if (lstat(map_path, &st) < 0)
1478 goto out; 1522 goto out;
1479 1523
1480 if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) { 1524 if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) {
1481 pr_warning("File %s not owned by current user or root, " 1525 pr_warning("File %s not owned by current user or root, "
1482 "ignoring it (use -f to override).\n", dso->name); 1526 "ignoring it (use -f to override).\n", map_path);
1483 goto out; 1527 goto out;
1484 } 1528 }
1485 1529
1486 ret = dso__load_perf_map(dso, map); 1530 ret = dso__load_perf_map(map_path, dso, map);
1487 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : 1531 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
1488 DSO_BINARY_TYPE__NOT_FOUND; 1532 DSO_BINARY_TYPE__NOT_FOUND;
1489 goto out; 1533 goto out;