12 #include <sys/types.h>
14 #include <tools/le_byteshift.h>
16 #include <linux/elf.h>
17 #include <linux/types.h>
19 const char *outfilename;
21 /* Symbols that we need in vdso2c. */
26 sym_VDSO_FAKE_SECTION_TABLE_START,
27 sym_VDSO_FAKE_SECTION_TABLE_END,
30 const int special_pages[] = {
40 struct 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
47 [sym_VDSO_FAKE_SECTION_TABLE_END] = {
48 "VDSO_FAKE_SECTION_TABLE_END", false
50 {"VDSO32_NOTE_MASK", true},
51 {"VDSO32_SYSENTER_RETURN", true},
52 {"__kernel_vsyscall", true},
53 {"__kernel_sigreturn", true},
54 {"__kernel_rt_sigreturn", true},
57 __attribute__((format(printf, 1, 2))) __attribute__((noreturn))
58 static void fail(const char *format, ...)
62 fprintf(stderr, "Error: ");
63 vfprintf(stderr, format, ap);
70 * Evil macros for little-endian reads and writes
72 #define GLE(x, bits, ifnot) \
73 __builtin_choose_expr( \
74 (sizeof(*(x)) == bits/8), \
75 (__typeof__(*(x)))get_unaligned_le##bits(x), ifnot)
77 extern void bad_get_le(void);
79 __builtin_choose_expr(sizeof(*(x)) == 1, *(x), bad_get_le())
82 GLE(x, 64, GLE(x, 32, GLE(x, 16, LAST_GLE(x))))
84 #define PLE(x, val, bits, ifnot) \
85 __builtin_choose_expr( \
86 (sizeof(*(x)) == bits/8), \
87 put_unaligned_le##bits((val), (x)), ifnot)
89 extern void bad_put_le(void);
90 #define LAST_PLE(x, val) \
91 __builtin_choose_expr(sizeof(*(x)) == 1, *(x) = (val), bad_put_le())
93 #define PUT_LE(x, val) \
94 PLE(x, val, 64, PLE(x, val, 32, PLE(x, val, 16, LAST_PLE(x, val))))
97 #define NSYMS (sizeof(required_syms) / sizeof(required_syms[0]))
99 #define BITSFUNC3(name, bits) name##bits
100 #define BITSFUNC2(name, bits) BITSFUNC3(name, bits)
101 #define BITSFUNC(name) BITSFUNC2(name, ELF_BITS)
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)
115 static void go(void *addr, size_t len, FILE *outfile, const char *name)
117 Elf64_Ehdr *hdr = (Elf64_Ehdr *)addr;
119 if (hdr->e_ident[EI_CLASS] == ELFCLASS64) {
120 go64(addr, len, outfile, name);
121 } else if (hdr->e_ident[EI_CLASS] == ELFCLASS32) {
122 go32(addr, len, outfile, name);
124 fail("unknown ELF class\n");
128 int main(int argc, char **argv)
138 printf("Usage: vdso2c INPUT OUTPUT\n");
143 * Figure out the struct name. If we're writing to a .so file,
144 * generate raw output insted.
146 name = strdup(argv[2]);
147 namelen = strlen(name);
148 if (namelen >= 3 && !strcmp(name + namelen - 3, ".so")) {
151 tmp = strrchr(name, '/');
154 tmp = strchr(name, '.');
157 for (tmp = name; *tmp; tmp++)
162 fd = open(argv[1], O_RDONLY);
164 err(1, "%s", argv[1]);
166 len = lseek(fd, 0, SEEK_END);
167 if (len == (off_t)-1)
170 addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
171 if (addr == MAP_FAILED)
174 outfilename = argv[2];
175 outfile = fopen(outfilename, "w");
177 err(1, "%s", argv[2]);
179 go(addr, (size_t)len, outfile, name);