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