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