1 // SPDX-License-Identifier: GPL-2.0-only << 2 /* 1 /* 3 * linux/arch/arm/kernel/module.c !! 2 * This program is free software; you can redistribute it and/or modify >> 3 * it under the terms of the GNU General Public License as published by >> 4 * the Free Software Foundation; either version 2 of the License, or >> 5 * (at your option) any later version. 4 * 6 * 5 * Copyright (C) 2002 Russell King. !! 7 * This program is distributed in the hope that it will be useful, 6 * Modified for nommu by Hyok S. Choi !! 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of >> 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> 10 * GNU General Public License for more details. 7 * 11 * 8 * Module allocation method suggested by Andi !! 12 * You should have received a copy of the GNU General Public License >> 13 * along with this program; if not, write to the Free Software >> 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >> 15 * >> 16 * Copyright (C) 2001 Rusty Russell. >> 17 * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org) >> 18 * Copyright (C) 2005 Thiemo Seufer 9 */ 19 */ 10 #include <linux/module.h> !! 20 >> 21 #undef DEBUG >> 22 >> 23 #include <linux/extable.h> 11 #include <linux/moduleloader.h> 24 #include <linux/moduleloader.h> 12 #include <linux/kernel.h> << 13 #include <linux/mm.h> << 14 #include <linux/elf.h> 25 #include <linux/elf.h> >> 26 #include <linux/mm.h> >> 27 #include <linux/numa.h> >> 28 #include <linux/vmalloc.h> >> 29 #include <linux/slab.h> 15 #include <linux/fs.h> 30 #include <linux/fs.h> 16 #include <linux/string.h> 31 #include <linux/string.h> >> 32 #include <linux/kernel.h> >> 33 #include <linux/spinlock.h> >> 34 #include <linux/jump_label.h> 17 35 18 #include <asm/sections.h> !! 36 #include <asm/pgtable.h> /* MODULE_START */ 19 #include <asm/smp_plat.h> << 20 #include <asm/unwind.h> << 21 #include <asm/opcodes.h> << 22 37 23 bool module_init_section(const char *name) !! 38 struct mips_hi16 { 24 { !! 39 struct mips_hi16 *next; 25 return strstarts(name, ".init") || !! 40 Elf_Addr *addr; 26 strstarts(name, ".ARM.extab.in !! 41 Elf_Addr value; 27 strstarts(name, ".ARM.exidx.in !! 42 }; 28 } << 29 43 30 bool module_exit_section(const char *name) !! 44 static LIST_HEAD(dbe_list); 31 { !! 45 static DEFINE_SPINLOCK(dbe_lock); 32 return strstarts(name, ".exit") || << 33 strstarts(name, ".ARM.extab.ex << 34 strstarts(name, ".ARM.exidx.ex << 35 } << 36 46 37 #ifdef CONFIG_ARM_HAS_GROUP_RELOCS !! 47 #ifdef MODULE_START 38 /* !! 48 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 { 49 { 62 u32 val = *offset; !! 50 return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END, 63 u32 shift; !! 51 GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE, 64 do { !! 52 __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 } 53 } 73 #endif 54 #endif 74 55 75 int !! 56 int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v) 76 apply_relocate(Elf32_Shdr *sechdrs, const char !! 57 { 77 unsigned int relindex, struct m !! 58 return 0; 78 { !! 59 } 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 << 105 sym = ((Elf32_Sym *)symsec->sh << 106 symname = strtab + sym->st_nam << 107 << 108 if (rel->r_offset < 0 || rel-> << 109 pr_err("%s: section %u << 110 module->name, r << 111 rel->r_offset, << 112 return -ENOEXEC; << 113 } << 114 << 115 loc = dstsec->sh_addr + rel->r << 116 60 117 switch (ELF32_R_TYPE(rel->r_in !! 61 static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v) 118 case R_ARM_NONE: !! 62 { 119 /* ignore */ !! 63 *location += v; 120 break; << 121 64 122 case R_ARM_ABS32: !! 65 return 0; 123 case R_ARM_TARGET1: !! 66 } 124 *(u32 *)loc += sym->st << 125 break; << 126 67 127 case R_ARM_PC24: !! 68 static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) 128 case R_ARM_CALL: !! 69 { 129 case R_ARM_JUMP24: !! 70 if (v % 4) { 130 if (sym->st_value & 3) !! 71 pr_err("module %s: dangerous R_MIPS_26 REL relocation\n", 131 pr_err("%s: se !! 72 me->name); 132 module- !! 73 return -ENOEXEC; 133 return -ENOEXE !! 74 } 134 } << 135 << 136 offset = __mem_to_opco << 137 offset = (offset & 0x0 << 138 offset = sign_extend32 << 139 75 140 offset += sym->st_valu !! 76 if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { >> 77 pr_err("module %s: relocation overflow\n", >> 78 me->name); >> 79 return -ENOEXEC; >> 80 } 141 81 142 /* !! 82 *location = (*location & ~0x03ffffff) | 143 * Route through a PLT !! 83 ((*location + (v >> 2)) & 0x03ffffff); 144 * supported range. No << 145 * contains the absolu << 146 * @sym + addend, corr << 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 84 164 offset >>= 2; !! 85 return 0; 165 offset &= 0x00ffffff; !! 86 } 166 87 167 *(u32 *)loc &= __opcod !! 88 static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) 168 *(u32 *)loc |= __opcod !! 89 { 169 break; !! 90 struct mips_hi16 *n; 170 91 171 case R_ARM_V4BX: !! 92 /* 172 /* Preserve Rm and the !! 93 * We cannot relocate this one now because we don't know the value of 173 * other bits to re-cod !! 94 * the carry we need to add. Save the information, and let LO16 do the 174 * MOV PC,Rm. !! 95 * actual relocation. 175 */ !! 96 */ 176 *(u32 *)loc &= __opcode !! 97 n = kmalloc(sizeof *n, GFP_KERNEL); 177 *(u32 *)loc |= __opcode !! 98 if (!n) 178 break; !! 99 return -ENOMEM; 179 !! 100 180 case R_ARM_PREL31: !! 101 n->addr = (Elf_Addr *)location; 181 offset = (*(s32 *)loc !! 102 n->value = v; 182 offset += sym->st_valu !! 103 n->next = me->arch.r_mips_hi16_list; 183 if (offset >= 0x400000 !! 104 me->arch.r_mips_hi16_list = n; 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 105 194 case R_ARM_REL32: !! 106 return 0; 195 *(u32 *)loc += sym->st !! 107 } 196 break; << 197 108 198 case R_ARM_MOVW_ABS_NC: !! 109 static void free_relocation_chain(struct mips_hi16 *l) 199 case R_ARM_MOVT_ABS: !! 110 { 200 case R_ARM_MOVW_PREL_NC: !! 111 struct mips_hi16 *next; 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 112 218 *(u32 *)loc = __opcode !! 113 while (l) { 219 break; !! 114 next = l->next; >> 115 kfree(l); >> 116 l = next; >> 117 } >> 118 } 220 119 221 #ifdef CONFIG_ARM_HAS_GROUP_RELOCS !! 120 static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v) 222 case R_ARM_ALU_PC_G0_NC: !! 121 { 223 group = 0; !! 122 unsigned long insnlo = *location; 224 fallthrough; !! 123 struct mips_hi16 *l; 225 case R_ARM_ALU_PC_G1_NC: !! 124 Elf_Addr val, vallo; 226 tmp = __mem_to_opcode_ !! 125 227 offset = ror32(tmp & 0 !! 126 /* Sign extend the addend we extract from the lo insn. */ 228 if (tmp & BIT(22)) !! 127 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; 229 offset = -offs !! 128 230 offset += sym->st_valu !! 129 if (me->arch.r_mips_hi16_list != NULL) { 231 if (offset < 0) { !! 130 l = me->arch.r_mips_hi16_list; 232 offset = -offs !! 131 while (l != NULL) { 233 tmp = (tmp & ~ !! 132 struct mips_hi16 *next; 234 } else { !! 133 unsigned long insn; 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 134 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 /* 135 /* 274 * For function symbol !! 136 * 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 */ 137 */ 282 if (ELF32_ST_TYPE(sym- !! 138 if (v != l->value) 283 !(sym->st_value & !! 139 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 140 292 /* 141 /* 293 * 25 bit signed addre !! 142 * Do the HI16 relocation. Note that we actually don't 294 * instructions): !! 143 * need to know anything about the LO16 itself, except 295 * S:I1:I2:imm10:imm !! 144 * where to find the low 16 bits of the addend needed 296 * where: !! 145 * 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 */ 146 */ 305 sign = (upper >> 10) & !! 147 insn = *l->addr; 306 j1 = (lower >> 13) & 1 !! 148 val = ((insn & 0xffff) << 16) + vallo; 307 j2 = (lower >> 11) & 1 !! 149 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 150 315 /* 151 /* 316 * Route through a PLT !! 152 * Account for the sign extension that will happen in 317 * supported range. !! 153 * the low bits. 318 */ 154 */ 319 if (IS_ENABLED(CONFIG_ !! 155 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 156 344 *(u16 *)loc = __opcode !! 157 insn = (insn & ~0xffff) | val; 345 *(u16 *)(loc + 2) = __ !! 158 *l->addr = insn; 346 break; << 347 << 348 case R_ARM_THM_MOVW_ABS_NC: << 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 << 355 /* << 356 * MOVT/MOVW instructi << 357 * << 358 * i = upper[10] << 359 * imm4 = upper[3:0] << 360 * imm3 = lower[14:12] << 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 159 389 default: !! 160 next = l->next; 390 pr_err("%s: unknown re !! 161 kfree(l); 391 module->name, E !! 162 l = next; 392 return -ENOEXEC; << 393 } 163 } >> 164 >> 165 me->arch.r_mips_hi16_list = NULL; 394 } 166 } >> 167 >> 168 /* >> 169 * Ok, we're done with the HI16 relocs. Now deal with the LO16. >> 170 */ >> 171 val = v + vallo; >> 172 insnlo = (insnlo & ~0xffff) | (val & 0xffff); >> 173 *location = insnlo; >> 174 395 return 0; 175 return 0; >> 176 >> 177 out_danger: >> 178 free_relocation_chain(l); >> 179 me->arch.r_mips_hi16_list = NULL; >> 180 >> 181 pr_err("module %s: dangerous R_MIPS_LO16 REL relocation\n", me->name); >> 182 >> 183 return -ENOEXEC; 396 } 184 } 397 185 398 static const Elf_Shdr *find_mod_section(const !! 186 static int apply_r_mips_pc_rel(struct module *me, u32 *location, Elf_Addr v, 399 const Elf_Shdr *sechdrs, const char *n !! 187 unsigned bits) 400 { 188 { 401 const Elf_Shdr *s, *se; !! 189 unsigned long mask = GENMASK(bits - 1, 0); 402 const char *secstrs = (void *)hdr + se !! 190 unsigned long se_bits; >> 191 long offset; >> 192 >> 193 if (v % 4) { >> 194 pr_err("module %s: dangerous R_MIPS_PC%u REL relocation\n", >> 195 me->name, bits); >> 196 return -ENOEXEC; >> 197 } >> 198 >> 199 /* retrieve & sign extend implicit addend */ >> 200 offset = *location & mask; >> 201 offset |= (offset & BIT(bits - 1)) ? ~mask : 0; >> 202 >> 203 offset += ((long)v - (long)location) >> 2; >> 204 >> 205 /* check the sign bit onwards are identical - ie. we didn't overflow */ >> 206 se_bits = (offset & BIT(bits - 1)) ? ~0ul : 0; >> 207 if ((offset & ~mask) != (se_bits & ~mask)) { >> 208 pr_err("module %s: relocation overflow\n", me->name); >> 209 return -ENOEXEC; >> 210 } 403 211 404 for (s = sechdrs, se = sechdrs + hdr-> !! 212 *location = (*location & ~mask) | (offset & mask); 405 if (strcmp(name, secstrs + s-> << 406 return s; << 407 213 408 return NULL; !! 214 return 0; 409 } 215 } 410 216 411 extern void fixup_pv_table(const void *, unsig !! 217 static int apply_r_mips_pc16_rel(struct module *me, u32 *location, Elf_Addr v) 412 extern void fixup_smp(const void *, unsigned l !! 218 { >> 219 return apply_r_mips_pc_rel(me, location, v, 16); >> 220 } 413 221 414 int module_finalize(const Elf32_Ehdr *hdr, con !! 222 static int apply_r_mips_pc21_rel(struct module *me, u32 *location, Elf_Addr v) 415 struct module *mod) << 416 { 223 { 417 const Elf_Shdr *s = NULL; !! 224 return apply_r_mips_pc_rel(me, location, v, 21); 418 #ifdef CONFIG_ARM_UNWIND !! 225 } 419 const char *secstrs = (void *)hdr + se << 420 const Elf_Shdr *sechdrs_end = sechdrs << 421 struct list_head *unwind_list = &mod-> << 422 226 423 INIT_LIST_HEAD(unwind_list); !! 227 static int apply_r_mips_pc26_rel(struct module *me, u32 *location, Elf_Addr v) 424 mod->arch.init_table = NULL; !! 228 { >> 229 return apply_r_mips_pc_rel(me, location, v, 26); >> 230 } 425 231 426 for (s = sechdrs; s < sechdrs_end; s++ !! 232 static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, 427 const char *secname = secstrs !! 233 Elf_Addr v) = { 428 const char *txtname; !! 234 [R_MIPS_NONE] = apply_r_mips_none, 429 const Elf_Shdr *txt_sec; !! 235 [R_MIPS_32] = apply_r_mips_32_rel, >> 236 [R_MIPS_26] = apply_r_mips_26_rel, >> 237 [R_MIPS_HI16] = apply_r_mips_hi16_rel, >> 238 [R_MIPS_LO16] = apply_r_mips_lo16_rel, >> 239 [R_MIPS_PC16] = apply_r_mips_pc16_rel, >> 240 [R_MIPS_PC21_S2] = apply_r_mips_pc21_rel, >> 241 [R_MIPS_PC26_S2] = apply_r_mips_pc26_rel, >> 242 }; >> 243 >> 244 int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, >> 245 unsigned int symindex, unsigned int relsec, >> 246 struct module *me) >> 247 { >> 248 Elf_Mips_Rel *rel = (void *) sechdrs[relsec].sh_addr; >> 249 int (*handler)(struct module *me, u32 *location, Elf_Addr v); >> 250 Elf_Sym *sym; >> 251 u32 *location; >> 252 unsigned int i, type; >> 253 Elf_Addr v; >> 254 int res; >> 255 >> 256 pr_debug("Applying relocate section %u to %u\n", relsec, >> 257 sechdrs[relsec].sh_info); >> 258 >> 259 me->arch.r_mips_hi16_list = NULL; >> 260 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { >> 261 /* This is where to make the change */ >> 262 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr >> 263 + rel[i].r_offset; >> 264 /* This is the symbol it is referring to */ >> 265 sym = (Elf_Sym *)sechdrs[symindex].sh_addr >> 266 + ELF_MIPS_R_SYM(rel[i]); >> 267 if (sym->st_value >= -MAX_ERRNO) { >> 268 /* Ignore unresolved weak symbol */ >> 269 if (ELF_ST_BIND(sym->st_info) == STB_WEAK) >> 270 continue; >> 271 pr_warn("%s: Unknown symbol %s\n", >> 272 me->name, strtab + sym->st_name); >> 273 return -ENOENT; >> 274 } 430 275 431 if (!(s->sh_flags & SHF_ALLOC) !! 276 type = ELF_MIPS_R_TYPE(rel[i]); 432 s->sh_type != ELF_SECTION_ << 433 continue; << 434 277 435 if (!strcmp(".ARM.exidx", secn !! 278 if (type < ARRAY_SIZE(reloc_handlers_rel)) 436 txtname = ".text"; !! 279 handler = reloc_handlers_rel[type]; 437 else 280 else 438 txtname = secname + st !! 281 handler = NULL; 439 txt_sec = find_mod_section(hdr << 440 282 441 if (txt_sec) { !! 283 if (!handler) { 442 struct unwind_table *t !! 284 pr_err("%s: Unknown relocation type %u\n", 443 unwind_table_a !! 285 me->name, type); 444 !! 286 return -EINVAL; 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 } 287 } >> 288 >> 289 v = sym->st_value; >> 290 res = handler(me, location, v); >> 291 if (res) >> 292 return res; 454 } 293 } 455 #endif !! 294 456 #ifdef CONFIG_ARM_PATCH_PHYS_VIRT !! 295 /* 457 s = find_mod_section(hdr, sechdrs, ".p !! 296 * Normally the hi16 list should be deallocated at this point. A 458 if (s) !! 297 * malformed binary however could contain a series of R_MIPS_HI16 459 fixup_pv_table((void *)s->sh_a !! 298 * relocations not followed by a R_MIPS_LO16 relocation. In that 460 #endif !! 299 * case, free up the list and return an error. 461 s = find_mod_section(hdr, sechdrs, ".a !! 300 */ 462 if (s && !is_smp()) !! 301 if (me->arch.r_mips_hi16_list) { 463 #ifdef CONFIG_SMP_ON_UP !! 302 free_relocation_chain(me->arch.r_mips_hi16_list); 464 fixup_smp((void *)s->sh_addr, !! 303 me->arch.r_mips_hi16_list = NULL; 465 #else !! 304 466 return -EINVAL; !! 305 return -ENOEXEC; 467 #endif !! 306 } >> 307 468 return 0; 308 return 0; 469 } 309 } 470 310 471 void !! 311 /* Given an address, look for it in the module exception tables. */ 472 module_arch_cleanup(struct module *mod) !! 312 const struct exception_table_entry *search_module_dbetables(unsigned long addr) 473 { 313 { 474 #ifdef CONFIG_ARM_UNWIND !! 314 unsigned long flags; 475 struct unwind_table *tmp; !! 315 const struct exception_table_entry *e = NULL; 476 struct unwind_table *n; !! 316 struct mod_arch_specific *dbe; 477 !! 317 478 list_for_each_entry_safe(tmp, n, !! 318 spin_lock_irqsave(&dbe_lock, flags); 479 &mod->arch.unwind_list !! 319 list_for_each_entry(dbe, &dbe_list, dbe_list) { 480 list_del(&tmp->mod_list); !! 320 e = search_extable(dbe->dbe_start, dbe->dbe_end - 1, addr); 481 unwind_table_del(tmp); !! 321 if (e) >> 322 break; 482 } 323 } 483 mod->arch.init_table = NULL; !! 324 spin_unlock_irqrestore(&dbe_lock, flags); 484 #endif !! 325 >> 326 /* Now, if we found one, we are running inside it now, hence >> 327 we cannot unload the module, hence no refcnt needed. */ >> 328 return e; 485 } 329 } 486 330 487 void __weak module_arch_freeing_init(struct mo !! 331 /* Put in dbe list if necessary. */ >> 332 int module_finalize(const Elf_Ehdr *hdr, >> 333 const Elf_Shdr *sechdrs, >> 334 struct module *me) 488 { 335 { 489 #ifdef CONFIG_ARM_UNWIND !! 336 const Elf_Shdr *s; 490 struct unwind_table *init = mod->arch. !! 337 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; >> 338 >> 339 /* Make jump label nops. */ >> 340 jump_label_apply_nops(me); 491 341 492 if (init) { !! 342 INIT_LIST_HEAD(&me->arch.dbe_list); 493 mod->arch.init_table = NULL; !! 343 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { 494 list_del(&init->mod_list); !! 344 if (strcmp("__dbe_table", secstrings + s->sh_name) != 0) 495 unwind_table_del(init); !! 345 continue; >> 346 me->arch.dbe_start = (void *)s->sh_addr; >> 347 me->arch.dbe_end = (void *)s->sh_addr + s->sh_size; >> 348 spin_lock_irq(&dbe_lock); >> 349 list_add(&me->arch.dbe_list, &dbe_list); >> 350 spin_unlock_irq(&dbe_lock); 496 } 351 } 497 #endif !! 352 return 0; >> 353 } >> 354 >> 355 void module_arch_cleanup(struct module *mod) >> 356 { >> 357 spin_lock_irq(&dbe_lock); >> 358 list_del(&mod->arch.dbe_list); >> 359 spin_unlock_irq(&dbe_lock); 498 } 360 } 499 361
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.