]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - arch/x86/vdso/vdso2c.c
Merge remote-tracking branches 'spi/topic/adi-v3', 'spi/topic/atmel', 'spi/topic...
[mirror_ubuntu-artful-kernel.git] / arch / x86 / vdso / vdso2c.c
CommitLineData
6f121e54
AL
1#include <inttypes.h>
2#include <stdint.h>
3#include <unistd.h>
4#include <stdarg.h>
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8#include <fcntl.h>
9#include <err.h>
10
11#include <sys/mman.h>
12#include <sys/types.h>
13
bdfb9bcc
PA
14#include <tools/le_byteshift.h>
15
6f121e54
AL
16#include <linux/elf.h>
17#include <linux/types.h>
18
01156183
AL
19const char *outfilename;
20
6f121e54 21/* Symbols that we need in vdso2c. */
18d0a6fd
AL
22enum {
23 sym_vvar_page,
24 sym_hpet_page,
25 sym_end_mapping,
bfad381c
AL
26 sym_VDSO_FAKE_SECTION_TABLE_START,
27 sym_VDSO_FAKE_SECTION_TABLE_END,
18d0a6fd
AL
28};
29
30const int special_pages[] = {
31 sym_vvar_page,
32 sym_hpet_page,
33};
34
bfad381c
AL
35struct vdso_sym {
36 const char *name;
37 bool export;
38};
39
40struct vdso_sym required_syms[] = {
41 [sym_vvar_page] = {"vvar_page", true},
42 [sym_hpet_page] = {"hpet_page", true},
43 [sym_end_mapping] = {"end_mapping", true},
44 [sym_VDSO_FAKE_SECTION_TABLE_START] = {
45 "VDSO_FAKE_SECTION_TABLE_START", false
46 },
47 [sym_VDSO_FAKE_SECTION_TABLE_END] = {
48 "VDSO_FAKE_SECTION_TABLE_END", false
49 },
50 {"VDSO32_NOTE_MASK", true},
51 {"VDSO32_SYSENTER_RETURN", true},
52 {"__kernel_vsyscall", true},
53 {"__kernel_sigreturn", true},
54 {"__kernel_rt_sigreturn", true},
6f121e54
AL
55};
56
57__attribute__((format(printf, 1, 2))) __attribute__((noreturn))
58static void fail(const char *format, ...)
59{
60 va_list ap;
61 va_start(ap, format);
62 fprintf(stderr, "Error: ");
63 vfprintf(stderr, format, ap);
01156183 64 unlink(outfilename);
6f121e54
AL
65 exit(1);
66 va_end(ap);
67}
68
add4eed0 69/*
b4b31f61 70 * Evil macros for little-endian reads and writes
add4eed0 71 */
c191920f 72#define GLE(x, bits, ifnot) \
add4eed0 73 __builtin_choose_expr( \
bdfb9bcc
PA
74 (sizeof(*(x)) == bits/8), \
75 (__typeof__(*(x)))get_unaligned_le##bits(x), ifnot)
add4eed0 76
bdfb9bcc 77extern void bad_get_le(void);
b4b31f61 78#define LAST_GLE(x) \
bdfb9bcc 79 __builtin_choose_expr(sizeof(*(x)) == 1, *(x), bad_get_le())
add4eed0 80
c191920f 81#define GET_LE(x) \
b4b31f61
AL
82 GLE(x, 64, GLE(x, 32, GLE(x, 16, LAST_GLE(x))))
83
84#define PLE(x, val, bits, ifnot) \
85 __builtin_choose_expr( \
86 (sizeof(*(x)) == bits/8), \
87 put_unaligned_le##bits((val), (x)), ifnot)
88
89extern void bad_put_le(void);
90#define LAST_PLE(x, val) \
91 __builtin_choose_expr(sizeof(*(x)) == 1, *(x) = (val), bad_put_le())
92
93#define PUT_LE(x, val) \
94 PLE(x, val, 64, PLE(x, val, 32, PLE(x, val, 16, LAST_PLE(x, val))))
95
add4eed0 96
6f121e54
AL
97#define NSYMS (sizeof(required_syms) / sizeof(required_syms[0]))
98
c1979c37
AL
99#define BITSFUNC3(name, bits) name##bits
100#define BITSFUNC2(name, bits) BITSFUNC3(name, bits)
101#define BITSFUNC(name) BITSFUNC2(name, ELF_BITS)
102
103#define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x
104#define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x)
105#define ELF(x) ELF_BITS_XFORM(ELF_BITS, x)
106
107#define ELF_BITS 64
6f121e54 108#include "vdso2c.h"
c1979c37
AL
109#undef ELF_BITS
110
111#define ELF_BITS 32
6f121e54 112#include "vdso2c.h"
c1979c37 113#undef ELF_BITS
6f121e54 114
01156183 115static void go(void *addr, size_t len, FILE *outfile, const char *name)
6f121e54
AL
116{
117 Elf64_Ehdr *hdr = (Elf64_Ehdr *)addr;
118
119 if (hdr->e_ident[EI_CLASS] == ELFCLASS64) {
01156183 120 go64(addr, len, outfile, name);
6f121e54 121 } else if (hdr->e_ident[EI_CLASS] == ELFCLASS32) {
01156183 122 go32(addr, len, outfile, name);
6f121e54 123 } else {
01156183 124 fail("unknown ELF class\n");
6f121e54
AL
125 }
126}
127
128int main(int argc, char **argv)
129{
130 int fd;
131 off_t len;
132 void *addr;
133 FILE *outfile;
6f121e54
AL
134 char *name, *tmp;
135 int namelen;
136
137 if (argc != 3) {
138 printf("Usage: vdso2c INPUT OUTPUT\n");
139 return 1;
140 }
141
142 /*
143 * Figure out the struct name. If we're writing to a .so file,
144 * generate raw output insted.
145 */
146 name = strdup(argv[2]);
147 namelen = strlen(name);
148 if (namelen >= 3 && !strcmp(name + namelen - 3, ".so")) {
149 name = NULL;
150 } else {
151 tmp = strrchr(name, '/');
152 if (tmp)
153 name = tmp + 1;
154 tmp = strchr(name, '.');
155 if (tmp)
156 *tmp = '\0';
157 for (tmp = name; *tmp; tmp++)
158 if (*tmp == '-')
159 *tmp = '_';
160 }
161
162 fd = open(argv[1], O_RDONLY);
163 if (fd == -1)
164 err(1, "%s", argv[1]);
165
166 len = lseek(fd, 0, SEEK_END);
167 if (len == (off_t)-1)
168 err(1, "lseek");
169
170 addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
171 if (addr == MAP_FAILED)
172 err(1, "mmap");
173
01156183
AL
174 outfilename = argv[2];
175 outfile = fopen(outfilename, "w");
6f121e54
AL
176 if (!outfile)
177 err(1, "%s", argv[2]);
178
01156183 179 go(addr, (size_t)len, outfile, name);
6f121e54
AL
180
181 munmap(addr, len);
182 fclose(outfile);
183
01156183 184 return 0;
6f121e54 185}