diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2014-06-06 17:30:37 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-06-06 17:54:54 -0400 |
commit | bdfb9bcc25005d06a9c301830bdeb7ca5a0b6ef7 (patch) | |
tree | 4598169d540d42653e4dbd320473cb3ea1f6592c /arch | |
parent | a0abcf2e8f8017051830f738ac1bf5ef42703243 (diff) |
x86, vdso: Use <tools/le_byteshift.h> for littleendian access
There are no standard functions for littleendian data (unlike
bigendian data.) Thus, use <tools/le_byteshift.h> to access
littleendian data members. Those are fairly inefficient, but it
doesn't matter for this purpose (and can be optimized later.) This
avoids portability problems.
Reported-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Tested-by: Andy Lutomirski <luto@amacapital.net>
Link: http://lkml.kernel.org/r/20140606140017.afb7f91142f66cb3dd13c186@linux-foundation.org
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/vdso/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/vdso/vdso2c.c | 10 | ||||
-rw-r--r-- | arch/x86/vdso/vdso2c.h | 62 |
3 files changed, 38 insertions, 35 deletions
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile index 895d4b16b7e3..9769df094035 100644 --- a/arch/x86/vdso/Makefile +++ b/arch/x86/vdso/Makefile | |||
@@ -59,6 +59,7 @@ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ | |||
59 | $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE | 59 | $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE |
60 | $(call if_changed,vdso) | 60 | $(call if_changed,vdso) |
61 | 61 | ||
62 | HOST_EXTRACFLAGS += -I$(srctree)/tools/include | ||
62 | hostprogs-y += vdso2c | 63 | hostprogs-y += vdso2c |
63 | 64 | ||
64 | quiet_cmd_vdso2c = VDSO2C $@ | 65 | quiet_cmd_vdso2c = VDSO2C $@ |
diff --git a/arch/x86/vdso/vdso2c.c b/arch/x86/vdso/vdso2c.c index deabaf5bfb89..450ac6eaf613 100644 --- a/arch/x86/vdso/vdso2c.c +++ b/arch/x86/vdso/vdso2c.c | |||
@@ -11,6 +11,8 @@ | |||
11 | #include <sys/mman.h> | 11 | #include <sys/mman.h> |
12 | #include <sys/types.h> | 12 | #include <sys/types.h> |
13 | 13 | ||
14 | #include <tools/le_byteshift.h> | ||
15 | |||
14 | #include <linux/elf.h> | 16 | #include <linux/elf.h> |
15 | #include <linux/types.h> | 17 | #include <linux/types.h> |
16 | 18 | ||
@@ -56,12 +58,12 @@ static void fail(const char *format, ...) | |||
56 | */ | 58 | */ |
57 | #define GLE(x, bits, ifnot) \ | 59 | #define GLE(x, bits, ifnot) \ |
58 | __builtin_choose_expr( \ | 60 | __builtin_choose_expr( \ |
59 | (sizeof(x) == bits/8), \ | 61 | (sizeof(*(x)) == bits/8), \ |
60 | (__typeof__(x))le##bits##toh(x), ifnot) | 62 | (__typeof__(*(x)))get_unaligned_le##bits(x), ifnot) |
61 | 63 | ||
62 | extern void bad_get_le(uint64_t); | 64 | extern void bad_get_le(void); |
63 | #define LAST_LE(x) \ | 65 | #define LAST_LE(x) \ |
64 | __builtin_choose_expr(sizeof(x) == 1, (x), bad_get_le(x)) | 66 | __builtin_choose_expr(sizeof(*(x)) == 1, *(x), bad_get_le()) |
65 | 67 | ||
66 | #define GET_LE(x) \ | 68 | #define GET_LE(x) \ |
67 | GLE(x, 64, GLE(x, 32, GLE(x, 16, LAST_LE(x)))) | 69 | GLE(x, 64, GLE(x, 32, GLE(x, 16, LAST_LE(x)))) |
diff --git a/arch/x86/vdso/vdso2c.h b/arch/x86/vdso/vdso2c.h index d1e99e1892c4..8a074637a576 100644 --- a/arch/x86/vdso/vdso2c.h +++ b/arch/x86/vdso/vdso2c.h | |||
@@ -18,27 +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 + GET_LE(hdr->e_phoff)); | 21 | Elf_Phdr *pt = (Elf_Phdr *)(addr + GET_LE(&hdr->e_phoff)); |
22 | 22 | ||
23 | /* Walk the segment table. */ | 23 | /* Walk the segment table. */ |
24 | for (i = 0; i < GET_LE(hdr->e_phnum); i++) { | 24 | for (i = 0; i < GET_LE(&hdr->e_phnum); i++) { |
25 | if (GET_LE(pt[i].p_type) == PT_LOAD) { | 25 | if (GET_LE(&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 (GET_LE(pt[i].p_offset) != 0 || | 29 | if (GET_LE(&pt[i].p_offset) != 0 || |
30 | GET_LE(pt[i].p_vaddr) != 0) | 30 | GET_LE(&pt[i].p_vaddr) != 0) |
31 | fail("PT_LOAD in wrong place\n"); | 31 | fail("PT_LOAD in wrong place\n"); |
32 | 32 | ||
33 | if (GET_LE(pt[i].p_memsz) != GET_LE(pt[i].p_filesz)) | 33 | if (GET_LE(&pt[i].p_memsz) != GET_LE(&pt[i].p_filesz)) |
34 | fail("cannot handle memsz != filesz\n"); | 34 | fail("cannot handle memsz != filesz\n"); |
35 | 35 | ||
36 | load_size = GET_LE(pt[i].p_memsz); | 36 | load_size = GET_LE(&pt[i].p_memsz); |
37 | found_load = 1; | 37 | found_load = 1; |
38 | } else if (GET_LE(pt[i].p_type) == PT_DYNAMIC) { | 38 | } else if (GET_LE(&pt[i].p_type) == PT_DYNAMIC) { |
39 | dyn = addr + GET_LE(pt[i].p_offset); | 39 | dyn = addr + GET_LE(&pt[i].p_offset); |
40 | dyn_end = addr + GET_LE(pt[i].p_offset) + | 40 | dyn_end = addr + GET_LE(&pt[i].p_offset) + |
41 | GET_LE(pt[i].p_memsz); | 41 | GET_LE(&pt[i].p_memsz); |
42 | } | 42 | } |
43 | } | 43 | } |
44 | if (!found_load) | 44 | if (!found_load) |
@@ -47,24 +47,24 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name) | |||
47 | 47 | ||
48 | /* Walk the dynamic table */ | 48 | /* Walk the dynamic table */ |
49 | for (i = 0; dyn + i < dyn_end && | 49 | for (i = 0; dyn + i < dyn_end && |
50 | GET_LE(dyn[i].d_tag) != DT_NULL; i++) { | 50 | GET_LE(&dyn[i].d_tag) != DT_NULL; i++) { |
51 | typeof(dyn[i].d_tag) tag = GET_LE(dyn[i].d_tag); | 51 | typeof(dyn[i].d_tag) tag = GET_LE(&dyn[i].d_tag); |
52 | if (tag == DT_REL || tag == DT_RELSZ || | 52 | if (tag == DT_REL || tag == DT_RELSZ || |
53 | tag == DT_RELENT || tag == DT_TEXTREL) | 53 | tag == DT_RELENT || tag == DT_TEXTREL) |
54 | fail("vdso image contains dynamic relocations\n"); | 54 | fail("vdso image contains dynamic relocations\n"); |
55 | } | 55 | } |
56 | 56 | ||
57 | /* Walk the section table */ | 57 | /* Walk the section table */ |
58 | secstrings_hdr = addr + GET_LE(hdr->e_shoff) + | 58 | secstrings_hdr = addr + GET_LE(&hdr->e_shoff) + |
59 | GET_LE(hdr->e_shentsize)*GET_LE(hdr->e_shstrndx); | 59 | GET_LE(&hdr->e_shentsize)*GET_LE(&hdr->e_shstrndx); |
60 | secstrings = addr + GET_LE(secstrings_hdr->sh_offset); | 60 | secstrings = addr + GET_LE(&secstrings_hdr->sh_offset); |
61 | for (i = 0; i < GET_LE(hdr->e_shnum); i++) { | 61 | for (i = 0; i < GET_LE(&hdr->e_shnum); i++) { |
62 | Elf_Shdr *sh = addr + GET_LE(hdr->e_shoff) + | 62 | Elf_Shdr *sh = addr + GET_LE(&hdr->e_shoff) + |
63 | GET_LE(hdr->e_shentsize) * i; | 63 | GET_LE(&hdr->e_shentsize) * i; |
64 | if (GET_LE(sh->sh_type) == SHT_SYMTAB) | 64 | if (GET_LE(&sh->sh_type) == SHT_SYMTAB) |
65 | symtab_hdr = sh; | 65 | symtab_hdr = sh; |
66 | 66 | ||
67 | if (!strcmp(secstrings + GET_LE(sh->sh_name), | 67 | if (!strcmp(secstrings + GET_LE(&sh->sh_name), |
68 | ".altinstructions")) | 68 | ".altinstructions")) |
69 | alt_sec = sh; | 69 | alt_sec = sh; |
70 | } | 70 | } |
@@ -72,25 +72,25 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name) | |||
72 | if (!symtab_hdr) | 72 | if (!symtab_hdr) |
73 | fail("no symbol table\n"); | 73 | fail("no symbol table\n"); |
74 | 74 | ||
75 | strtab_hdr = addr + GET_LE(hdr->e_shoff) + | 75 | strtab_hdr = addr + GET_LE(&hdr->e_shoff) + |
76 | GET_LE(hdr->e_shentsize) * GET_LE(symtab_hdr->sh_link); | 76 | GET_LE(&hdr->e_shentsize) * GET_LE(&symtab_hdr->sh_link); |
77 | 77 | ||
78 | /* Walk the symbol table */ | 78 | /* Walk the symbol table */ |
79 | for (i = 0; | 79 | for (i = 0; |
80 | i < GET_LE(symtab_hdr->sh_size) / GET_LE(symtab_hdr->sh_entsize); | 80 | i < GET_LE(&symtab_hdr->sh_size) / GET_LE(&symtab_hdr->sh_entsize); |
81 | i++) { | 81 | i++) { |
82 | int k; | 82 | int k; |
83 | Elf_Sym *sym = addr + GET_LE(symtab_hdr->sh_offset) + | 83 | Elf_Sym *sym = addr + GET_LE(&symtab_hdr->sh_offset) + |
84 | GET_LE(symtab_hdr->sh_entsize) * i; | 84 | GET_LE(&symtab_hdr->sh_entsize) * i; |
85 | const char *name = addr + GET_LE(strtab_hdr->sh_offset) + | 85 | const char *name = addr + GET_LE(&strtab_hdr->sh_offset) + |
86 | GET_LE(sym->st_name); | 86 | GET_LE(&sym->st_name); |
87 | for (k = 0; k < NSYMS; k++) { | 87 | for (k = 0; k < NSYMS; k++) { |
88 | if (!strcmp(name, required_syms[k])) { | 88 | if (!strcmp(name, required_syms[k])) { |
89 | if (syms[k]) { | 89 | if (syms[k]) { |
90 | fail("duplicate symbol %s\n", | 90 | fail("duplicate symbol %s\n", |
91 | required_syms[k]); | 91 | required_syms[k]); |
92 | } | 92 | } |
93 | syms[k] = GET_LE(sym->st_value); | 93 | syms[k] = GET_LE(&sym->st_value); |
94 | } | 94 | } |
95 | } | 95 | } |
96 | } | 96 | } |
@@ -150,9 +150,9 @@ static void GOFUNC(void *addr, size_t len, FILE *outfile, const char *name) | |||
150 | fprintf(outfile, "\t},\n"); | 150 | fprintf(outfile, "\t},\n"); |
151 | if (alt_sec) { | 151 | if (alt_sec) { |
152 | fprintf(outfile, "\t.alt = %lu,\n", | 152 | fprintf(outfile, "\t.alt = %lu,\n", |
153 | (unsigned long)GET_LE(alt_sec->sh_offset)); | 153 | (unsigned long)GET_LE(&alt_sec->sh_offset)); |
154 | fprintf(outfile, "\t.alt_len = %lu,\n", | 154 | fprintf(outfile, "\t.alt_len = %lu,\n", |
155 | (unsigned long)GET_LE(alt_sec->sh_size)); | 155 | (unsigned long)GET_LE(&alt_sec->sh_size)); |
156 | } | 156 | } |
157 | for (i = 0; i < NSYMS; i++) { | 157 | for (i = 0; i < NSYMS; i++) { |
158 | if (syms[i]) | 158 | if (syms[i]) |