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