linux/tools/perf/util/vdso.c
<<
>>
Prefs
   1
   2#include <unistd.h>
   3#include <stdio.h>
   4#include <string.h>
   5#include <sys/types.h>
   6#include <sys/stat.h>
   7#include <fcntl.h>
   8#include <stdlib.h>
   9#include <linux/kernel.h>
  10
  11#include "vdso.h"
  12#include "util.h"
  13#include "symbol.h"
  14#include "linux/string.h"
  15
  16static bool vdso_found;
  17static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX";
  18
  19static int find_vdso_map(void **start, void **end)
  20{
  21        FILE *maps;
  22        char line[128];
  23        int found = 0;
  24
  25        maps = fopen("/proc/self/maps", "r");
  26        if (!maps) {
  27                pr_err("vdso: cannot open maps\n");
  28                return -1;
  29        }
  30
  31        while (!found && fgets(line, sizeof(line), maps)) {
  32                int m = -1;
  33
  34                /* We care only about private r-x mappings. */
  35                if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
  36                                start, end, &m))
  37                        continue;
  38                if (m < 0)
  39                        continue;
  40
  41                if (!strncmp(&line[m], VDSO__MAP_NAME,
  42                             sizeof(VDSO__MAP_NAME) - 1))
  43                        found = 1;
  44        }
  45
  46        fclose(maps);
  47        return !found;
  48}
  49
  50static char *get_file(void)
  51{
  52        char *vdso = NULL;
  53        char *buf = NULL;
  54        void *start, *end;
  55        size_t size;
  56        int fd;
  57
  58        if (vdso_found)
  59                return vdso_file;
  60
  61        if (find_vdso_map(&start, &end))
  62                return NULL;
  63
  64        size = end - start;
  65
  66        buf = memdup(start, size);
  67        if (!buf)
  68                return NULL;
  69
  70        fd = mkstemp(vdso_file);
  71        if (fd < 0)
  72                goto out;
  73
  74        if (size == (size_t) write(fd, buf, size))
  75                vdso = vdso_file;
  76
  77        close(fd);
  78
  79 out:
  80        free(buf);
  81
  82        vdso_found = (vdso != NULL);
  83        return vdso;
  84}
  85
  86void vdso__exit(void)
  87{
  88        if (vdso_found)
  89                unlink(vdso_file);
  90}
  91
  92struct dso *vdso__dso_findnew(struct list_head *head)
  93{
  94        struct dso *dso = dsos__find(head, VDSO__MAP_NAME, true);
  95
  96        if (!dso) {
  97                char *file;
  98
  99                file = get_file();
 100                if (!file)
 101                        return NULL;
 102
 103                dso = dso__new(VDSO__MAP_NAME);
 104                if (dso != NULL) {
 105                        dsos__add(head, dso);
 106                        dso__set_long_name(dso, file);
 107                }
 108        }
 109
 110        return dso;
 111}
 112