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
find_vdso_map(void ** start,void ** end)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
get_file(void)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
vdso__exit(void)86 void vdso__exit(void)
87 {
88 if (vdso_found)
89 unlink(vdso_file);
90 }
91
vdso__dso_findnew(struct list_head * head)92 struct 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