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