1 /* 2 * Copyright (C) 2015 Imagination Technologies 3 * Author: Alex Smith <alex.smith@imgtec.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the 7 * Free Software Foundation; either version 2 of the License, or (at your 8 * option) any later version. 9 */ 10 11 static inline bool FUNC(patch_vdso)(const char *path, void *vdso) 12 { 13 const ELF(Ehdr) *ehdr = vdso; 14 void *shdrs; 15 ELF(Shdr) *shdr; 16 char *shstrtab, *name; 17 uint16_t sh_count, sh_entsize, i; 18 19 shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff); 20 sh_count = swap_uint16(ehdr->e_shnum); 21 sh_entsize = swap_uint16(ehdr->e_shentsize); 22 23 shdr = shdrs + (sh_entsize * swap_uint16(ehdr->e_shstrndx)); 24 shstrtab = vdso + FUNC(swap_uint)(shdr->sh_offset); 25 26 for (i = 0; i < sh_count; i++) { 27 shdr = shdrs + (i * sh_entsize); 28 name = shstrtab + swap_uint32(shdr->sh_name); 29 30 /* 31 * Ensure there are no relocation sections - ld.so does not 32 * relocate the VDSO so if there are relocations things will 33 * break. 34 */ 35 switch (swap_uint32(shdr->sh_type)) { 36 case SHT_REL: 37 case SHT_RELA: 38 fprintf(stderr, 39 "%s: '%s' contains relocation sections\n", 40 program_name, path); 41 return false; 42 } 43 44 /* Check for existing sections. */ 45 if (strcmp(name, ".MIPS.abiflags") == 0) { 46 fprintf(stderr, 47 "%s: '%s' already contains a '.MIPS.abiflags' section\n", 48 program_name, path); 49 return false; 50 } 51 52 if (strcmp(name, ".mips_abiflags") == 0) { 53 strcpy(name, ".MIPS.abiflags"); 54 shdr->sh_type = swap_uint32(SHT_MIPS_ABIFLAGS); 55 shdr->sh_entsize = shdr->sh_size; 56 } 57 } 58 59 return true; 60 } 61 62 static inline bool FUNC(get_symbols)(const char *path, void *vdso) 63 { 64 const ELF(Ehdr) *ehdr = vdso; 65 void *shdrs, *symtab; 66 ELF(Shdr) *shdr; 67 const ELF(Sym) *sym; 68 char *strtab, *name; 69 uint16_t sh_count, sh_entsize, st_count, st_entsize, i, j; 70 uint64_t offset; 71 uint32_t flags; 72 73 shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff); 74 sh_count = swap_uint16(ehdr->e_shnum); 75 sh_entsize = swap_uint16(ehdr->e_shentsize); 76 77 for (i = 0; i < sh_count; i++) { 78 shdr = shdrs + (i * sh_entsize); 79 80 if (swap_uint32(shdr->sh_type) == SHT_SYMTAB) 81 break; 82 } 83 84 if (i == sh_count) { 85 fprintf(stderr, "%s: '%s' has no symbol table\n", program_name, 86 path); 87 return false; 88 } 89 90 /* Get flags */ 91 flags = swap_uint32(ehdr->e_flags); 92 if (elf_class == ELFCLASS64) 93 elf_abi = ABI_N64; 94 else if (flags & EF_MIPS_ABI2) 95 elf_abi = ABI_N32; 96 else 97 elf_abi = ABI_O32; 98 99 /* Get symbol table. */ 100 symtab = vdso + FUNC(swap_uint)(shdr->sh_offset); 101 st_entsize = FUNC(swap_uint)(shdr->sh_entsize); 102 st_count = FUNC(swap_uint)(shdr->sh_size) / st_entsize; 103 104 /* Get string table. */ 105 shdr = shdrs + (swap_uint32(shdr->sh_link) * sh_entsize); 106 strtab = vdso + FUNC(swap_uint)(shdr->sh_offset); 107 108 /* Write offsets for symbols needed by the kernel. */ 109 for (i = 0; vdso_symbols[i].name; i++) { 110 if (!(vdso_symbols[i].abis & elf_abi)) 111 continue; 112 113 for (j = 0; j < st_count; j++) { 114 sym = symtab + (j * st_entsize); 115 name = strtab + swap_uint32(sym->st_name); 116 117 if (!strcmp(name, vdso_symbols[i].name)) { 118 offset = FUNC(swap_uint)(sym->st_value); 119 120 fprintf(out_file, 121 "\t.%s = 0x%" PRIx64 ",\n", 122 vdso_symbols[i].offset_name, offset); 123 break; 124 } 125 } 126 127 if (j == st_count) { 128 fprintf(stderr, 129 "%s: '%s' is missing required symbol '%s'\n", 130 program_name, path, vdso_symbols[i].name); 131 return false; 132 } 133 } 134 135 return true; 136 } 137