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