map = map__new(machine, event->mmap2.start,
                        event->mmap2.len, event->mmap2.pgoff,
-                       event->mmap2.pid, event->mmap2.maj,
+                       event->mmap2.maj,
                        event->mmap2.min, event->mmap2.ino,
                        event->mmap2.ino_generation,
                        event->mmap2.prot,
 
        map = map__new(machine, event->mmap.start,
                        event->mmap.len, event->mmap.pgoff,
-                       event->mmap.pid, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0,
                        event->mmap.filename,
                        type, thread);
 
 
 }
 
 struct map *map__new(struct machine *machine, u64 start, u64 len,
-                    u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
+                    u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
                     u64 ino_gen, u32 prot, u32 flags, char *filename,
                     enum map_type type, struct thread *thread)
 {
        struct map *map = malloc(sizeof(*map));
+       struct nsinfo *nsi = NULL;
+       struct nsinfo *nnsi;
 
        if (map != NULL) {
                char newfilename[PATH_MAX];
                map->ino_generation = ino_gen;
                map->prot = prot;
                map->flags = flags;
+               nsi = nsinfo__get(thread->nsinfo);
 
-               if ((anon || no_dso) && type == MAP__FUNCTION) {
-                       snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
+               if ((anon || no_dso) && nsi && type == MAP__FUNCTION) {
+                       snprintf(newfilename, sizeof(newfilename),
+                                "/tmp/perf-%d.map", nsi->pid);
                        filename = newfilename;
                }
 
                }
 
                if (vdso) {
+                       /* The vdso maps are always on the host and not the
+                        * container.  Ensure that we don't use setns to look
+                        * them up.
+                        */
+                       nnsi = nsinfo__copy(nsi);
+                       if (nnsi) {
+                               nsinfo__put(nsi);
+                               nnsi->need_setns = false;
+                               nsi = nnsi;
+                       }
                        pgoff = 0;
                        dso = machine__findnew_vdso(machine, thread);
                } else
                        if (type != MAP__FUNCTION)
                                dso__set_loaded(dso, map->type);
                }
-               dso->nsinfo = nsinfo__get(thread->nsinfo);
+               dso->nsinfo = nsi;
                dso__put(dso);
        }
        return map;
 out_delete:
+       nsinfo__put(nsi);
        free(map);
        return NULL;
 }
 
 void map__init(struct map *map, enum map_type type,
               u64 start, u64 end, u64 pgoff, struct dso *dso);
 struct map *map__new(struct machine *machine, u64 start, u64 len,
-                    u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
+                    u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
                     u64 ino_gen, u32 prot, u32 flags,
                     char *filename, enum map_type type, struct thread *thread);
 struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
 
        free(namespaces);
 }
 
-void nsinfo__init(struct nsinfo *nsi)
+int nsinfo__init(struct nsinfo *nsi)
 {
        char oldns[PATH_MAX];
+       char spath[PATH_MAX];
        char *newns = NULL;
+       char *statln = NULL;
        struct stat old_stat;
        struct stat new_stat;
+       FILE *f = NULL;
+       size_t linesz = 0;
+       int rv = -1;
 
        if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
-               return;
+               return rv;
 
        if (asprintf(&newns, "/proc/%d/ns/mnt", nsi->pid) == -1)
-               return;
+               return rv;
 
        if (stat(oldns, &old_stat) < 0)
                goto out;
                newns = NULL;
        }
 
