Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'x86-vdso-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 vdso fixes from Peter Anvin:
"Fixes for x86/vdso.

One is a simple build fix for bigendian hosts, one is to make "make
vdso_install" work again, and the rest is about working around a bug
in Google's Go language -- two are documentation patches that improves
the sample code that the Go coders took, modified, and broke; the
other two implements a workaround that keeps existing Go binaries from
segfaulting at least"

* 'x86-vdso-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/vdso: Fix vdso_install
x86/vdso: Hack to keep 64-bit Go programs working
x86/vdso: Add PUT_LE to store little-endian values
x86/vdso/doc: Make vDSO examples more portable
x86/vdso/doc: Rename vdso_test.c to vdso_standalone_test_x86.c
x86, vdso: Remove one final use of htole16()

+279 -137
+40 -27
Documentation/vDSO/parse_vdso.c
··· 1 1 /* 2 2 * parse_vdso.c: Linux reference vDSO parser 3 - * Written by Andrew Lutomirski, 2011. 3 + * Written by Andrew Lutomirski, 2011-2014. 4 4 * 5 5 * This code is meant to be linked in to various programs that run on Linux. 6 6 * As such, it is available with as few restrictions as possible. This file ··· 11 11 * it starts a program. It works equally well in statically and dynamically 12 12 * linked binaries. 13 13 * 14 - * This code is tested on x86_64. In principle it should work on any 64-bit 14 + * This code is tested on x86. In principle it should work on any 15 15 * architecture that has a vDSO. 16 16 */ 17 17 18 18 #include <stdbool.h> 19 19 #include <stdint.h> 20 20 #include <string.h> 21 + #include <limits.h> 21 22 #include <elf.h> 22 23 23 24 /* ··· 46 45 47 46 48 47 /* And here's the code. */ 49 - 50 - #ifndef __x86_64__ 51 - # error Not yet ported to non-x86_64 architectures 48 + #ifndef ELF_BITS 49 + # if ULONG_MAX > 0xffffffffUL 50 + # define ELF_BITS 64 51 + # else 52 + # define ELF_BITS 32 53 + # endif 52 54 #endif 55 + 56 + #define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x 57 + #define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x) 58 + #define ELF(x) ELF_BITS_XFORM(ELF_BITS, x) 53 59 54 60 static struct vdso_info 55 61 { ··· 67 59 uintptr_t load_offset; /* load_addr - recorded vaddr */ 68 60 69 61 /* Symbol table */ 70 - Elf64_Sym *symtab; 62 + ELF(Sym) *symtab; 71 63 const char *symstrings; 72 - Elf64_Word *bucket, *chain; 73 - Elf64_Word nbucket, nchain; 64 + ELF(Word) *bucket, *chain; 65 + ELF(Word) nbucket, nchain; 74 66 75 67 /* Version table */ 76 - Elf64_Versym *versym; 77 - Elf64_Verdef *verdef; 68 + ELF(Versym) *versym; 69 + ELF(Verdef) *verdef; 78 70 } vdso_info; 79 71 80 72 /* Straight from the ELF specification. */ ··· 100 92 101 93 vdso_info.load_addr = base; 102 94 103 - Elf64_Ehdr *hdr = (Elf64_Ehdr*)base; 104 - Elf64_Phdr *pt = (Elf64_Phdr*)(vdso_info.load_addr + hdr->e_phoff); 105 - Elf64_Dyn *dyn = 0; 95 + ELF(Ehdr) *hdr = (ELF(Ehdr)*)base; 96 + if (hdr->e_ident[EI_CLASS] != 97 + (ELF_BITS == 32 ? ELFCLASS32 : ELFCLASS64)) { 98 + return; /* Wrong ELF class -- check ELF_BITS */ 99 + } 100 + 101 + ELF(Phdr) *pt = (ELF(Phdr)*)(vdso_info.load_addr + hdr->e_phoff); 102 + ELF(Dyn) *dyn = 0; 106 103 107 104 /* 108 105 * We need two things from the segment table: the load offset ··· 121 108 + (uintptr_t)pt[i].p_offset 122 109 - (uintptr_t)pt[i].p_vaddr; 123 110 } else if (pt[i].p_type == PT_DYNAMIC) { 124 - dyn = (Elf64_Dyn*)(base + pt[i].p_offset); 111 + dyn = (ELF(Dyn)*)(base + pt[i].p_offset); 125 112 } 126 113 } 127 114 ··· 131 118 /* 132 119 * Fish out the useful bits of the dynamic table. 133 120 */ 134 - Elf64_Word *hash = 0; 121 + ELF(Word) *hash = 0; 135 122 vdso_info.symstrings = 0; 136 123 vdso_info.symtab = 0; 137 124 vdso_info.versym = 0; ··· 144 131 + vdso_info.load_offset); 145 132 break; 146 133 case DT_SYMTAB: 147 - vdso_info.symtab = (Elf64_Sym *) 134 + vdso_info.symtab = (ELF(Sym) *) 148 135 ((uintptr_t)dyn[i].d_un.d_ptr 149 136 + vdso_info.load_offset); 150 137 break; 151 138 case DT_HASH: 152 - hash = (Elf64_Word *) 139 + hash = (ELF(Word) *) 153 140 ((uintptr_t)dyn[i].d_un.d_ptr 154 141 + vdso_info.load_offset); 155 142 break; 156 143 case DT_VERSYM: 157 - vdso_info.versym = (Elf64_Versym *) 144 + vdso_info.versym = (ELF(Versym) *) 158 145 ((uintptr_t)dyn[i].d_un.d_ptr 159 146 + vdso_info.load_offset); 160 147 break; 161 148 case DT_VERDEF: 162 - vdso_info.verdef = (Elf64_Verdef *) 149 + vdso_info.verdef = (ELF(Verdef) *) 163 150 ((uintptr_t)dyn[i].d_un.d_ptr 164 151 + vdso_info.load_offset); 165 152 break; ··· 181 168 vdso_info.valid = true; 182 169 } 183 170 184 - static bool vdso_match_version(Elf64_Versym ver, 185 - const char *name, Elf64_Word hash) 171 + static bool vdso_match_version(ELF(Versym) ver, 172 + const char *name, ELF(Word) hash) 186 173 { 187 174 /* 188 175 * This is a helper function to check if the version indexed by ··· 201 188 202 189 /* First step: find the version definition */ 203 190 ver &= 0x7fff; /* Apparently bit 15 means "hidden" */ 204 - Elf64_Verdef *def = vdso_info.verdef; 191 + ELF(Verdef) *def = vdso_info.verdef; 205 192 while(true) { 206 193 if ((def->vd_flags & VER_FLG_BASE) == 0 207 194 && (def->vd_ndx & 0x7fff) == ver) ··· 210 197 if (def->vd_next == 0) 211 198 return false; /* No definition. */ 212 199 213 - def = (Elf64_Verdef *)((char *)def + def->vd_next); 200 + def = (ELF(Verdef) *)((char *)def + def->vd_next); 214 201 } 215 202 216 203 /* Now figure out whether it matches. */ 217 - Elf64_Verdaux *aux = (Elf64_Verdaux*)((char *)def + def->vd_aux); 204 + ELF(Verdaux) *aux = (ELF(Verdaux)*)((char *)def + def->vd_aux); 218 205 return def->vd_hash == hash 219 206 && !strcmp(name, vdso_info.symstrings + aux->vda_name); 220 207 } ··· 226 213 return 0; 227 214 228 215 ver_hash = elf_hash(version); 229 - Elf64_Word chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket]; 216 + ELF(Word) chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket]; 230 217 231 218 for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) { 232 - Elf64_Sym *sym = &vdso_info.symtab[chain]; 219 + ELF(Sym) *sym = &vdso_info.symtab[chain]; 233 220 234 221 /* Check for a defined global or weak function w/ right name. */ 235 222 if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC) ··· 256 243 257 244 void vdso_init_from_auxv(void *auxv) 258 245 { 259 - Elf64_auxv_t *elf_auxv = auxv; 246 + ELF(auxv_t) *elf_auxv = auxv; 260 247 for (int i = 0; elf_auxv[i].a_type != AT_NULL; i++) 261 248 { 262 249 if (elf_auxv[i].a_type == AT_SYSINFO_EHDR) {
+128
Documentation/vDSO/vdso_standalone_test_x86.c
··· 1 + /* 2 + * vdso_test.c: Sample code to test parse_vdso.c on x86 3 + * Copyright (c) 2011-2014 Andy Lutomirski 4 + * Subject to the GNU General Public License, version 2 5 + * 6 + * You can amuse yourself by compiling with: 7 + * gcc -std=gnu99 -nostdlib 8 + * -Os -fno-asynchronous-unwind-tables -flto -lgcc_s 9 + * vdso_standalone_test_x86.c parse_vdso.c 10 + * to generate a small binary. On x86_64, you can omit -lgcc_s 11 + * if you want the binary to be completely standalone. 12 + */ 13 + 14 + #include <sys/syscall.h> 15 + #include <sys/time.h> 16 + #include <unistd.h> 17 + #include <stdint.h> 18 + 19 + extern void *vdso_sym(const char *version, const char *name); 20 + extern void vdso_init_from_sysinfo_ehdr(uintptr_t base); 21 + extern void vdso_init_from_auxv(void *auxv); 22 + 23 + /* We need a libc functions... */ 24 + int strcmp(const char *a, const char *b) 25 + { 26 + /* This implementation is buggy: it never returns -1. */ 27 + while (*a || *b) { 28 + if (*a != *b) 29 + return 1; 30 + if (*a == 0 || *b == 0) 31 + return 1; 32 + a++; 33 + b++; 34 + } 35 + 36 + return 0; 37 + } 38 + 39 + /* ...and two syscalls. This is x86-specific. */ 40 + static inline long x86_syscall3(long nr, long a0, long a1, long a2) 41 + { 42 + long ret; 43 + #ifdef __x86_64__ 44 + asm volatile ("syscall" : "=a" (ret) : "a" (nr), 45 + "D" (a0), "S" (a1), "d" (a2) : 46 + "cc", "memory", "rcx", 47 + "r8", "r9", "r10", "r11" ); 48 + #else 49 + asm volatile ("int $0x80" : "=a" (ret) : "a" (nr), 50 + "b" (a0), "c" (a1), "d" (a2) : 51 + "cc", "memory" ); 52 + #endif 53 + return ret; 54 + } 55 + 56 + static inline long linux_write(int fd, const void *data, size_t len) 57 + { 58 + return x86_syscall3(__NR_write, fd, (long)data, (long)len); 59 + } 60 + 61 + static inline void linux_exit(int code) 62 + { 63 + x86_syscall3(__NR_exit, code, 0, 0); 64 + } 65 + 66 + void to_base10(char *lastdig, uint64_t n) 67 + { 68 + while (n) { 69 + *lastdig = (n % 10) + '0'; 70 + n /= 10; 71 + lastdig--; 72 + } 73 + } 74 + 75 + __attribute__((externally_visible)) void c_main(void **stack) 76 + { 77 + /* Parse the stack */ 78 + long argc = (long)*stack; 79 + stack += argc + 2; 80 + 81 + /* Now we're pointing at the environment. Skip it. */ 82 + while(*stack) 83 + stack++; 84 + stack++; 85 + 86 + /* Now we're pointing at auxv. Initialize the vDSO parser. */ 87 + vdso_init_from_auxv((void *)stack); 88 + 89 + /* Find gettimeofday. */ 90 + typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz); 91 + gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday"); 92 + 93 + if (!gtod) 94 + linux_exit(1); 95 + 96 + struct timeval tv; 97 + long ret = gtod(&tv, 0); 98 + 99 + if (ret == 0) { 100 + char buf[] = "The time is .000000\n"; 101 + to_base10(buf + 31, tv.tv_sec); 102 + to_base10(buf + 38, tv.tv_usec); 103 + linux_write(1, buf, sizeof(buf) - 1); 104 + } else { 105 + linux_exit(ret); 106 + } 107 + 108 + linux_exit(0); 109 + } 110 + 111 + /* 112 + * This is the real entry point. It passes the initial stack into 113 + * the C entry point. 114 + */ 115 + asm ( 116 + ".text\n" 117 + ".global _start\n" 118 + ".type _start,@function\n" 119 + "_start:\n\t" 120 + #ifdef __x86_64__ 121 + "mov %rsp,%rdi\n\t" 122 + "jmp c_main" 123 + #else 124 + "push %esp\n\t" 125 + "call c_main\n\t" 126 + "int $3" 127 + #endif 128 + );
+24 -83
Documentation/vDSO/vdso_test.c
··· 1 1 /* 2 - * vdso_test.c: Sample code to test parse_vdso.c on x86_64 3 - * Copyright (c) 2011 Andy Lutomirski 2 + * vdso_test.c: Sample code to test parse_vdso.c 3 + * Copyright (c) 2014 Andy Lutomirski 4 4 * Subject to the GNU General Public License, version 2 5 5 * 6 - * You can amuse yourself by compiling with: 7 - * gcc -std=gnu99 -nostdlib 8 - * -Os -fno-asynchronous-unwind-tables -flto 9 - * vdso_test.c parse_vdso.c -o vdso_test 10 - * to generate a small binary with no dependencies at all. 6 + * Compile with: 7 + * gcc -std=gnu99 vdso_test.c parse_vdso.c 8 + * 9 + * Tested on x86, 32-bit and 64-bit. It may work on other architectures, too. 11 10 */ 12 11 13 - #include <sys/syscall.h> 14 - #include <sys/time.h> 15 - #include <unistd.h> 16 12 #include <stdint.h> 13 + #include <elf.h> 14 + #include <stdio.h> 15 + #include <sys/auxv.h> 16 + #include <sys/time.h> 17 17 18 18 extern void *vdso_sym(const char *version, const char *name); 19 19 extern void vdso_init_from_sysinfo_ehdr(uintptr_t base); 20 20 extern void vdso_init_from_auxv(void *auxv); 21 21 22 - /* We need a libc functions... */ 23 - int strcmp(const char *a, const char *b) 22 + int main(int argc, char **argv) 24 23 { 25 - /* This implementation is buggy: it never returns -1. */ 26 - while (*a || *b) { 27 - if (*a != *b) 28 - return 1; 29 - if (*a == 0 || *b == 0) 30 - return 1; 31 - a++; 32 - b++; 24 + unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR); 25 + if (!sysinfo_ehdr) { 26 + printf("AT_SYSINFO_EHDR is not present!\n"); 27 + return 0; 33 28 } 34 29 35 - return 0; 36 - } 37 - 38 - /* ...and two syscalls. This is x86_64-specific. */ 39 - static inline long linux_write(int fd, const void *data, size_t len) 40 - { 41 - 42 - long ret; 43 - asm volatile ("syscall" : "=a" (ret) : "a" (__NR_write), 44 - "D" (fd), "S" (data), "d" (len) : 45 - "cc", "memory", "rcx", 46 - "r8", "r9", "r10", "r11" ); 47 - return ret; 48 - } 49 - 50 - static inline void linux_exit(int code) 51 - { 52 - asm volatile ("syscall" : : "a" (__NR_exit), "D" (code)); 53 - } 54 - 55 - void to_base10(char *lastdig, uint64_t n) 56 - { 57 - while (n) { 58 - *lastdig = (n % 10) + '0'; 59 - n /= 10; 60 - lastdig--; 61 - } 62 - } 63 - 64 - __attribute__((externally_visible)) void c_main(void **stack) 65 - { 66 - /* Parse the stack */ 67 - long argc = (long)*stack; 68 - stack += argc + 2; 69 - 70 - /* Now we're pointing at the environment. Skip it. */ 71 - while(*stack) 72 - stack++; 73 - stack++; 74 - 75 - /* Now we're pointing at auxv. Initialize the vDSO parser. */ 76 - vdso_init_from_auxv((void *)stack); 30 + vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR)); 77 31 78 32 /* Find gettimeofday. */ 79 33 typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz); 80 34 gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday"); 81 35 82 - if (!gtod) 83 - linux_exit(1); 36 + if (!gtod) { 37 + printf("Could not find __vdso_gettimeofday\n"); 38 + return 1; 39 + } 84 40 85 41 struct timeval tv; 86 42 long ret = gtod(&tv, 0); 87 43 88 44 if (ret == 0) { 89 - char buf[] = "The time is .000000\n"; 90 - to_base10(buf + 31, tv.tv_sec); 91 - to_base10(buf + 38, tv.tv_usec); 92 - linux_write(1, buf, sizeof(buf) - 1); 45 + printf("The time is %lld.%06lld\n", 46 + (long long)tv.tv_sec, (long long)tv.tv_usec); 93 47 } else { 94 - linux_exit(ret); 48 + printf("__vdso_gettimeofday failed\n"); 95 49 } 96 50 97 - linux_exit(0); 51 + return 0; 98 52 } 99 - 100 - /* 101 - * This is the real entry point. It passes the initial stack into 102 - * the C entry point. 103 - */ 104 - asm ( 105 - ".text\n" 106 - ".global _start\n" 107 - ".type _start,@function\n" 108 - "_start:\n\t" 109 - "mov %rsp,%rdi\n\t" 110 - "jmp c_main" 111 - );
+21 -19
arch/x86/vdso/Makefile
··· 9 9 VDSO32-$(CONFIG_X86_32) := y 10 10 VDSO32-$(CONFIG_COMPAT) := y 11 11 12 - vdso-install-$(VDSO64-y) += vdso.so 13 - vdso-install-$(VDSOX32-y) += vdsox32.so 14 - vdso-install-$(VDSO32-y) += $(vdso32-images) 15 - 16 - 17 12 # files to link into the vdso 18 - vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o 19 - 20 - vobjs-$(VDSOX32-y) += $(vobjx32s-compat) 21 - 22 - # Filter out x32 objects. 23 - vobj64s := $(filter-out $(vobjx32s-compat),$(vobjs-y)) 13 + vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o vdso-fakesections.o 14 + vobjs-nox32 := vdso-fakesections.o 24 15 25 16 # files to link into kernel 26 17 obj-y += vma.o ··· 25 34 26 35 obj-$(VDSO32-y) += vdso32-setup.o 27 36 28 - vobjs := $(foreach F,$(vobj64s),$(obj)/$F) 37 + vobjs := $(foreach F,$(vobjs-y),$(obj)/$F) 29 38 30 39 $(obj)/vdso.o: $(obj)/vdso.so 31 40 ··· 95 104 -Wl,-z,max-page-size=4096 \ 96 105 -Wl,-z,common-page-size=4096 97 106 98 - vobjx32s-y := $(vobj64s:.o=-x32.o) 107 + # 64-bit objects to re-brand as x32 108 + vobjs64-for-x32 := $(filter-out $(vobjs-nox32),$(vobjs-y)) 109 + 110 + # x32-rebranded versions 111 + vobjx32s-y := $(vobjs64-for-x32:.o=-x32.o) 112 + 113 + # same thing, but in the output directory 99 114 vobjx32s := $(foreach F,$(vobjx32s-y),$(obj)/$F) 100 115 101 116 # Convert 64bit object file to x32 for x32 vDSO. ··· 173 176 GCOV_PROFILE := n 174 177 175 178 # 176 - # Install the unstripped copy of vdso*.so listed in $(vdso-install-y). 179 + # Install the unstripped copies of vdso*.so. 177 180 # 178 - quiet_cmd_vdso_install = INSTALL $@ 179 - cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@ 180 - $(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE 181 + quiet_cmd_vdso_install = INSTALL $(@:install_%=%) 182 + cmd_vdso_install = cp $< $(MODLIB)/vdso/$(@:install_%=%) 183 + 184 + vdso_img_insttargets := $(vdso_img_sodbg:%.dbg=install_%) 185 + 186 + $(MODLIB)/vdso: FORCE 181 187 @mkdir -p $(MODLIB)/vdso 188 + 189 + $(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso FORCE 182 190 $(call cmd,vdso_install) 183 191 184 - PHONY += vdso_install $(vdso-install-y) 185 - vdso_install: $(vdso-install-y) 192 + PHONY += vdso_install $(vdso_img_insttargets) 193 + vdso_install: $(vdso_img_insttargets) FORCE 186 194 187 195 clean-files := vdso32-syscall* vdso32-sysenter* vdso32-int80*
+32
arch/x86/vdso/vdso-fakesections.c
··· 1 + /* 2 + * Copyright 2014 Andy Lutomirski 3 + * Subject to the GNU Public License, v.2 4 + * 5 + * Hack to keep broken Go programs working. 6 + * 7 + * The Go runtime had a couple of bugs: it would read the section table to try 8 + * to figure out how many dynamic symbols there were (it shouldn't have looked 9 + * at the section table at all) and, if there were no SHT_SYNDYM section table 10 + * entry, it would use an uninitialized value for the number of symbols. As a 11 + * workaround, we supply a minimal section table. vdso2c will adjust the 12 + * in-memory image so that "vdso_fake_sections" becomes the section table. 13 + * 14 + * The bug was introduced by: 15 + * https://code.google.com/p/go/source/detail?r=56ea40aac72b (2012-08-31) 16 + * and is being addressed in the Go runtime in this issue: 17 + * https://code.google.com/p/go/issues/detail?id=8197 18 + */ 19 + 20 + #ifndef __x86_64__ 21 + #error This hack is specific to the 64-bit vDSO 22 + #endif 23 + 24 + #include <linux/elf.h> 25 + 26 + extern const __visible struct elf64_shdr vdso_fake_sections[]; 27 + const __visible struct elf64_shdr vdso_fake_sections[] = { 28 + { 29 + .sh_type = SHT_DYNSYM, 30 + .sh_entsize = sizeof(Elf64_Sym), 31 + } 32 + };
+16 -3
arch/x86/vdso/vdso2c.c
··· 54 54 } 55 55 56 56 /* 57 - * Evil macros to do a little-endian read. 57 + * Evil macros for little-endian reads and writes 58 58 */ 59 59 #define GLE(x, bits, ifnot) \ 60 60 __builtin_choose_expr( \ ··· 62 62 (__typeof__(*(x)))get_unaligned_le##bits(x), ifnot) 63 63 64 64 extern void bad_get_le(void); 65 - #define LAST_LE(x) \ 65 + #define LAST_GLE(x) \ 66 66 __builtin_choose_expr(sizeof(*(x)) == 1, *(x), bad_get_le()) 67 67 68 68 #define GET_LE(x) \ 69 - GLE(x, 64, GLE(x, 32, GLE(x, 16, LAST_LE(x)))) 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 + 76 + extern 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 + 70 83 71 84 #define NSYMS (sizeof(required_syms) / sizeof(required_syms[0])) 72 85
+18 -5
arch/x86/vdso/vdso2c.h
··· 18 18 const char *secstrings; 19 19 uint64_t syms[NSYMS] = {}; 20 20 21 + uint64_t fake_sections_value = 0, fake_sections_size = 0; 22 + 21 23 Elf_Phdr *pt = (Elf_Phdr *)(addr + GET_LE(&hdr->e_phoff)); 22 24 23 25 /* Walk the segment table. */ ··· 86 84 GET_LE(&symtab_hdr->sh_entsize) * i; 87 85 const char *name = addr + GET_LE(&strtab_hdr->sh_offset) + 88 86 GET_LE(&sym->st_name); 87 + 89 88 for (k = 0; k < NSYMS; k++) { 90 89 if (!strcmp(name, required_syms[k])) { 91 90 if (syms[k]) { ··· 95 92 } 96 93 syms[k] = GET_LE(&sym->st_value); 97 94 } 95 + } 96 + 97 + if (!strcmp(name, "vdso_fake_sections")) { 98 + if (fake_sections_value) 99 + fail("duplicate vdso_fake_sections\n"); 100 + fake_sections_value = GET_LE(&sym->st_value); 101 + fake_sections_size = GET_LE(&sym->st_size); 98 102 } 99 103 } 100 104 ··· 122 112 if (syms[sym_end_mapping] % 4096) 123 113 fail("end_mapping must be a multiple of 4096\n"); 124 114 125 - /* Remove sections. */ 126 - hdr->e_shoff = 0; 127 - hdr->e_shentsize = 0; 128 - hdr->e_shnum = 0; 129 - hdr->e_shstrndx = htole16(SHN_UNDEF); 115 + /* Remove sections or use fakes */ 116 + if (fake_sections_size % sizeof(Elf_Shdr)) 117 + fail("vdso_fake_sections size is not a multiple of %ld\n", 118 + (long)sizeof(Elf_Shdr)); 119 + PUT_LE(&hdr->e_shoff, fake_sections_value); 120 + PUT_LE(&hdr->e_shentsize, fake_sections_value ? sizeof(Elf_Shdr) : 0); 121 + PUT_LE(&hdr->e_shnum, fake_sections_size / sizeof(Elf_Shdr)); 122 + PUT_LE(&hdr->e_shstrndx, SHN_UNDEF); 130 123 131 124 if (!name) { 132 125 fwrite(addr, load_size, 1, outfile);