blob: 0ddb3b8a89ecff40fc2626ec5937d2c1bb62a2ca [file] [log] [blame]
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +02001
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{
Waiman Longf9ceffb2013-05-09 10:42:48 -040094 struct dso *dso = dsos__find(head, VDSO__MAP_NAME, true);
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020095
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);
Arnaldo Carvalho de Melo7e155d42013-12-10 15:08:44 -0300106 dso__set_long_name(dso, file, false);
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200107 }
108 }
109
110 return dso;
111}