diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-05-30 11:48:49 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-05-30 19:58:43 -0400 |
commit | add4eed0a2abea3951206f504330ee5daf8c178a (patch) | |
tree | 887492cf9d0f28135e9c353a5ceafe6d3e633247 /arch/x86/vdso | |
parent | 011561837dad082a92c0537db2d134e66419c6ad (diff) |
x86/vdso, build: Fix cross-compilation from big-endian architectures
This adds a macro GET(x) to convert x from big-endian to
little-endian. Hopefully I put it everywhere it needs to go and got
all the cases needed for everyone's linux/elf.h.
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
Link: http://lkml.kernel.org/r/2cf258df123cb24bad63c274c8563c050547d99d.1401464755.git.luto@amacapital.net
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/vdso')
-rw-r--r-- | arch/x86/vdso/vdso2c.c | 15 | ||||
-rw-r--r-- | arch/x86/vdso/vdso2c.h | 63 |
2 files changed, 50 insertions, 28 deletions
diff --git a/arch/x86/vdso/vdso2c.c b/arch/x86/vdso/vdso2c.c index fe8bfbf62612..de19ced6c87d 100644 --- a/arch/x86/vdso/vdso2c.c +++ b/arch/x86/vdso/vdso2c.c | |||
@@ -51,6 +51,21 @@ static void fail(const char *format, ...) | |||
51 | va_end(ap); | 51 | va_end(ap); |
52 | } | 52 | } |
53 | 53 | ||
54 | /* | ||
55 | * Evil macros to do a little-endian read. | ||
56 | */ | ||
57 | #define __GET_TYPE(x, type, bits, ifnot) \ | ||
58 | __builtin_choose_expr( \ | ||
59 | __builtin_types_compatible_p(typeof(x), type), \ | ||
60 | le##bits##toh((x)), ifnot) | ||
61 | |||
62 | extern void bad_get(uint64_t); | ||
63 | |||
64 | #define GET(x) \ | ||
65 | __GET_TYPE((x), __u32, 32, __GET_TYPE((x), __u64, 64, \ | ||
66 | __GET_TYPE((x), __s32, 32, __GET_TYPE((x), __s64, 64, \ | ||
67 | __GET_TYPE((x), __u16, 16, bad_get(x)))))) | ||
68 | |||
54 | #define NSYMS (sizeof(required_syms) / sizeof(required_syms[0])) | 69 | #define NSYMS (sizeof(required_syms) / sizeof(required_syms[0])) |
55 | 70 | ||
56 | #define BITS 64 | 71 | #define BITS 64 |
diff --git a/arch/x86/vdso/vdso2c.h b/arch/x86/vdso/vdso2c.h index 26a7c1fa7452..f0475dad2286 100644 --- a/arch/x86/vdso/vdso2c.h +++ b/arch/x86/vdso/vdso2c.h | |||
@@ -18,25 +18,27 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name) | |||
18 | const char *secstrings; | 18 | const char *secstrings; |
19 | uint64_t syms[NSYMS] = {}; | 19 | uint64_t syms[NSYMS] = {}; |
20 | 20 | ||
21 | Elf_Phdr *pt = (Elf_Phdr *)(addr + hdr->e_phoff); | 21 | Elf_Phdr *pt = (Elf_Phdr *)(addr + GET(hdr->e_phoff)); |
22 | 22 | ||
23 | /* Walk the segment table. */ | 23 | /* Walk the segment table. */ |
24 | for (i = 0; i < hdr->e_phnum; i++) { | 24 | for (i = 0; i < GET(hdr->e_phnum); i++) { |
25 | if (pt[i].p_type == PT_LOAD) { | 25 | if (GET(pt[i].p_type) == PT_LOAD) { |
26 | if (found_load) | 26 | if (found_load) |
27 | fail("multiple PT_LOAD segs\n"); | 27 | fail("multiple PT_LOAD segs\n"); |
28 | 28 | ||
29 | if (pt[i].p_offset != 0 || pt[i].p_vaddr != 0) | 29 | if (GET(pt[i].p_offset) != 0 || |
30 | GET(pt[i].p_vaddr) != 0) | ||
30 | fail("PT_LOAD in wrong place\n"); | 31 | fail("PT_LOAD in wrong place\n"); |
31 | 32 | ||
32 | if (pt[i].p_memsz != pt[i].p_filesz) | 33 | if (GET(pt[i].p_memsz) != GET(pt[i].p_filesz)) |
33 | fail("cannot handle memsz != filesz\n"); | 34 | fail("cannot handle memsz != filesz\n"); |
34 | 35 | ||
35 | load_size = pt[i].p_memsz; | 36 | load_size = GET(pt[i].p_memsz); |
36 | found_load = 1; | 37 | found_load = 1; |
37 | } else if (pt[i].p_type == PT_DYNAMIC) { | 38 | } else if (GET(pt[i].p_type) == PT_DYNAMIC) { |
38 | dyn = addr + pt[i].p_offset; | 39 | dyn = addr + GET(pt[i].p_offset); |
39 | dyn_end = addr + pt[i].p_offset + pt[i].p_memsz; | 40 | dyn_end = addr + GET(pt[i].p_offset) + |
41 | GET(pt[i].p_memsz); | ||
40 | } | 42 | } |
41 | } | 43 | } |
42 | if (!found_load) | 44 | if (!found_load) |
@@ -44,43 +46,48 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name) | |||
44 | data_size = (load_size + 4095) / 4096 * 4096; | 46 | data_size = (load_size + 4095) / 4096 * 4096; |
45 | 47 | ||
46 | /* Walk the dynamic table */ | 48 | /* Walk the dynamic table */ |
47 | for (i = 0; dyn + i < dyn_end && dyn[i].d_tag != DT_NULL; i++) { | 49 | for (i = 0; dyn + i < dyn_end && GET(dyn[i].d_tag) != DT_NULL; i++) { |
48 | if (dyn[i].d_tag == DT_REL || dyn[i].d_tag == DT_RELSZ || | 50 | typeof(dyn[i].d_tag) tag = GET(dyn[i].d_tag); |
49 | dyn[i].d_tag == DT_RELENT || dyn[i].d_tag == DT_TEXTREL) | 51 | if (tag == DT_REL || tag == DT_RELSZ || |
52 | tag == DT_RELENT || tag == DT_TEXTREL) | ||
50 | fail("vdso image contains dynamic relocations\n"); | 53 | fail("vdso image contains dynamic relocations\n"); |
51 | } | 54 | } |
52 | 55 | ||
53 | /* Walk the section table */ | 56 | /* Walk the section table */ |
54 | secstrings_hdr = addr + hdr->e_shoff + hdr->e_shentsize*hdr->e_shstrndx; | 57 | secstrings_hdr = addr + GET(hdr->e_shoff) + |
55 | secstrings = addr + secstrings_hdr->sh_offset; | 58 | GET(hdr->e_shentsize)*GET(hdr->e_shstrndx); |
56 | for (i = 0; i < hdr->e_shnum; i++) { | 59 | secstrings = addr + GET(secstrings_hdr->sh_offset); |
57 | Elf_Shdr *sh = addr + hdr->e_shoff + hdr->e_shentsize * i; | 60 | for (i = 0; i < GET(hdr->e_shnum); i++) { |
58 | if (sh->sh_type == SHT_SYMTAB) | 61 | Elf_Shdr *sh = addr + GET(hdr->e_shoff) + |
62 | GET(hdr->e_shentsize) * i; | ||
63 | if (GET(sh->sh_type) == SHT_SYMTAB) | ||
59 | symtab_hdr = sh; | 64 | symtab_hdr = sh; |
60 | 65 | ||
61 | if (!strcmp(secstrings + sh->sh_name, ".altinstructions")) | 66 | if (!strcmp(secstrings + GET(sh->sh_name), ".altinstructions")) |
62 | alt_sec = sh; | 67 | alt_sec = sh; |
63 | } | 68 | } |
64 | 69 | ||
65 | if (!symtab_hdr) | 70 | if (!symtab_hdr) |
66 | fail("no symbol table\n"); | 71 | fail("no symbol table\n"); |
67 | 72 | ||
68 | strtab_hdr = addr + hdr->e_shoff + | 73 | strtab_hdr = addr + GET(hdr->e_shoff) + |
69 | hdr->e_shentsize * symtab_hdr->sh_link; | 74 | GET(hdr->e_shentsize) * GET(symtab_hdr->sh_link); |
70 | 75 | ||
71 | /* Walk the symbol table */ | 76 | /* Walk the symbol table */ |
72 | for (i = 0; i < symtab_hdr->sh_size / symtab_hdr->sh_entsize; i++) { | 77 | for (i = 0; i < GET(symtab_hdr->sh_size) / GET(symtab_hdr->sh_entsize); |
78 | i++) { | ||
73 | int k; | 79 | int k; |
74 | Elf_Sym *sym = addr + symtab_hdr->sh_offset + | 80 | Elf_Sym *sym = addr + GET(symtab_hdr->sh_offset) + |
75 | symtab_hdr->sh_entsize * i; | 81 | GET(symtab_hdr->sh_entsize) * i; |
76 | const char *name = addr + strtab_hdr->sh_offset + sym->st_name; | 82 | const char *name = addr + GET(strtab_hdr->sh_offset) + |
83 | GET(sym->st_name); | ||
77 | for (k = 0; k < NSYMS; k++) { | 84 | for (k = 0; k < NSYMS; k++) { |
78 | if (!strcmp(name, required_syms[k])) { | 85 | if (!strcmp(name, required_syms[k])) { |
79 | if (syms[k]) { | 86 | if (syms[k]) { |
80 | fail("duplicate symbol %s\n", | 87 | fail("duplicate symbol %s\n", |
81 | required_syms[k]); | 88 | required_syms[k]); |
82 | } | 89 | } |
83 | syms[k] = sym->st_value; | 90 | syms[k] = GET(sym->st_value); |
84 | } | 91 | } |
85 | } | 92 | } |
86 | } | 93 | } |
@@ -106,7 +113,7 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name) | |||
106 | hdr->e_shoff = 0; | 113 | hdr->e_shoff = 0; |
107 | hdr->e_shentsize = 0; | 114 | hdr->e_shentsize = 0; |
108 | hdr->e_shnum = 0; | 115 | hdr->e_shnum = 0; |
109 | hdr->e_shstrndx = SHN_UNDEF; | 116 | hdr->e_shstrndx = htole16(SHN_UNDEF); |
110 | 117 | ||
111 | if (!name) { | 118 | if (!name) { |
112 | fwrite(addr, load_size, 1, outfile); | 119 | fwrite(addr, load_size, 1, outfile); |
@@ -140,9 +147,9 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name) | |||
140 | fprintf(outfile, "\t},\n"); | 147 | fprintf(outfile, "\t},\n"); |
141 | if (alt_sec) { | 148 | if (alt_sec) { |
142 | fprintf(outfile, "\t.alt = %lu,\n", | 149 | fprintf(outfile, "\t.alt = %lu,\n", |
143 | (unsigned long)alt_sec->sh_offset); | 150 | (unsigned long)GET(alt_sec->sh_offset)); |
144 | fprintf(outfile, "\t.alt_len = %lu,\n", | 151 | fprintf(outfile, "\t.alt_len = %lu,\n", |
145 | (unsigned long)alt_sec->sh_size); | 152 | (unsigned long)GET(alt_sec->sh_size)); |
146 | } | 153 | } |
147 | for (i = 0; i < NSYMS; i++) { | 154 | for (i = 0; i < NSYMS; i++) { |
148 | if (syms[i]) | 155 | if (syms[i]) |