+       /* If we're dealing with a process that is in a different PID namespace,
+        * attempt to work out the innermost tgid for the process.
+        */
+       if (snprintf(spath, PATH_MAX, "/proc/%d/status", nsi->pid) >= PATH_MAX)
+               goto out;
+
+       f = fopen(spath, "r");
+       if (f == NULL)
+               goto out;
+
+       while (getline(&statln, &linesz, f) != -1) {
+               /* Use tgid if CONFIG_PID_NS is not defined. */
+               if (strstr(statln, "Tgid:") != NULL) {
+                       nsi->tgid = (pid_t)strtol(strrchr(statln, '\t'),
+                                                    NULL, 10);
+                       nsi->nstgid = nsi->tgid;
+               }
+
+               if (strstr(statln, "NStgid:") != NULL) {
+                       nsi->nstgid = (pid_t)strtol(strrchr(statln, '\t'),
+                                                    NULL, 10);
+                       break;
+               }
+       }
+       rv = 0;
+
 out:
+       if (f != NULL)
+               (void) fclose(f);
+       free(statln);
        free(newns);
+       return rv;
 }
 
 struct nsinfo *nsinfo__new(pid_t pid)
 {
-       struct nsinfo *nsi = calloc(1, sizeof(*nsi));
+       struct nsinfo *nsi;
 
+       if (pid == 0)
+               return NULL;
+
+       nsi = calloc(1, sizeof(*nsi));
        if (nsi != NULL) {
                nsi->pid = pid;
+               nsi->tgid = pid;
+               nsi->nstgid = pid;
                nsi->need_setns = false;
-               nsinfo__init(nsi);
+               /* Init may fail if the process exits while we're trying to look
+                * at its proc information.  In that case, save the pid but
+                * don't try to enter the namespace.
+                */
+               if (nsinfo__init(nsi) == -1)
+                       nsi->need_setns = false;
+
                refcount_set(&nsi->refcnt, 1);
        }
 
        return nsi;
 }
 
+struct nsinfo *nsinfo__copy(struct nsinfo *nsi)
+{
+       struct nsinfo *nnsi;
+
+       nnsi = calloc(1, sizeof(*nnsi));
+       if (nnsi != NULL) {
+               nnsi->pid = nsi->pid;
+               nnsi->tgid = nsi->tgid;
+               nnsi->nstgid = nsi->nstgid;
+               nnsi->need_setns = nsi->need_setns;
+               if (nsi->mntns_path) {
+                       nnsi->mntns_path = strdup(nsi->mntns_path);
+                       if (!nnsi->mntns_path) {
+                               free(nnsi);
+                               return NULL;
+                       }
+               }
+               refcount_set(&nnsi->refcnt, 1);
+       }
+
+       return nnsi;
+}
+
 void nsinfo__delete(struct nsinfo *nsi)
 {
        zfree(&nsi->mntns_path);
                nsinfo__delete(nsi);
 }
 
-void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)
+void nsinfo__mountns_enter(struct nsinfo *nsi,
+                                 struct nscookie *nc)
 {
        char curpath[PATH_MAX];
        int oldns = -1;
 
 
 struct nsinfo {
        pid_t                   pid;
+       pid_t                   tgid;
+       pid_t                   nstgid;
        bool                    need_setns;
        char                    *mntns_path;
        refcount_t              refcnt;
        int                     newns;
 };
 
-void nsinfo__init(struct nsinfo *nsi);
+int nsinfo__init(struct nsinfo *nsi);
 struct nsinfo *nsinfo__new(pid_t pid);
+struct nsinfo *nsinfo__copy(struct nsinfo *nsi);
 void nsinfo__delete(struct nsinfo *nsi);
 
 struct nsinfo *nsinfo__get(struct nsinfo *nsi);
 
 #include "strlist.h"
 #include "intlist.h"
 #include "namespaces.h"
-#include "vdso.h"
 #include "header.h"
 #include "path.h"
 #include "sane_ctype.h"
        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;
 
        }
 }
 
+/* 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;
        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);
 
-       /* The vdso files always live in the host container, so don't go looking
-        * for them in the container's mount namespace.
-        */
-       if (dso__is_vdso(dso))
-               nsinfo__mountns_exit(&nsc);
-
        /* check again under the dso->lock */
        if (dso__loaded(dso, map->type)) {
                ret = 1;
 
        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;