1 // SPDX-License-Identifier: GPL-2.0-only !! 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 2 /* 3 * linux/arch/arm/kernel/module.c << 4 * 3 * 5 * Copyright (C) 2002 Russell King. !! 4 * Copyright (C) 2001 Rusty Russell. 6 * Modified for nommu by Hyok S. Choi !! 5 * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org) 7 * !! 6 * Copyright (C) 2005 Thiemo Seufer 8 * Module allocation method suggested by Andi << 9 */ 7 */ 10 #include <linux/module.h> !! 8 >> 9 #undef DEBUG >> 10 >> 11 #include <linux/extable.h> 11 #include <linux/moduleloader.h> 12 #include <linux/moduleloader.h> 12 #include <linux/kernel.h> << 13 #include <linux/mm.h> << 14 #include <linux/elf.h> 13 #include <linux/elf.h> >> 14 #include <linux/mm.h> >> 15 #include <linux/numa.h> >> 16 #include <linux/vmalloc.h> >> 17 #include <linux/slab.h> 15 #include <linux/fs.h> 18 #include <linux/fs.h> 16 #include <linux/string.h> 19 #include <linux/string.h> >> 20 #include <linux/kernel.h> >> 21 #include <linux/spinlock.h> >> 22 #include <linux/jump_label.h> 17 23 18 #include <asm/sections.h> << 19 #include <asm/smp_plat.h> << 20 #include <asm/unwind.h> << 21 #include <asm/opcodes.h> << 22 24 23 bool module_init_section(const char *name) !! 25 struct mips_hi16 { 24 { !! 26 struct mips_hi16 *next; 25 return strstarts(name, ".init") || !! 27 Elf_Addr *addr; 26 strstarts(name, ".ARM.extab.in !! 28 Elf_Addr value; 27 strstarts(name, ".ARM.exidx.in !! 29 }; 28 } << 29 30 30 bool module_exit_section(const char *name) !! 31 static LIST_HEAD(dbe_list); 31 { !! 32 static DEFINE_SPINLOCK(dbe_lock); 32 return strstarts(name, ".exit") || << 33 strstarts(name, ".ARM.extab.ex << 34 strstarts(name, ".ARM.exidx.ex << 35 } << 36 33 37 #ifdef CONFIG_ARM_HAS_GROUP_RELOCS !! 34 #ifdef MODULE_START 38 /* !! 35 void *module_alloc(unsigned long size) 39 * This implements the partitioning algorithm << 40 * documented in the ARM AArch32 ELF psABI (IH << 41 * << 42 * A single PC-relative symbol reference is di << 43 * operations, where the final one could be in << 44 * instruction with immediate offset. E.g., << 45 * << 46 * ADD Rd, PC, #... or << 47 * ADD Rd, Rd, #... << 48 * LDR Rd, [Rd, #...] << 49 * << 50 * The latter has a guaranteed range of only 1 << 51 * of limited use in the kernel. However, the << 52 * -/+ 256 MiB, (2x8 + 12 == 28 bits), which m << 53 * any in-kernel symbol reference (unless modu << 54 * << 55 * The main advantage of this approach over th << 56 * load is that literal loads may miss in the << 57 * lower cache efficiency for variables that a << 58 * different places in the code. << 59 */ << 60 static u32 get_group_rem(u32 group, u32 *offse << 61 { 36 { 62 u32 val = *offset; !! 37 return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END, 63 u32 shift; !! 38 GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE, 64 do { !! 39 __builtin_return_address(0)); 65 shift = val ? (31 - __fls(val) << 66 *offset = val; << 67 if (!val) << 68 break; << 69 val &= 0xffffff >> shift; << 70 } while (group--); << 71 return shift; << 72 } 40 } 73 #endif 41 #endif 74 42 75 int !! 43 static int apply_r_mips_none(struct module *me, u32 *location, 76 apply_relocate(Elf32_Shdr *sechdrs, const char !! 44 u32 base, Elf_Addr v, bool rela) 77 unsigned int relindex, struct m !! 45 { 78 { !! 46 return 0; 79 Elf32_Shdr *symsec = sechdrs + syminde !! 47 } 80 Elf32_Shdr *relsec = sechdrs + relinde << 81 Elf32_Shdr *dstsec = sechdrs + relsec- << 82 Elf32_Rel *rel = (void *)relsec->sh_ad << 83 unsigned int i; << 84 << 85 for (i = 0; i < relsec->sh_size / size << 86 unsigned long loc; << 87 Elf32_Sym *sym; << 88 const char *symname; << 89 #ifdef CONFIG_ARM_HAS_GROUP_RELOCS << 90 u32 shift, group = 1; << 91 #endif << 92 s32 offset; << 93 u32 tmp; << 94 #ifdef CONFIG_THUMB2_KERNEL << 95 u32 upper, lower, sign, j1, j2 << 96 #endif << 97 48 98 offset = ELF32_R_SYM(rel->r_in !! 49 static int apply_r_mips_32(struct module *me, u32 *location, 99 if (offset < 0 || offset > (sy !! 50 u32 base, Elf_Addr v, bool rela) 100 pr_err("%s: section %u !! 51 { 101 module->name, !! 52 *location = base + v; 102 return -ENOEXEC; << 103 } << 104 53 105 sym = ((Elf32_Sym *)symsec->sh !! 54 return 0; 106 symname = strtab + sym->st_nam !! 55 } 107 56 108 if (rel->r_offset < 0 || rel-> !! 57 static int apply_r_mips_26(struct module *me, u32 *location, 109 pr_err("%s: section %u !! 58 u32 base, Elf_Addr v, bool rela) 110 module->name, r !! 59 { 111 rel->r_offset, !! 60 if (v % 4) { 112 return -ENOEXEC; !! 61 pr_err("module %s: dangerous R_MIPS_26 relocation\n", 113 } !! 62 me->name); >> 63 return -ENOEXEC; >> 64 } 114 65 115 loc = dstsec->sh_addr + rel->r !! 66 if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { >> 67 pr_err("module %s: relocation overflow\n", >> 68 me->name); >> 69 return -ENOEXEC; >> 70 } 116 71 117 switch (ELF32_R_TYPE(rel->r_in !! 72 *location = (*location & ~0x03ffffff) | 118 case R_ARM_NONE: !! 73 ((base + (v >> 2)) & 0x03ffffff); 119 /* ignore */ << 120 break; << 121 74 122 case R_ARM_ABS32: !! 75 return 0; 123 case R_ARM_TARGET1: !! 76 } 124 *(u32 *)loc += sym->st << 125 break; << 126 << 127 case R_ARM_PC24: << 128 case R_ARM_CALL: << 129 case R_ARM_JUMP24: << 130 if (sym->st_value & 3) << 131 pr_err("%s: se << 132 module- << 133 return -ENOEXE << 134 } << 135 << 136 offset = __mem_to_opco << 137 offset = (offset & 0x0 << 138 offset = sign_extend32 << 139 77 140 offset += sym->st_valu !! 78 static int apply_r_mips_hi16(struct module *me, u32 *location, >> 79 u32 base, Elf_Addr v, bool rela) >> 80 { >> 81 struct mips_hi16 *n; 141 82 142 /* !! 83 if (rela) { 143 * Route through a PLT !! 84 *location = (*location & 0xffff0000) | 144 * supported range. No !! 85 ((((long long) v + 0x8000LL) >> 16) & 0xffff); 145 * contains the absolu !! 86 return 0; 146 * @sym + addend, corr !! 87 } 147 */ << 148 if (IS_ENABLED(CONFIG_ << 149 (offset <= (s32)0x << 150 offset >= (s32)0x << 151 offset = get_m << 152 << 153 - loc << 154 << 155 if (offset <= (s32)0xf << 156 offset >= (s32)0x0 << 157 pr_err("%s: se << 158 module- << 159 ELF32_R << 160 sym->st << 161 return -ENOEXE << 162 } << 163 88 164 offset >>= 2; !! 89 /* 165 offset &= 0x00ffffff; !! 90 * We cannot relocate this one now because we don't know the value of >> 91 * the carry we need to add. Save the information, and let LO16 do the >> 92 * actual relocation. >> 93 */ >> 94 n = kmalloc(sizeof *n, GFP_KERNEL); >> 95 if (!n) >> 96 return -ENOMEM; >> 97 >> 98 n->addr = (Elf_Addr *)location; >> 99 n->value = v; >> 100 n->next = me->arch.r_mips_hi16_list; >> 101 me->arch.r_mips_hi16_list = n; 166 102 167 *(u32 *)loc &= __opcod !! 103 return 0; 168 *(u32 *)loc |= __opcod !! 104 } 169 break; << 170 105 171 case R_ARM_V4BX: !! 106 static void free_relocation_chain(struct mips_hi16 *l) 172 /* Preserve Rm and the !! 107 { 173 * other bits to re-cod !! 108 struct mips_hi16 *next; 174 * MOV PC,Rm. << 175 */ << 176 *(u32 *)loc &= __opcode << 177 *(u32 *)loc |= __opcode << 178 break; << 179 << 180 case R_ARM_PREL31: << 181 offset = (*(s32 *)loc << 182 offset += sym->st_valu << 183 if (offset >= 0x400000 << 184 pr_err("%s: se << 185 module- << 186 ELF32_R << 187 sym->st << 188 return -ENOEXE << 189 } << 190 *(u32 *)loc &= 0x80000 << 191 *(u32 *)loc |= offset << 192 break; << 193 109 194 case R_ARM_REL32: !! 110 while (l) { 195 *(u32 *)loc += sym->st !! 111 next = l->next; 196 break; !! 112 kfree(l); >> 113 l = next; >> 114 } >> 115 } 197 116 198 case R_ARM_MOVW_ABS_NC: !! 117 static int apply_r_mips_lo16(struct module *me, u32 *location, 199 case R_ARM_MOVT_ABS: !! 118 u32 base, Elf_Addr v, bool rela) 200 case R_ARM_MOVW_PREL_NC: !! 119 { 201 case R_ARM_MOVT_PREL: !! 120 unsigned long insnlo = base; 202 offset = tmp = __mem_t !! 121 struct mips_hi16 *l; 203 offset = ((offset & 0x !! 122 Elf_Addr val, vallo; 204 offset = sign_extend32 !! 123 205 !! 124 if (rela) { 206 offset += sym->st_valu !! 125 *location = (*location & 0xffff0000) | (v & 0xffff); 207 if (ELF32_R_TYPE(rel-> !! 126 return 0; 208 ELF32_R_TYPE(rel-> !! 127 } 209 offset -= loc; << 210 if (ELF32_R_TYPE(rel-> << 211 ELF32_R_TYPE(rel-> << 212 offset >>= 16; << 213 << 214 tmp &= 0xfff0f000; << 215 tmp |= ((offset & 0xf0 << 216 (offset & 0x0f << 217 128 218 *(u32 *)loc = __opcode !! 129 /* Sign extend the addend we extract from the lo insn. */ 219 break; !! 130 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; 220 131 221 #ifdef CONFIG_ARM_HAS_GROUP_RELOCS !! 132 if (me->arch.r_mips_hi16_list != NULL) { 222 case R_ARM_ALU_PC_G0_NC: !! 133 l = me->arch.r_mips_hi16_list; 223 group = 0; !! 134 while (l != NULL) { 224 fallthrough; !! 135 struct mips_hi16 *next; 225 case R_ARM_ALU_PC_G1_NC: !! 136 unsigned long insn; 226 tmp = __mem_to_opcode_ << 227 offset = ror32(tmp & 0 << 228 if (tmp & BIT(22)) << 229 offset = -offs << 230 offset += sym->st_valu << 231 if (offset < 0) { << 232 offset = -offs << 233 tmp = (tmp & ~ << 234 } else { << 235 tmp = (tmp & ~ << 236 } << 237 << 238 shift = get_group_rem( << 239 if (shift < 24) { << 240 offset >>= 24 << 241 offset |= (shi << 242 } << 243 *(u32 *)loc = __opcode << 244 break; << 245 137 246 case R_ARM_LDR_PC_G2: << 247 tmp = __mem_to_opcode_ << 248 offset = tmp & 0xfff; << 249 if (~tmp & BIT(23)) << 250 offset = -offs << 251 offset += sym->st_valu << 252 if (offset < 0) { << 253 offset = -offs << 254 tmp &= ~BIT(23 << 255 } else { << 256 tmp |= BIT(23) << 257 } << 258 get_group_rem(2, &offs << 259 << 260 if (offset > 0xfff) { << 261 pr_err("%s: se << 262 module- << 263 ELF32_R << 264 sym->st << 265 return -ENOEXE << 266 } << 267 *(u32 *)loc = __opcode << 268 break; << 269 #endif << 270 #ifdef CONFIG_THUMB2_KERNEL << 271 case R_ARM_THM_CALL: << 272 case R_ARM_THM_JUMP24: << 273 /* 138 /* 274 * For function symbol !! 139 * The value for the HI16 had best be the same. 275 * allowed (no interwo << 276 * << 277 * For non-function sy << 278 * has no specific ARM << 279 * the branch is resol << 280 * that interworking i << 281 */ 140 */ 282 if (ELF32_ST_TYPE(sym- !! 141 if (v != l->value) 283 !(sym->st_value & !! 142 goto out_danger; 284 pr_err("%s: se << 285 module- << 286 return -ENOEXE << 287 } << 288 << 289 upper = __mem_to_opcod << 290 lower = __mem_to_opcod << 291 143 292 /* 144 /* 293 * 25 bit signed addre !! 145 * Do the HI16 relocation. Note that we actually don't 294 * instructions): !! 146 * need to know anything about the LO16 itself, except 295 * S:I1:I2:imm10:imm !! 147 * where to find the low 16 bits of the addend needed 296 * where: !! 148 * by the LO16. 297 * S = upper[10] << 298 * I1 = ~(J1 ^ S) << 299 * I2 = ~(J2 ^ S) << 300 * imm10 = upper[9:0 << 301 * imm11 = lower[10: << 302 * J1 = lower[13] << 303 * J2 = lower[11] << 304 */ 149 */ 305 sign = (upper >> 10) & !! 150 insn = *l->addr; 306 j1 = (lower >> 13) & 1 !! 151 val = ((insn & 0xffff) << 16) + vallo; 307 j2 = (lower >> 11) & 1 !! 152 val += v; 308 offset = (sign << 24) << 309 ((~(j2 ^ sign) << 310 ((upper & 0x03 << 311 ((lower & 0x07 << 312 offset = sign_extend32 << 313 offset += sym->st_valu << 314 153 315 /* 154 /* 316 * Route through a PLT !! 155 * Account for the sign extension that will happen in 317 * supported range. !! 156 * the low bits. 318 */ 157 */ 319 if (IS_ENABLED(CONFIG_ !! 158 val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff; 320 (offset <= (s32)0x << 321 offset >= (s32)0x << 322 offset = get_m << 323 << 324 - loc << 325 << 326 if (offset <= (s32)0xf << 327 offset >= (s32)0x0 << 328 pr_err("%s: se << 329 module- << 330 ELF32_R << 331 sym->st << 332 return -ENOEXE << 333 } << 334 << 335 sign = (offset >> 24) << 336 j1 = sign ^ (~(offset << 337 j2 = sign ^ (~(offset << 338 upper = (u16)((upper & << 339 (( << 340 lower = (u16)((lower & << 341 (j1 << 1 << 342 ((offset << 343 159 344 *(u16 *)loc = __opcode !! 160 insn = (insn & ~0xffff) | val; 345 *(u16 *)(loc + 2) = __ !! 161 *l->addr = insn; 346 break; !! 162 >> 163 next = l->next; >> 164 kfree(l); >> 165 l = next; >> 166 } 347 167 348 case R_ARM_THM_MOVW_ABS_NC: !! 168 me->arch.r_mips_hi16_list = NULL; 349 case R_ARM_THM_MOVT_ABS: !! 169 } 350 case R_ARM_THM_MOVW_PREL_NC: << 351 case R_ARM_THM_MOVT_PREL: << 352 upper = __mem_to_opcod << 353 lower = __mem_to_opcod << 354 170 355 /* !! 171 /* 356 * MOVT/MOVW instructi !! 172 * Ok, we're done with the HI16 relocs. Now deal with the LO16. 357 * !! 173 */ 358 * i = upper[10] !! 174 val = v + vallo; 359 * imm4 = upper[3:0] !! 175 insnlo = (insnlo & ~0xffff) | (val & 0xffff); 360 * imm3 = lower[14:12] !! 176 *location = insnlo; 361 * imm8 = lower[7:0] << 362 * << 363 * imm16 = imm4:i:imm3 << 364 */ << 365 offset = ((upper & 0x0 << 366 ((upper & 0x04 << 367 ((lower & 0x70 << 368 offset = sign_extend32 << 369 offset += sym->st_valu << 370 << 371 if (ELF32_R_TYPE(rel-> << 372 ELF32_R_TYPE(rel-> << 373 offset -= loc; << 374 if (ELF32_R_TYPE(rel-> << 375 ELF32_R_TYPE(rel-> << 376 offset >>= 16; << 377 << 378 upper = (u16)((upper & << 379 ((offset << 380 ((offset << 381 lower = (u16)((lower & << 382 ((offset << 383 (offset << 384 *(u16 *)loc = __opcode << 385 *(u16 *)(loc + 2) = __ << 386 break; << 387 #endif << 388 177 389 default: !! 178 return 0; 390 pr_err("%s: unknown re !! 179 391 module->name, E !! 180 out_danger: 392 return -ENOEXEC; !! 181 free_relocation_chain(l); 393 } !! 182 me->arch.r_mips_hi16_list = NULL; >> 183 >> 184 pr_err("module %s: dangerous R_MIPS_LO16 relocation\n", me->name); >> 185 >> 186 return -ENOEXEC; >> 187 } >> 188 >> 189 static int apply_r_mips_pc(struct module *me, u32 *location, u32 base, >> 190 Elf_Addr v, unsigned int bits) >> 191 { >> 192 unsigned long mask = GENMASK(bits - 1, 0); >> 193 unsigned long se_bits; >> 194 long offset; >> 195 >> 196 if (v % 4) { >> 197 pr_err("module %s: dangerous R_MIPS_PC%u relocation\n", >> 198 me->name, bits); >> 199 return -ENOEXEC; >> 200 } >> 201 >> 202 /* retrieve & sign extend implicit addend if any */ >> 203 offset = base & mask; >> 204 offset |= (offset & BIT(bits - 1)) ? ~mask : 0; >> 205 >> 206 offset += ((long)v - (long)location) >> 2; >> 207 >> 208 /* check the sign bit onwards are identical - ie. we didn't overflow */ >> 209 se_bits = (offset & BIT(bits - 1)) ? ~0ul : 0; >> 210 if ((offset & ~mask) != (se_bits & ~mask)) { >> 211 pr_err("module %s: relocation overflow\n", me->name); >> 212 return -ENOEXEC; 394 } 213 } >> 214 >> 215 *location = (*location & ~mask) | (offset & mask); >> 216 395 return 0; 217 return 0; 396 } 218 } 397 219 398 static const Elf_Shdr *find_mod_section(const !! 220 static int apply_r_mips_pc16(struct module *me, u32 *location, 399 const Elf_Shdr *sechdrs, const char *n !! 221 u32 base, Elf_Addr v, bool rela) >> 222 { >> 223 return apply_r_mips_pc(me, location, base, v, 16); >> 224 } >> 225 >> 226 static int apply_r_mips_pc21(struct module *me, u32 *location, >> 227 u32 base, Elf_Addr v, bool rela) >> 228 { >> 229 return apply_r_mips_pc(me, location, base, v, 21); >> 230 } >> 231 >> 232 static int apply_r_mips_pc26(struct module *me, u32 *location, >> 233 u32 base, Elf_Addr v, bool rela) 400 { 234 { 401 const Elf_Shdr *s, *se; !! 235 return apply_r_mips_pc(me, location, base, v, 26); 402 const char *secstrs = (void *)hdr + se !! 236 } >> 237 >> 238 static int apply_r_mips_64(struct module *me, u32 *location, >> 239 u32 base, Elf_Addr v, bool rela) >> 240 { >> 241 if (WARN_ON(!rela)) >> 242 return -EINVAL; 403 243 404 for (s = sechdrs, se = sechdrs + hdr-> !! 244 *(Elf_Addr *)location = v; 405 if (strcmp(name, secstrs + s-> << 406 return s; << 407 245 408 return NULL; !! 246 return 0; 409 } 247 } 410 248 411 extern void fixup_pv_table(const void *, unsig !! 249 static int apply_r_mips_higher(struct module *me, u32 *location, 412 extern void fixup_smp(const void *, unsigned l !! 250 u32 base, Elf_Addr v, bool rela) >> 251 { >> 252 if (WARN_ON(!rela)) >> 253 return -EINVAL; >> 254 >> 255 *location = (*location & 0xffff0000) | >> 256 ((((long long)v + 0x80008000LL) >> 32) & 0xffff); 413 257 414 int module_finalize(const Elf32_Ehdr *hdr, con !! 258 return 0; 415 struct module *mod) !! 259 } >> 260 >> 261 static int apply_r_mips_highest(struct module *me, u32 *location, >> 262 u32 base, Elf_Addr v, bool rela) 416 { 263 { 417 const Elf_Shdr *s = NULL; !! 264 if (WARN_ON(!rela)) 418 #ifdef CONFIG_ARM_UNWIND !! 265 return -EINVAL; 419 const char *secstrs = (void *)hdr + se << 420 const Elf_Shdr *sechdrs_end = sechdrs << 421 struct list_head *unwind_list = &mod-> << 422 266 423 INIT_LIST_HEAD(unwind_list); !! 267 *location = (*location & 0xffff0000) | 424 mod->arch.init_table = NULL; !! 268 ((((long long)v + 0x800080008000LL) >> 48) & 0xffff); 425 269 426 for (s = sechdrs; s < sechdrs_end; s++ !! 270 return 0; 427 const char *secname = secstrs !! 271 } 428 const char *txtname; << 429 const Elf_Shdr *txt_sec; << 430 272 431 if (!(s->sh_flags & SHF_ALLOC) !! 273 /** 432 s->sh_type != ELF_SECTION_ !! 274 * reloc_handler() - Apply a particular relocation to a module 433 continue; !! 275 * @me: the module to apply the reloc to >> 276 * @location: the address at which the reloc is to be applied >> 277 * @base: the existing value at location for REL-style; 0 for RELA-style >> 278 * @v: the value of the reloc, with addend for RELA-style >> 279 * >> 280 * Each implemented reloc_handler function applies a particular type of >> 281 * relocation to the module @me. Relocs that may be found in either REL or RELA >> 282 * variants can be handled by making use of the @base & @v parameters which are >> 283 * set to values which abstract the difference away from the particular reloc >> 284 * implementations. >> 285 * >> 286 * Return: 0 upon success, else -ERRNO >> 287 */ >> 288 typedef int (*reloc_handler)(struct module *me, u32 *location, >> 289 u32 base, Elf_Addr v, bool rela); >> 290 >> 291 /* The handlers for known reloc types */ >> 292 static reloc_handler reloc_handlers[] = { >> 293 [R_MIPS_NONE] = apply_r_mips_none, >> 294 [R_MIPS_32] = apply_r_mips_32, >> 295 [R_MIPS_26] = apply_r_mips_26, >> 296 [R_MIPS_HI16] = apply_r_mips_hi16, >> 297 [R_MIPS_LO16] = apply_r_mips_lo16, >> 298 [R_MIPS_PC16] = apply_r_mips_pc16, >> 299 [R_MIPS_64] = apply_r_mips_64, >> 300 [R_MIPS_HIGHER] = apply_r_mips_higher, >> 301 [R_MIPS_HIGHEST] = apply_r_mips_highest, >> 302 [R_MIPS_PC21_S2] = apply_r_mips_pc21, >> 303 [R_MIPS_PC26_S2] = apply_r_mips_pc26, >> 304 }; >> 305 >> 306 static int __apply_relocate(Elf_Shdr *sechdrs, const char *strtab, >> 307 unsigned int symindex, unsigned int relsec, >> 308 struct module *me, bool rela) >> 309 { >> 310 union { >> 311 Elf_Mips_Rel *rel; >> 312 Elf_Mips_Rela *rela; >> 313 } r; >> 314 reloc_handler handler; >> 315 Elf_Sym *sym; >> 316 u32 *location, base; >> 317 unsigned int i, type; >> 318 Elf_Addr v; >> 319 int err = 0; >> 320 size_t reloc_sz; >> 321 >> 322 pr_debug("Applying relocate section %u to %u\n", relsec, >> 323 sechdrs[relsec].sh_info); >> 324 >> 325 r.rel = (void *)sechdrs[relsec].sh_addr; >> 326 reloc_sz = rela ? sizeof(*r.rela) : sizeof(*r.rel); >> 327 me->arch.r_mips_hi16_list = NULL; >> 328 for (i = 0; i < sechdrs[relsec].sh_size / reloc_sz; i++) { >> 329 /* This is where to make the change */ >> 330 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr >> 331 + r.rel->r_offset; >> 332 /* This is the symbol it is referring to */ >> 333 sym = (Elf_Sym *)sechdrs[symindex].sh_addr >> 334 + ELF_MIPS_R_SYM(*r.rel); >> 335 if (sym->st_value >= -MAX_ERRNO) { >> 336 /* Ignore unresolved weak symbol */ >> 337 if (ELF_ST_BIND(sym->st_info) == STB_WEAK) >> 338 continue; >> 339 pr_warn("%s: Unknown symbol %s\n", >> 340 me->name, strtab + sym->st_name); >> 341 err = -ENOENT; >> 342 goto out; >> 343 } 434 344 435 if (!strcmp(".ARM.exidx", secn !! 345 type = ELF_MIPS_R_TYPE(*r.rel); 436 txtname = ".text"; !! 346 if (type < ARRAY_SIZE(reloc_handlers)) >> 347 handler = reloc_handlers[type]; 437 else 348 else 438 txtname = secname + st !! 349 handler = NULL; 439 txt_sec = find_mod_section(hdr !! 350 >> 351 if (!handler) { >> 352 pr_err("%s: Unknown relocation type %u\n", >> 353 me->name, type); >> 354 err = -EINVAL; >> 355 goto out; >> 356 } 440 357 441 if (txt_sec) { !! 358 if (rela) { 442 struct unwind_table *t !! 359 v = sym->st_value + r.rela->r_addend; 443 unwind_table_a !! 360 base = 0; 444 !! 361 r.rela = &r.rela[1]; 445 !! 362 } else { 446 !! 363 v = sym->st_value; 447 !! 364 base = *location; 448 list_add(&table->mod_l !! 365 r.rel = &r.rel[1]; 449 << 450 /* save init table for << 451 if (strcmp(".ARM.exidx << 452 mod->arch.init << 453 } 366 } >> 367 >> 368 err = handler(me, location, base, v, rela); >> 369 if (err) >> 370 goto out; 454 } 371 } 455 #endif !! 372 456 #ifdef CONFIG_ARM_PATCH_PHYS_VIRT !! 373 out: 457 s = find_mod_section(hdr, sechdrs, ".p !! 374 /* 458 if (s) !! 375 * Normally the hi16 list should be deallocated at this point. A 459 fixup_pv_table((void *)s->sh_a !! 376 * malformed binary however could contain a series of R_MIPS_HI16 460 #endif !! 377 * relocations not followed by a R_MIPS_LO16 relocation, or if we hit 461 s = find_mod_section(hdr, sechdrs, ".a !! 378 * an error processing a reloc we might have gotten here before 462 if (s && !is_smp()) !! 379 * reaching the R_MIPS_LO16. In either case, free up the list and 463 #ifdef CONFIG_SMP_ON_UP !! 380 * return an error. 464 fixup_smp((void *)s->sh_addr, !! 381 */ 465 #else !! 382 if (me->arch.r_mips_hi16_list) { 466 return -EINVAL; !! 383 free_relocation_chain(me->arch.r_mips_hi16_list); 467 #endif !! 384 me->arch.r_mips_hi16_list = NULL; 468 return 0; !! 385 err = err ?: -ENOEXEC; >> 386 } >> 387 >> 388 return err; 469 } 389 } 470 390 471 void !! 391 int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, 472 module_arch_cleanup(struct module *mod) !! 392 unsigned int symindex, unsigned int relsec, >> 393 struct module *me) 473 { 394 { 474 #ifdef CONFIG_ARM_UNWIND !! 395 return __apply_relocate(sechdrs, strtab, symindex, relsec, me, false); 475 struct unwind_table *tmp; !! 396 } 476 struct unwind_table *n; !! 397 477 !! 398 #ifdef CONFIG_MODULES_USE_ELF_RELA 478 list_for_each_entry_safe(tmp, n, !! 399 int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, 479 &mod->arch.unwind_list !! 400 unsigned int symindex, unsigned int relsec, 480 list_del(&tmp->mod_list); !! 401 struct module *me) 481 unwind_table_del(tmp); !! 402 { >> 403 return __apply_relocate(sechdrs, strtab, symindex, relsec, me, true); >> 404 } >> 405 #endif /* CONFIG_MODULES_USE_ELF_RELA */ >> 406 >> 407 /* Given an address, look for it in the module exception tables. */ >> 408 const struct exception_table_entry *search_module_dbetables(unsigned long addr) >> 409 { >> 410 unsigned long flags; >> 411 const struct exception_table_entry *e = NULL; >> 412 struct mod_arch_specific *dbe; >> 413 >> 414 spin_lock_irqsave(&dbe_lock, flags); >> 415 list_for_each_entry(dbe, &dbe_list, dbe_list) { >> 416 e = search_extable(dbe->dbe_start, >> 417 dbe->dbe_end - dbe->dbe_start, addr); >> 418 if (e) >> 419 break; 482 } 420 } 483 mod->arch.init_table = NULL; !! 421 spin_unlock_irqrestore(&dbe_lock, flags); 484 #endif !! 422 >> 423 /* Now, if we found one, we are running inside it now, hence >> 424 we cannot unload the module, hence no refcnt needed. */ >> 425 return e; 485 } 426 } 486 427 487 void __weak module_arch_freeing_init(struct mo !! 428 /* Put in dbe list if necessary. */ >> 429 int module_finalize(const Elf_Ehdr *hdr, >> 430 const Elf_Shdr *sechdrs, >> 431 struct module *me) 488 { 432 { 489 #ifdef CONFIG_ARM_UNWIND !! 433 const Elf_Shdr *s; 490 struct unwind_table *init = mod->arch. !! 434 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; >> 435 >> 436 /* Make jump label nops. */ >> 437 jump_label_apply_nops(me); 491 438 492 if (init) { !! 439 INIT_LIST_HEAD(&me->arch.dbe_list); 493 mod->arch.init_table = NULL; !! 440 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { 494 list_del(&init->mod_list); !! 441 if (strcmp("__dbe_table", secstrings + s->sh_name) != 0) 495 unwind_table_del(init); !! 442 continue; >> 443 me->arch.dbe_start = (void *)s->sh_addr; >> 444 me->arch.dbe_end = (void *)s->sh_addr + s->sh_size; >> 445 spin_lock_irq(&dbe_lock); >> 446 list_add(&me->arch.dbe_list, &dbe_list); >> 447 spin_unlock_irq(&dbe_lock); 496 } 448 } 497 #endif !! 449 return 0; >> 450 } >> 451 >> 452 void module_arch_cleanup(struct module *mod) >> 453 { >> 454 spin_lock_irq(&dbe_lock); >> 455 list_del(&mod->arch.dbe_list); >> 456 spin_unlock_irq(&dbe_lock); 498 } 457 } 499 458
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.