blob: f51390a1ed5162af88460fa8e35465dba24deb63 [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"
Adrian Hunter2a030682014-07-22 16:17:53 +030014#include "machine.h"
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020015#include "linux/string.h"
Jiri Olsa84f5d362014-07-14 23:46:48 +020016#include "debug.h"
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020017
Adrian Huntere477f3f2014-10-23 18:16:03 -030018/*
19 * Include definition of find_vdso_map() also used in perf-read-vdso.c for
20 * building perf-read-vdso32 and perf-read-vdsox32.
21 */
22#include "find-vdso-map.c"
23
Adrian Hunter30f4f812014-07-22 16:17:54 +030024#define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX"
25
26struct vdso_file {
27 bool found;
28 bool error;
29 char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)];
30 const char *dso_name;
31};
32
33struct vdso_info {
34 struct vdso_file vdso;
35};
36
Adrian Hunterd027b642014-07-23 14:23:00 +030037static struct vdso_info *vdso_info__new(void)
38{
39 static const struct vdso_info vdso_info_init = {
40 .vdso = {
41 .temp_file_name = VDSO__TEMP_FILE_NAME,
Adrian Hunter51682dc2014-07-22 16:17:57 +030042 .dso_name = DSO__NAME_VDSO,
Adrian Hunterd027b642014-07-23 14:23:00 +030043 },
44 };
Adrian Hunter30f4f812014-07-22 16:17:54 +030045
Adrian Hunterd027b642014-07-23 14:23:00 +030046 return memdup(&vdso_info_init, sizeof(vdso_info_init));
47}
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020048
Adrian Hunter30f4f812014-07-22 16:17:54 +030049static char *get_file(struct vdso_file *vdso_file)
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020050{
51 char *vdso = NULL;
52 char *buf = NULL;
53 void *start, *end;
54 size_t size;
55 int fd;
56
Adrian Hunter30f4f812014-07-22 16:17:54 +030057 if (vdso_file->found)
58 return vdso_file->temp_file_name;
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020059
Adrian Hunter30f4f812014-07-22 16:17:54 +030060 if (vdso_file->error || find_vdso_map(&start, &end))
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020061 return NULL;
62
63 size = end - start;
64
65 buf = memdup(start, size);
66 if (!buf)
67 return NULL;
68
Adrian Hunter30f4f812014-07-22 16:17:54 +030069 fd = mkstemp(vdso_file->temp_file_name);
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020070 if (fd < 0)
71 goto out;
72
73 if (size == (size_t) write(fd, buf, size))
Adrian Hunter30f4f812014-07-22 16:17:54 +030074 vdso = vdso_file->temp_file_name;
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020075
76 close(fd);
77
78 out:
79 free(buf);
80
Adrian Hunter30f4f812014-07-22 16:17:54 +030081 vdso_file->found = (vdso != NULL);
82 vdso_file->error = !vdso_file->found;
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020083 return vdso;
84}
85
Adrian Hunterd027b642014-07-23 14:23:00 +030086void vdso__exit(struct machine *machine)
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020087{
Adrian Hunterd027b642014-07-23 14:23:00 +030088 struct vdso_info *vdso_info = machine->vdso_info;
89
90 if (!vdso_info)
91 return;
92
Adrian Hunter30f4f812014-07-22 16:17:54 +030093 if (vdso_info->vdso.found)
94 unlink(vdso_info->vdso.temp_file_name);
Adrian Hunterd027b642014-07-23 14:23:00 +030095
96 zfree(&machine->vdso_info);
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +020097}
98
Adrian Hunter4f71f2a2014-07-22 16:17:56 +030099static struct dso *vdso__new(struct machine *machine, const char *short_name,
100 const char *long_name)
101{
102 struct dso *dso;
103
104 dso = dso__new(short_name);
105 if (dso != NULL) {
106 dsos__add(&machine->user_dsos, dso);
107 dso__set_long_name(dso, long_name, false);
108 }
109
110 return dso;
111}
112
Adrian Hunter5835edd2014-07-22 16:18:00 +0300113struct dso *vdso__dso_findnew(struct machine *machine,
114 struct thread *thread __maybe_unused)
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200115{
Adrian Hunterd027b642014-07-23 14:23:00 +0300116 struct vdso_info *vdso_info;
117 struct dso *dso;
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200118
Adrian Hunterd027b642014-07-23 14:23:00 +0300119 if (!machine->vdso_info)
120 machine->vdso_info = vdso_info__new();
121
122 vdso_info = machine->vdso_info;
123 if (!vdso_info)
124 return NULL;
125
Adrian Hunter51682dc2014-07-22 16:17:57 +0300126 dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true);
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200127 if (!dso) {
128 char *file;
129
Adrian Hunter30f4f812014-07-22 16:17:54 +0300130 file = get_file(&vdso_info->vdso);
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200131 if (!file)
132 return NULL;
133
Adrian Hunter51682dc2014-07-22 16:17:57 +0300134 dso = vdso__new(machine, DSO__NAME_VDSO, file);
Jiri Olsa7dbf4dc2012-09-10 18:50:19 +0200135 }
136
137 return dso;
138}
Adrian Hunter51682dc2014-07-22 16:17:57 +0300139
140bool dso__is_vdso(struct dso *dso)
141{
142 return !strcmp(dso->short_name, DSO__NAME_VDSO);
143}