linux/arch/arm/kernel/module-plts.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2014-2017 Linaro Ltd. <ard.biesheuvel@linaro.org>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 */
   8
   9#include <linux/elf.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/sort.h>
  13
  14#include <asm/cache.h>
  15#include <asm/opcodes.h>
  16
  17#define PLT_ENT_STRIDE          L1_CACHE_BYTES
  18#define PLT_ENT_COUNT           (PLT_ENT_STRIDE / sizeof(u32))
  19#define PLT_ENT_SIZE            (sizeof(struct plt_entries) / PLT_ENT_COUNT)
  20
  21#ifdef CONFIG_THUMB2_KERNEL
  22#define PLT_ENT_LDR             __opcode_to_mem_thumb32(0xf8dff000 | \
  23                                                        (PLT_ENT_STRIDE - 4))
  24#else
  25#define PLT_ENT_LDR             __opcode_to_mem_arm(0xe59ff000 | \
  26                                                    (PLT_ENT_STRIDE - 8))
  27#endif
  28
  29struct plt_entries {
  30        u32     ldr[PLT_ENT_COUNT];
  31        u32     lit[PLT_ENT_COUNT];
  32};
  33
  34static bool in_init(const struct module *mod, unsigned long loc)
  35{
  36        return loc - (u32)mod->init_layout.base < mod->init_layout.size;
  37}
  38
  39u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val)
  40{
  41        struct mod_plt_sec *pltsec = !in_init(mod, loc) ? &mod->arch.core :
  42                                                          &mod->arch.init;
  43
  44        struct plt_entries *plt = (struct plt_entries *)pltsec->plt->sh_addr;
  45        int idx = 0;
  46
  47        /*
  48         * Look for an existing entry pointing to 'val'. Given that the
  49         * relocations are sorted, this will be the last entry we allocated.
  50         * (if one exists).
  51         */
  52        if (pltsec->plt_count > 0) {
  53                plt += (pltsec->plt_count - 1) / PLT_ENT_COUNT;
  54                idx = (pltsec->plt_count - 1) % PLT_ENT_COUNT;
  55
  56                if (plt->lit[idx] == val)
  57                        return (u32)&plt->ldr[idx];
  58
  59                idx = (idx + 1) % PLT_ENT_COUNT;
  60                if (!idx)
  61                        plt++;
  62        }
  63
  64        pltsec->plt_count++;
  65        BUG_ON(pltsec->plt_count * PLT_ENT_SIZE > pltsec->plt->sh_size);
  66
  67        if (!idx)
  68                /* Populate a new set of entries */
  69                *plt = (struct plt_entries){
  70                        { [0 ... PLT_ENT_COUNT - 1] = PLT_ENT_LDR, },
  71                        { val, }
  72                };
  73        else
  74                plt->lit[idx] = val;
  75
  76        return (u32)&plt->ldr[idx];
  77}
  78
  79#define cmp_3way(a,b)   ((a) < (b) ? -1 : (a) > (b))
  80
  81static int cmp_rel(const void *a, const void *b)
  82{
  83        const Elf32_Rel *x = a, *y = b;
  84        int i;
  85
  86        /* sort by type and symbol index */
  87        i = cmp_3way(ELF32_R_TYPE(x->r_info), ELF32_R_TYPE(y->r_info));
  88        if (i == 0)
  89                i = cmp_3way(ELF32_R_SYM(x->r_info), ELF32_R_SYM(y->r_info));
  90        return i;
  91}
  92
  93static bool is_zero_addend_relocation(Elf32_Addr base, const Elf32_Rel *rel)
  94{
  95        u32 *tval = (u32 *)(base + rel->r_offset);
  96
  97        /*
  98         * Do a bitwise compare on the raw addend rather than fully decoding
  99         * the offset and doing an arithmetic comparison.
 100         * Note that a zero-addend jump/call relocation is encoded taking the
 101         * PC bias into account, i.e., -8 for ARM and -4 for Thumb2.
 102         */
 103        switch (ELF32_R_TYPE(rel->r_info)) {
 104                u16 upper, lower;
 105
 106        case R_ARM_THM_CALL:
 107        case R_ARM_THM_JUMP24:
 108                upper = __mem_to_opcode_thumb16(((u16 *)tval)[0]);
 109                lower = __mem_to_opcode_thumb16(((u16 *)tval)[1]);
 110
 111                return (upper & 0x7ff) == 0x7ff && (lower & 0x2fff) == 0x2ffe;
 112
 113        case R_ARM_CALL:
 114        case R_ARM_PC24:
 115        case R_ARM_JUMP24:
 116                return (__mem_to_opcode_arm(*tval) & 0xffffff) == 0xfffffe;
 117        }
 118        BUG();
 119}
 120
 121static bool duplicate_rel(Elf32_Addr base, const Elf32_Rel *rel, int num)
 122{
 123        const Elf32_Rel *prev;
 124
 125        /*
 126         * Entries are sorted by type and symbol index. That means that,
 127         * if a duplicate entry exists, it must be in the preceding
 128         * slot.
 129         */
 130        if (!num)
 131                return false;
 132
 133        prev = rel + num - 1;
 134        return cmp_rel(rel + num, prev) == 0 &&
 135               is_zero_addend_relocation(base, prev);
 136}
 137
 138/* Count how many PLT entries we may need */
 139static unsigned int count_plts(const Elf32_Sym *syms, Elf32_Addr base,
 140                               const Elf32_Rel *rel, int num, Elf32_Word dstidx)
 141{
 142        unsigned int ret = 0;
 143        const Elf32_Sym *s;
 144        int i;
 145
 146        for (i = 0; i < num; i++) {
 147                switch (ELF32_R_TYPE(rel[i].r_info)) {
 148                case R_ARM_CALL:
 149                case R_ARM_PC24:
 150                case R_ARM_JUMP24:
 151                case R_ARM_THM_CALL:
 152                case R_ARM_THM_JUMP24:
 153                        /*
 154                         * We only have to consider branch targets that resolve
 155                         * to symbols that are defined in a different section.
 156                         * This is not simply a heuristic, it is a fundamental
 157                         * limitation, since there is no guaranteed way to emit
 158                         * PLT entries sufficiently close to the branch if the
 159                         * section size exceeds the range of a branch
 160                         * instruction. So ignore relocations against defined
 161                         * symbols if they live in the same section as the
 162                         * relocation target.
 163                         */
 164                        s = syms + ELF32_R_SYM(rel[i].r_info);
 165                        if (s->st_shndx == dstidx)
 166                                break;
 167
 168                        /*
 169                         * Jump relocations with non-zero addends against
 170                         * undefined symbols are supported by the ELF spec, but
 171                         * do not occur in practice (e.g., 'jump n bytes past
 172                         * the entry point of undefined function symbol f').
 173                         * So we need to support them, but there is no need to
 174                         * take them into consideration when trying to optimize
 175                         * this code. So let's only check for duplicates when
 176                         * the addend is zero. (Note that calls into the core
 177                         * module via init PLT entries could involve section
 178                         * relative symbol references with non-zero addends, for
 179                         * which we may end up emitting duplicates, but the init
 180                         * PLT is released along with the rest of the .init
 181                         * region as soon as module loading completes.)
 182                         */
 183                        if (!is_zero_addend_relocation(base, rel + i) ||
 184                            !duplicate_rel(base, rel, i))
 185                                ret++;
 186                }
 187        }
 188        return ret;
 189}
 190
 191int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 192                              char *secstrings, struct module *mod)
 193{
 194        unsigned long core_plts = 0;
 195        unsigned long init_plts = 0;
 196        Elf32_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum;
 197        Elf32_Sym *syms = NULL;
 198
 199        /*
 200         * To store the PLTs, we expand the .text section for core module code
 201         * and for initialization code.
 202         */
 203        for (s = sechdrs; s < sechdrs_end; ++s) {
 204                if (strcmp(".plt", secstrings + s->sh_name) == 0)
 205                        mod->arch.core.plt = s;
 206                else if (strcmp(".init.plt", secstrings + s->sh_name) == 0)
 207                        mod->arch.init.plt = s;
 208                else if (s->sh_type == SHT_SYMTAB)
 209                        syms = (Elf32_Sym *)s->sh_addr;
 210        }
 211
 212        if (!mod->arch.core.plt || !mod->arch.init.plt) {
 213                pr_err("%s: module PLT section(s) missing\n", mod->name);
 214                return -ENOEXEC;
 215        }
 216        if (!syms) {
 217                pr_err("%s: module symtab section missing\n", mod->name);
 218                return -ENOEXEC;
 219        }
 220
 221        for (s = sechdrs + 1; s < sechdrs_end; ++s) {
 222                Elf32_Rel *rels = (void *)ehdr + s->sh_offset;
 223                int numrels = s->sh_size / sizeof(Elf32_Rel);
 224                Elf32_Shdr *dstsec = sechdrs + s->sh_info;
 225
 226                if (s->sh_type != SHT_REL)
 227                        continue;
 228
 229                /* ignore relocations that operate on non-exec sections */
 230                if (!(dstsec->sh_flags & SHF_EXECINSTR))
 231                        continue;
 232
 233                /* sort by type and symbol index */
 234                sort(rels, numrels, sizeof(Elf32_Rel), cmp_rel, NULL);
 235
 236                if (strncmp(secstrings + dstsec->sh_name, ".init", 5) != 0)
 237                        core_plts += count_plts(syms, dstsec->sh_addr, rels,
 238                                                numrels, s->sh_info);
 239                else
 240                        init_plts += count_plts(syms, dstsec->sh_addr, rels,
 241                                                numrels, s->sh_info);
 242        }
 243
 244        mod->arch.core.plt->sh_type = SHT_NOBITS;
 245        mod->arch.core.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
 246        mod->arch.core.plt->sh_addralign = L1_CACHE_BYTES;
 247        mod->arch.core.plt->sh_size = round_up(core_plts * PLT_ENT_SIZE,
 248                                               sizeof(struct plt_entries));
 249        mod->arch.core.plt_count = 0;
 250
 251        mod->arch.init.plt->sh_type = SHT_NOBITS;
 252        mod->arch.init.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
 253        mod->arch.init.plt->sh_addralign = L1_CACHE_BYTES;
 254        mod->arch.init.plt->sh_size = round_up(init_plts * PLT_ENT_SIZE,
 255                                               sizeof(struct plt_entries));
 256        mod->arch.init.plt_count = 0;
 257
 258        pr_debug("%s: plt=%x, init.plt=%x\n", __func__,
 259                 mod->arch.core.plt->sh_size, mod->arch.init.plt->sh_size);
 260        return 0;
 261}
 262