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