Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vdso.c
Go to the documentation of this file.
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 
16 static bool vdso_found;
17 static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX";
18 
19 static 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 
50 static 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 
86 void vdso__exit(void)
87 {
88  if (vdso_found)
89  unlink(vdso_file);
90 }
91 
93 {
94  struct dso *dso = dsos__find(head, VDSO__MAP_NAME);
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 }