Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * Copyright (C) 2015 Imagination Technologies
0004  * Author: Alex Smith <alex.smith@imgtec.com>
0005  */
0006 
0007 static inline bool FUNC(patch_vdso)(const char *path, void *vdso)
0008 {
0009     const ELF(Ehdr) *ehdr = vdso;
0010     void *shdrs;
0011     ELF(Shdr) *shdr;
0012     char *shstrtab, *name;
0013     uint16_t sh_count, sh_entsize, i;
0014 
0015     shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff);
0016     sh_count = swap_uint16(ehdr->e_shnum);
0017     sh_entsize = swap_uint16(ehdr->e_shentsize);
0018 
0019     shdr = shdrs + (sh_entsize * swap_uint16(ehdr->e_shstrndx));
0020     shstrtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
0021 
0022     for (i = 0; i < sh_count; i++) {
0023         shdr = shdrs + (i * sh_entsize);
0024         name = shstrtab + swap_uint32(shdr->sh_name);
0025 
0026         /*
0027          * Ensure there are no relocation sections - ld.so does not
0028          * relocate the VDSO so if there are relocations things will
0029          * break.
0030          */
0031         switch (swap_uint32(shdr->sh_type)) {
0032         case SHT_REL:
0033         case SHT_RELA:
0034             fprintf(stderr,
0035                 "%s: '%s' contains relocation sections\n",
0036                 program_name, path);
0037             return false;
0038         }
0039 
0040         /* Check for existing sections. */
0041         if (strcmp(name, ".MIPS.abiflags") == 0) {
0042             fprintf(stderr,
0043                 "%s: '%s' already contains a '.MIPS.abiflags' section\n",
0044                 program_name, path);
0045             return false;
0046         }
0047 
0048         if (strcmp(name, ".mips_abiflags") == 0) {
0049             strcpy(name, ".MIPS.abiflags");
0050             shdr->sh_type = swap_uint32(SHT_MIPS_ABIFLAGS);
0051             shdr->sh_entsize = shdr->sh_size;
0052         }
0053     }
0054 
0055     return true;
0056 }
0057 
0058 static inline bool FUNC(get_symbols)(const char *path, void *vdso)
0059 {
0060     const ELF(Ehdr) *ehdr = vdso;
0061     void *shdrs, *symtab;
0062     ELF(Shdr) *shdr;
0063     const ELF(Sym) *sym;
0064     char *strtab, *name;
0065     uint16_t sh_count, sh_entsize, st_count, st_entsize, i, j;
0066     uint64_t offset;
0067     uint32_t flags;
0068 
0069     shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff);
0070     sh_count = swap_uint16(ehdr->e_shnum);
0071     sh_entsize = swap_uint16(ehdr->e_shentsize);
0072 
0073     for (i = 0; i < sh_count; i++) {
0074         shdr = shdrs + (i * sh_entsize);
0075 
0076         if (swap_uint32(shdr->sh_type) == SHT_SYMTAB)
0077             break;
0078     }
0079 
0080     if (i == sh_count) {
0081         fprintf(stderr, "%s: '%s' has no symbol table\n", program_name,
0082             path);
0083         return false;
0084     }
0085 
0086     /* Get flags */
0087     flags = swap_uint32(ehdr->e_flags);
0088     if (elf_class == ELFCLASS64)
0089         elf_abi = ABI_N64;
0090     else if (flags & EF_MIPS_ABI2)
0091         elf_abi = ABI_N32;
0092     else
0093         elf_abi = ABI_O32;
0094 
0095     /* Get symbol table. */
0096     symtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
0097     st_entsize = FUNC(swap_uint)(shdr->sh_entsize);
0098     st_count = FUNC(swap_uint)(shdr->sh_size) / st_entsize;
0099 
0100     /* Get string table. */
0101     shdr = shdrs + (swap_uint32(shdr->sh_link) * sh_entsize);
0102     strtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
0103 
0104     /* Write offsets for symbols needed by the kernel. */
0105     for (i = 0; vdso_symbols[i].name; i++) {
0106         if (!(vdso_symbols[i].abis & elf_abi))
0107             continue;
0108 
0109         for (j = 0; j < st_count; j++) {
0110             sym = symtab + (j * st_entsize);
0111             name = strtab + swap_uint32(sym->st_name);
0112 
0113             if (!strcmp(name, vdso_symbols[i].name)) {
0114                 offset = FUNC(swap_uint)(sym->st_value);
0115 
0116                 fprintf(out_file,
0117                     "\t.%s = 0x%" PRIx64 ",\n",
0118                     vdso_symbols[i].offset_name, offset);
0119                 break;
0120             }
0121         }
0122 
0123         if (j == st_count) {
0124             fprintf(stderr,
0125                 "%s: '%s' is missing required symbol '%s'\n",
0126                 program_name, path, vdso_symbols[i].name);
0127             return false;
0128         }
0129     }
0130 
0131     return true;
0132 }