root/arch/mips/vdso/genvdso.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


   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 
   7 static 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 
  58 static 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 }

/* [<][>][^][v][top][bottom][index][help] */