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 struct plt_entry { 15 /* 16 * A program that conforms to the AArch64 Procedure Call Standard 17 * (AAPCS64) must assume that a veneer that alters IP0 (x16) and/or 18 * IP1 (x17) may be inserted at any branch instruction that is 19 * exposed to a relocation that supports long branches. Since that 20 * is exactly what we are dealing with here, we are free to use x16 21 * as a scratch register in the PLT veneers. 22 */ 23 __le32 mov0; /* movn x16, #0x.... */ 24 __le32 mov1; /* movk x16, #0x...., lsl #16 */ 25 __le32 mov2; /* movk x16, #0x...., lsl #32 */ 26 __le32 br; /* br x16 */ 27 }; 28 29 static bool in_init(const struct module *mod, void *loc) 30 { 31 return (u64)loc - (u64)mod->init_layout.base < mod->init_layout.size; 32 } 33 34 u64 module_emit_plt_entry(struct module *mod, void *loc, const Elf64_Rela *rela, 35 Elf64_Sym *sym) 36 { 37 struct mod_plt_sec *pltsec = !in_init(mod, loc) ? &mod->arch.core : 38 &mod->arch.init; 39 struct plt_entry *plt = (struct plt_entry *)pltsec->plt->sh_addr; 40 int i = pltsec->plt_num_entries; 41 u64 val = sym->st_value + rela->r_addend; 42 43 /* 44 * MOVK/MOVN/MOVZ opcode: 45 * +--------+------------+--------+-----------+-------------+---------+ 46 * | sf[31] | opc[30:29] | 100101 | hw[22:21] | imm16[20:5] | Rd[4:0] | 47 * +--------+------------+--------+-----------+-------------+---------+ 48 * 49 * Rd := 0x10 (x16) 50 * hw := 0b00 (no shift), 0b01 (lsl #16), 0b10 (lsl #32) 51 * opc := 0b11 (MOVK), 0b00 (MOVN), 0b10 (MOVZ) 52 * sf := 1 (64-bit variant) 53 */ 54 plt[i] = (struct plt_entry){ 55 cpu_to_le32(0x92800010 | (((~val ) & 0xffff)) << 5), 56 cpu_to_le32(0xf2a00010 | ((( val >> 16) & 0xffff)) << 5), 57 cpu_to_le32(0xf2c00010 | ((( val >> 32) & 0xffff)) << 5), 58 cpu_to_le32(0xd61f0200) 59 }; 60 61 /* 62 * Check if the entry we just created is a duplicate. Given that the 63 * relocations are sorted, this will be the last entry we allocated. 64 * (if one exists). 65 */ 66 if (i > 0 && 67 plt[i].mov0 == plt[i - 1].mov0 && 68 plt[i].mov1 == plt[i - 1].mov1 && 69 plt[i].mov2 == plt[i - 1].mov2) 70 return (u64)&plt[i - 1]; 71 72 pltsec->plt_num_entries++; 73 BUG_ON(pltsec->plt_num_entries > pltsec->plt_max_entries); 74 75 return (u64)&plt[i]; 76 } 77 78 #define cmp_3way(a,b) ((a) < (b) ? -1 : (a) > (b)) 79 80 static int cmp_rela(const void *a, const void *b) 81 { 82 const Elf64_Rela *x = a, *y = b; 83 int i; 84 85 /* sort by type, symbol index and addend */ 86 i = cmp_3way(ELF64_R_TYPE(x->r_info), ELF64_R_TYPE(y->r_info)); 87 if (i == 0) 88 i = cmp_3way(ELF64_R_SYM(x->r_info), ELF64_R_SYM(y->r_info)); 89 if (i == 0) 90 i = cmp_3way(x->r_addend, y->r_addend); 91 return i; 92 } 93 94 static bool duplicate_rel(const Elf64_Rela *rela, int num) 95 { 96 /* 97 * Entries are sorted by type, symbol index and addend. That means 98 * that, if a duplicate entry exists, it must be in the preceding 99 * slot. 100 */ 101 return num > 0 && cmp_rela(rela + num, rela + num - 1) == 0; 102 } 103 104 static unsigned int count_plts(Elf64_Sym *syms, Elf64_Rela *rela, int num, 105 Elf64_Word dstidx) 106 { 107 unsigned int ret = 0; 108 Elf64_Sym *s; 109 int i; 110 111 for (i = 0; i < num; i++) { 112 switch (ELF64_R_TYPE(rela[i].r_info)) { 113 case R_AARCH64_JUMP26: 114 case R_AARCH64_CALL26: 115 /* 116 * We only have to consider branch targets that resolve 117 * to symbols that are defined in a different section. 118 * This is not simply a heuristic, it is a fundamental 119 * limitation, since there is no guaranteed way to emit 120 * PLT entries sufficiently close to the branch if the 121 * section size exceeds the range of a branch 122 * instruction. So ignore relocations against defined 123 * symbols if they live in the same section as the 124 * relocation target. 125 */ 126 s = syms + ELF64_R_SYM(rela[i].r_info); 127 if (s->st_shndx == dstidx) 128 break; 129 130 /* 131 * Jump relocations with non-zero addends against 132 * undefined symbols are supported by the ELF spec, but 133 * do not occur in practice (e.g., 'jump n bytes past 134 * the entry point of undefined function symbol f'). 135 * So we need to support them, but there is no need to 136 * take them into consideration when trying to optimize 137 * this code. So let's only check for duplicates when 138 * the addend is zero: this allows us to record the PLT 139 * entry address in the symbol table itself, rather than 140 * having to search the list for duplicates each time we 141 * emit one. 142 */ 143 if (rela[i].r_addend != 0 || !duplicate_rel(rela, i)) 144 ret++; 145 break; 146 } 147 } 148 return ret; 149 } 150 151 int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, 152 char *secstrings, struct module *mod) 153 { 154 unsigned long core_plts = 0; 155 unsigned long init_plts = 0; 156 Elf64_Sym *syms = NULL; 157 int i; 158 159 /* 160 * Find the empty .plt section so we can expand it to store the PLT 161 * entries. Record the symtab address as well. 162 */ 163 for (i = 0; i < ehdr->e_shnum; i++) { 164 if (!strcmp(secstrings + sechdrs[i].sh_name, ".plt")) 165 mod->arch.core.plt = sechdrs + i; 166 else if (!strcmp(secstrings + sechdrs[i].sh_name, ".init.plt")) 167 mod->arch.init.plt = sechdrs + i; 168 else if (sechdrs[i].sh_type == SHT_SYMTAB) 169 syms = (Elf64_Sym *)sechdrs[i].sh_addr; 170 } 171 172 if (!mod->arch.core.plt || !mod->arch.init.plt) { 173 pr_err("%s: module PLT section(s) missing\n", mod->name); 174 return -ENOEXEC; 175 } 176 if (!syms) { 177 pr_err("%s: module symtab section missing\n", mod->name); 178 return -ENOEXEC; 179 } 180 181 for (i = 0; i < ehdr->e_shnum; i++) { 182 Elf64_Rela *rels = (void *)ehdr + sechdrs[i].sh_offset; 183 int numrels = sechdrs[i].sh_size / sizeof(Elf64_Rela); 184 Elf64_Shdr *dstsec = sechdrs + sechdrs[i].sh_info; 185 186 if (sechdrs[i].sh_type != SHT_RELA) 187 continue; 188 189 /* ignore relocations that operate on non-exec sections */ 190 if (!(dstsec->sh_flags & SHF_EXECINSTR)) 191 continue; 192 193 /* sort by type, symbol index and addend */ 194 sort(rels, numrels, sizeof(Elf64_Rela), cmp_rela, NULL); 195 196 if (strncmp(secstrings + dstsec->sh_name, ".init", 5) != 0) 197 core_plts += count_plts(syms, rels, numrels, 198 sechdrs[i].sh_info); 199 else 200 init_plts += count_plts(syms, rels, numrels, 201 sechdrs[i].sh_info); 202 } 203 204 mod->arch.core.plt->sh_type = SHT_NOBITS; 205 mod->arch.core.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; 206 mod->arch.core.plt->sh_addralign = L1_CACHE_BYTES; 207 mod->arch.core.plt->sh_size = (core_plts + 1) * sizeof(struct plt_entry); 208 mod->arch.core.plt_num_entries = 0; 209 mod->arch.core.plt_max_entries = core_plts; 210 211 mod->arch.init.plt->sh_type = SHT_NOBITS; 212 mod->arch.init.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC; 213 mod->arch.init.plt->sh_addralign = L1_CACHE_BYTES; 214 mod->arch.init.plt->sh_size = (init_plts + 1) * sizeof(struct plt_entry); 215 mod->arch.init.plt_num_entries = 0; 216 mod->arch.init.plt_max_entries = init_plts; 217 218 return 0; 219 } 220