Lines Matching +full:mod +full:- +full:12 +full:b
1 // SPDX-License-Identifier: GPL-2.0-only
42 * A single PC-relative symbol reference is divided in up to 3 add or subtract
52 * -/+ 256 MiB, (2x8 + 12 == 28 bits), which means it has sufficient range for
53 * any in-kernel symbol reference (unless module PLTs are being used).
56 * load is that literal loads may miss in the D-cache, and generally lead to
65 shift = val ? (31 - __fls(val)) & ~1 : 32; in get_group_rem()
70 } while (group--); in get_group_rem()
81 Elf32_Shdr *dstsec = sechdrs + relsec->sh_info; in apply_relocate()
82 Elf32_Rel *rel = (void *)relsec->sh_addr; in apply_relocate()
85 for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { in apply_relocate()
98 offset = ELF32_R_SYM(rel->r_info); in apply_relocate()
99 if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { in apply_relocate()
101 module->name, relindex, i); in apply_relocate()
102 return -ENOEXEC; in apply_relocate()
105 sym = ((Elf32_Sym *)symsec->sh_addr) + offset; in apply_relocate()
106 symname = strtab + sym->st_name; in apply_relocate()
108 if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { in apply_relocate()
110 module->name, relindex, i, symname, in apply_relocate()
111 rel->r_offset, dstsec->sh_size); in apply_relocate()
112 return -ENOEXEC; in apply_relocate()
115 loc = dstsec->sh_addr + rel->r_offset; in apply_relocate()
117 switch (ELF32_R_TYPE(rel->r_info)) { in apply_relocate()
124 *(u32 *)loc += sym->st_value; in apply_relocate()
130 if (sym->st_value & 3) { in apply_relocate()
131 pr_err("%s: section %u reloc %u sym '%s': unsupported interworking call (ARM -> Thumb)\n", in apply_relocate()
132 module->name, relindex, i, symname); in apply_relocate()
133 return -ENOEXEC; in apply_relocate()
140 offset += sym->st_value - loc; in apply_relocate()
153 - loc - 8; in apply_relocate()
157 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", in apply_relocate()
158 module->name, relindex, i, symname, in apply_relocate()
159 ELF32_R_TYPE(rel->r_info), loc, in apply_relocate()
160 sym->st_value); in apply_relocate()
161 return -ENOEXEC; in apply_relocate()
173 * other bits to re-code instruction as in apply_relocate()
182 offset += sym->st_value - loc; in apply_relocate()
183 if (offset >= 0x40000000 || offset < -0x40000000) { in apply_relocate()
184 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", in apply_relocate()
185 module->name, relindex, i, symname, in apply_relocate()
186 ELF32_R_TYPE(rel->r_info), loc, in apply_relocate()
187 sym->st_value); in apply_relocate()
188 return -ENOEXEC; in apply_relocate()
195 *(u32 *)loc += sym->st_value - loc; in apply_relocate()
206 offset += sym->st_value; in apply_relocate()
207 if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_PREL || in apply_relocate()
208 ELF32_R_TYPE(rel->r_info) == R_ARM_MOVW_PREL_NC) in apply_relocate()
209 offset -= loc; in apply_relocate()
210 if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS || in apply_relocate()
211 ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_PREL) in apply_relocate()
229 offset = -offset; in apply_relocate()
230 offset += sym->st_value - loc; in apply_relocate()
232 offset = -offset; in apply_relocate()
240 offset >>= 24 - shift; in apply_relocate()
250 offset = -offset; in apply_relocate()
251 offset += sym->st_value - loc; in apply_relocate()
253 offset = -offset; in apply_relocate()
261 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", in apply_relocate()
262 module->name, relindex, i, symname, in apply_relocate()
263 ELF32_R_TYPE(rel->r_info), loc, in apply_relocate()
264 sym->st_value); in apply_relocate()
265 return -ENOEXEC; in apply_relocate()
277 * For non-function symbols, the destination in apply_relocate()
282 if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && in apply_relocate()
283 !(sym->st_value & 1)) { in apply_relocate()
284 pr_err("%s: section %u reloc %u sym '%s': unsupported interworking call (Thumb -> ARM)\n", in apply_relocate()
285 module->name, relindex, i, symname); in apply_relocate()
286 return -ENOEXEC; in apply_relocate()
293 * 25 bit signed address range (Thumb-2 BL and B.W in apply_relocate()
300 * imm10 = upper[9:0] = offset[21:12] in apply_relocate()
310 ((upper & 0x03ff) << 12) | in apply_relocate()
313 offset += sym->st_value - loc; in apply_relocate()
324 - loc - 4; in apply_relocate()
328 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", in apply_relocate()
329 module->name, relindex, i, symname, in apply_relocate()
330 ELF32_R_TYPE(rel->r_info), loc, in apply_relocate()
331 sym->st_value); in apply_relocate()
332 return -ENOEXEC; in apply_relocate()
339 ((offset >> 12) & 0x03ff)); in apply_relocate()
356 * MOVT/MOVW instructions encoding in Thumb-2: in apply_relocate()
360 * imm3 = lower[14:12] in apply_relocate()
365 offset = ((upper & 0x000f) << 12) | in apply_relocate()
369 offset += sym->st_value; in apply_relocate()
371 if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_PREL || in apply_relocate()
372 ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVW_PREL_NC) in apply_relocate()
373 offset -= loc; in apply_relocate()
374 if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS || in apply_relocate()
375 ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_PREL) in apply_relocate()
379 ((offset & 0xf000) >> 12) | in apply_relocate()
391 module->name, ELF32_R_TYPE(rel->r_info)); in apply_relocate()
392 return -ENOEXEC; in apply_relocate()
402 const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; in find_mod_section()
404 for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) in find_mod_section()
405 if (strcmp(name, secstrs + s->sh_name) == 0) in find_mod_section()
415 struct module *mod) in module_finalize() argument
419 const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; in module_finalize()
420 const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum; in module_finalize()
421 struct list_head *unwind_list = &mod->arch.unwind_list; in module_finalize()
424 mod->arch.init_table = NULL; in module_finalize()
427 const char *secname = secstrs + s->sh_name; in module_finalize()
431 if (!(s->sh_flags & SHF_ALLOC) || in module_finalize()
432 s->sh_type != ELF_SECTION_UNWIND) in module_finalize()
443 unwind_table_add(s->sh_addr, in module_finalize()
444 s->sh_size, in module_finalize()
445 txt_sec->sh_addr, in module_finalize()
446 txt_sec->sh_size); in module_finalize()
448 list_add(&table->mod_list, unwind_list); in module_finalize()
452 mod->arch.init_table = table; in module_finalize()
459 fixup_pv_table((void *)s->sh_addr, s->sh_size); in module_finalize()
464 fixup_smp((void *)s->sh_addr, s->sh_size); in module_finalize()
466 return -EINVAL; in module_finalize()
472 module_arch_cleanup(struct module *mod) in module_arch_cleanup() argument
479 &mod->arch.unwind_list, mod_list) { in module_arch_cleanup()
480 list_del(&tmp->mod_list); in module_arch_cleanup()
483 mod->arch.init_table = NULL; in module_arch_cleanup()
487 void __weak module_arch_freeing_init(struct module *mod) in module_arch_freeing_init() argument
490 struct unwind_table *init = mod->arch.init_table; in module_arch_freeing_init()
493 mod->arch.init_table = NULL; in module_arch_freeing_init()
494 list_del(&init->mod_list); in module_arch_freeing_init()