blob: 290582452da36580a5944ffcc278945e11641f46 [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"
Jiri Olsa84f5d362014-07-14 23:46:48 +020015#include "debug.h"
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020016
17static bool vdso_found;
18static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX";
19
20static int find_vdso_map(void **start, void **end)
21{
22 FILE *maps;
23 char line[128];
24 int found = 0;
25
26 maps = fopen("/proc/self/maps", "r");
27 if (!maps) {
28 pr_err("vdso: cannot open maps\n");
29 return -1;
30 }
31
32 while (!found && fgets(line, sizeof(line), maps)) {
33 int m = -1;
34
35 /* We care only about private r-x mappings. */
36 if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
37 start, end, &m))
38 continue;
39 if (m < 0)
40 continue;
41
42 if (!strncmp(&line[m], VDSO__MAP_NAME,
43 sizeof(VDSO__MAP_NAME) - 1))
44 found = 1;
45 }
46
47 fclose(maps);
48 return !found;
49}
50
51static char *get_file(void)
52{
53 char *vdso = NULL;
54 char *buf = NULL;
55 void *start, *end;
56 size_t size;
57 int fd;
58
59 if (vdso_found)
60 return vdso_file;
61
62 if (find_vdso_map(&start, &end))
63 return NULL;
64
65 size = end - start;
66
67 buf = memdup(start, size);
68 if (!buf)
69 return NULL;
70
71 fd = mkstemp(vdso_file);
72 if (fd < 0)
73 goto out;
74
75 if (size == (size_t) write(fd, buf, size))
76 vdso = vdso_file;
77
78 close(fd);
79
80 out:
81 free(buf);
82
83 vdso_found = (vdso != NULL);
84 return vdso;
85}
86
87void vdso__exit(void)
88{
89 if (vdso_found)
90 unlink(vdso_file);
91}
92
93struct dso *vdso__dso_findnew(struct list_head *head)
94{
Waiman Longf9ceffb2013-05-09 10:42:48 -040095 struct dso *dso = dsos__find(head, VDSO__MAP_NAME, true);
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020096
97 if (!dso) {
98 char *file;
99
100 file = get_file();
101 if (!file)
102 return NULL;
103
104 dso = dso__new(VDSO__MAP_NAME);
105 if (dso != NULL) {
106 dsos__add(head, dso);
Arnaldo Carvalho de Melo7e155d42013-12-10 15:08:44 -0300107 dso__set_long_name(dso, file, false);
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200108 }
109 }
110
111 return dso;
112}