perf top: Fix -z option behavior
[deliverable/linux.git] / tools / perf / util / vdso.c
index 0ddb3b8a89ecff40fc2626ec5937d2c1bb62a2ca..adca69384fcc044eeea0a1a51580e8a29dea7058 100644 (file)
 #include "vdso.h"
 #include "util.h"
 #include "symbol.h"
+#include "machine.h"
 #include "linux/string.h"
+#include "debug.h"
 
-static bool vdso_found;
-static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX";
+#define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX"
+
+struct vdso_file {
+       bool found;
+       bool error;
+       char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)];
+       const char *dso_name;
+};
+
+struct vdso_info {
+       struct vdso_file vdso;
+};
+
+static struct vdso_info *vdso_info__new(void)
+{
+       static const struct vdso_info vdso_info_init = {
+               .vdso    = {
+                       .temp_file_name = VDSO__TEMP_FILE_NAME,
+                       .dso_name = DSO__NAME_VDSO,
+               },
+       };
+
+       return memdup(&vdso_info_init, sizeof(vdso_info_init));
+}
 
 static int find_vdso_map(void **start, void **end)
 {
@@ -47,7 +71,7 @@ static int find_vdso_map(void **start, void **end)
        return !found;
 }
 
-static char *get_file(void)
+static char *get_file(struct vdso_file *vdso_file)
 {
        char *vdso = NULL;
        char *buf = NULL;
@@ -55,10 +79,10 @@ static char *get_file(void)
        size_t size;
        int fd;
 
-       if (vdso_found)
-               return vdso_file;
+       if (vdso_file->found)
+               return vdso_file->temp_file_name;
 
-       if (find_vdso_map(&start, &end))
+       if (vdso_file->error || find_vdso_map(&start, &end))
                return NULL;
 
        size = end - start;
@@ -67,45 +91,78 @@ static char *get_file(void)
        if (!buf)
                return NULL;
 
-       fd = mkstemp(vdso_file);
+       fd = mkstemp(vdso_file->temp_file_name);
        if (fd < 0)
                goto out;
 
        if (size == (size_t) write(fd, buf, size))
-               vdso = vdso_file;
+               vdso = vdso_file->temp_file_name;
 
        close(fd);
 
  out:
        free(buf);
 
-       vdso_found = (vdso != NULL);
+       vdso_file->found = (vdso != NULL);
+       vdso_file->error = !vdso_file->found;
        return vdso;
 }
 
-void vdso__exit(void)
+void vdso__exit(struct machine *machine)
 {
-       if (vdso_found)
-               unlink(vdso_file);
+       struct vdso_info *vdso_info = machine->vdso_info;
+
+       if (!vdso_info)
+               return;
+
+       if (vdso_info->vdso.found)
+               unlink(vdso_info->vdso.temp_file_name);
+
+       zfree(&machine->vdso_info);
 }
 
-struct dso *vdso__dso_findnew(struct list_head *head)
+static struct dso *vdso__new(struct machine *machine, const char *short_name,
+                            const char *long_name)
 {
-       struct dso *dso = dsos__find(head, VDSO__MAP_NAME, true);
+       struct dso *dso;
 
+       dso = dso__new(short_name);
+       if (dso != NULL) {
+               dsos__add(&machine->user_dsos, dso);
+               dso__set_long_name(dso, long_name, false);
+       }
+
+       return dso;
+}
+
+struct dso *vdso__dso_findnew(struct machine *machine,
+                             struct thread *thread __maybe_unused)
+{
+       struct vdso_info *vdso_info;
+       struct dso *dso;
+
+       if (!machine->vdso_info)
+               machine->vdso_info = vdso_info__new();
+
+       vdso_info = machine->vdso_info;
+       if (!vdso_info)
+               return NULL;
+
+       dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true);
        if (!dso) {
                char *file;
 
-               file = get_file();
+               file = get_file(&vdso_info->vdso);
                if (!file)
                        return NULL;
 
-               dso = dso__new(VDSO__MAP_NAME);
-               if (dso != NULL) {
-                       dsos__add(head, dso);
-                       dso__set_long_name(dso, file, false);
-               }
+               dso = vdso__new(machine, DSO__NAME_VDSO, file);
        }
 
        return dso;
 }
+
+bool dso__is_vdso(struct dso *dso)
+{
+       return !strcmp(dso->short_name, DSO__NAME_VDSO);
+}
This page took 0.052195 seconds and 5 git commands to generate.