Lines Matching +full:lower +full:- +full:case
1 // SPDX-License-Identifier: GPL-2.0-only
76 * A single PC-relative symbol reference is divided in up to 3 add or subtract
86 * -/+ 256 MiB, (2x8 + 12 == 28 bits), which means it has sufficient range for
87 * any in-kernel symbol reference (unless module PLTs are being used).
90 * load is that literal loads may miss in the D-cache, and generally lead to
91 * lower cache efficiency for variables that are referenced often from many
99 shift = val ? (31 - __fls(val)) & ~1 : 32; in get_group_rem()
104 } while (group--); in get_group_rem()
115 Elf32_Shdr *dstsec = sechdrs + relsec->sh_info; in apply_relocate()
116 Elf32_Rel *rel = (void *)relsec->sh_addr; in apply_relocate()
119 for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { in apply_relocate()
129 u32 upper, lower, sign, j1, j2; in apply_relocate() local
132 offset = ELF32_R_SYM(rel->r_info); in apply_relocate()
133 if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { in apply_relocate()
135 module->name, relindex, i); in apply_relocate()
136 return -ENOEXEC; in apply_relocate()
139 sym = ((Elf32_Sym *)symsec->sh_addr) + offset; in apply_relocate()
140 symname = strtab + sym->st_name; in apply_relocate()
142 if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { in apply_relocate()
144 module->name, relindex, i, symname, in apply_relocate()
145 rel->r_offset, dstsec->sh_size); in apply_relocate()
146 return -ENOEXEC; in apply_relocate()
149 loc = dstsec->sh_addr + rel->r_offset; in apply_relocate()
151 switch (ELF32_R_TYPE(rel->r_info)) { in apply_relocate()
152 case R_ARM_NONE: in apply_relocate()
156 case R_ARM_ABS32: in apply_relocate()
157 case R_ARM_TARGET1: in apply_relocate()
158 *(u32 *)loc += sym->st_value; in apply_relocate()
161 case R_ARM_PC24: in apply_relocate()
162 case R_ARM_CALL: in apply_relocate()
163 case R_ARM_JUMP24: in apply_relocate()
164 if (sym->st_value & 3) { in apply_relocate()
165 pr_err("%s: section %u reloc %u sym '%s': unsupported interworking call (ARM -> Thumb)\n", in apply_relocate()
166 module->name, relindex, i, symname); in apply_relocate()
167 return -ENOEXEC; in apply_relocate()
173 offset -= 0x04000000; in apply_relocate()
175 offset += sym->st_value - loc; in apply_relocate()
188 - loc - 8; in apply_relocate()
192 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", in apply_relocate()
193 module->name, relindex, i, symname, in apply_relocate()
194 ELF32_R_TYPE(rel->r_info), loc, in apply_relocate()
195 sym->st_value); in apply_relocate()
196 return -ENOEXEC; in apply_relocate()
206 case R_ARM_V4BX: in apply_relocate()
208 * other bits to re-code instruction as in apply_relocate()
215 case R_ARM_PREL31: in apply_relocate()
217 offset += sym->st_value - loc; in apply_relocate()
218 if (offset >= 0x40000000 || offset < -0x40000000) { in apply_relocate()
219 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", in apply_relocate()
220 module->name, relindex, i, symname, in apply_relocate()
221 ELF32_R_TYPE(rel->r_info), loc, in apply_relocate()
222 sym->st_value); in apply_relocate()
223 return -ENOEXEC; in apply_relocate()
229 case R_ARM_REL32: in apply_relocate()
230 *(u32 *)loc += sym->st_value - loc; in apply_relocate()
233 case R_ARM_MOVW_ABS_NC: in apply_relocate()
234 case R_ARM_MOVT_ABS: in apply_relocate()
235 case R_ARM_MOVW_PREL_NC: in apply_relocate()
236 case R_ARM_MOVT_PREL: in apply_relocate()
239 offset = (offset ^ 0x8000) - 0x8000; in apply_relocate()
241 offset += sym->st_value; in apply_relocate()
242 if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_PREL || in apply_relocate()
243 ELF32_R_TYPE(rel->r_info) == R_ARM_MOVW_PREL_NC) in apply_relocate()
244 offset -= loc; in apply_relocate()
245 if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS || in apply_relocate()
246 ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_PREL) in apply_relocate()
257 case R_ARM_ALU_PC_G0_NC: in apply_relocate()
260 case R_ARM_ALU_PC_G1_NC: in apply_relocate()
264 offset = -offset; in apply_relocate()
265 offset += sym->st_value - loc; in apply_relocate()
267 offset = -offset; in apply_relocate()
275 offset >>= 24 - shift; in apply_relocate()
281 case R_ARM_LDR_PC_G2: in apply_relocate()
285 offset = -offset; in apply_relocate()
286 offset += sym->st_value - loc; in apply_relocate()
288 offset = -offset; in apply_relocate()
296 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", in apply_relocate()
297 module->name, relindex, i, symname, in apply_relocate()
298 ELF32_R_TYPE(rel->r_info), loc, in apply_relocate()
299 sym->st_value); in apply_relocate()
300 return -ENOEXEC; in apply_relocate()
306 case R_ARM_THM_CALL: in apply_relocate()
307 case R_ARM_THM_JUMP24: in apply_relocate()
312 * For non-function symbols, the destination in apply_relocate()
317 if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && in apply_relocate()
318 !(sym->st_value & 1)) { in apply_relocate()
319 pr_err("%s: section %u reloc %u sym '%s': unsupported interworking call (Thumb -> ARM)\n", in apply_relocate()
320 module->name, relindex, i, symname); in apply_relocate()
321 return -ENOEXEC; in apply_relocate()
325 lower = __mem_to_opcode_thumb16(*(u16 *)(loc + 2)); in apply_relocate()
328 * 25 bit signed address range (Thumb-2 BL and B.W in apply_relocate()
336 * imm11 = lower[10:0] = offset[11:1] in apply_relocate()
337 * J1 = lower[13] in apply_relocate()
338 * J2 = lower[11] in apply_relocate()
341 j1 = (lower >> 13) & 1; in apply_relocate()
342 j2 = (lower >> 11) & 1; in apply_relocate()
346 ((lower & 0x07ff) << 1); in apply_relocate()
348 offset -= 0x02000000; in apply_relocate()
349 offset += sym->st_value - loc; in apply_relocate()
360 - loc - 4; in apply_relocate()
364 pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", in apply_relocate()
365 module->name, relindex, i, symname, in apply_relocate()
366 ELF32_R_TYPE(rel->r_info), loc, in apply_relocate()
367 sym->st_value); in apply_relocate()
368 return -ENOEXEC; in apply_relocate()
376 lower = (u16)((lower & 0xd000) | in apply_relocate()
381 *(u16 *)(loc + 2) = __opcode_to_mem_thumb16(lower); in apply_relocate()
384 case R_ARM_THM_MOVW_ABS_NC: in apply_relocate()
385 case R_ARM_THM_MOVT_ABS: in apply_relocate()
386 case R_ARM_THM_MOVW_PREL_NC: in apply_relocate()
387 case R_ARM_THM_MOVT_PREL: in apply_relocate()
389 lower = __mem_to_opcode_thumb16(*(u16 *)(loc + 2)); in apply_relocate()
392 * MOVT/MOVW instructions encoding in Thumb-2: in apply_relocate()
396 * imm3 = lower[14:12] in apply_relocate()
397 * imm8 = lower[7:0] in apply_relocate()
403 ((lower & 0x7000) >> 4) | (lower & 0x00ff); in apply_relocate()
404 offset = (offset ^ 0x8000) - 0x8000; in apply_relocate()
405 offset += sym->st_value; in apply_relocate()
407 if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_PREL || in apply_relocate()
408 ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVW_PREL_NC) in apply_relocate()
409 offset -= loc; in apply_relocate()
410 if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS || in apply_relocate()
411 ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_PREL) in apply_relocate()
417 lower = (u16)((lower & 0x8f00) | in apply_relocate()
421 *(u16 *)(loc + 2) = __opcode_to_mem_thumb16(lower); in apply_relocate()
427 module->name, ELF32_R_TYPE(rel->r_info)); in apply_relocate()
428 return -ENOEXEC; in apply_relocate()
443 const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; in find_mod_section()
445 for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) in find_mod_section()
446 if (strcmp(name, secstrs + s->sh_name) == 0) in find_mod_section()
460 const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; in module_finalize()
461 const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum; in module_finalize()
462 struct list_head *unwind_list = &mod->arch.unwind_list; in module_finalize()
465 mod->arch.init_table = NULL; in module_finalize()
468 const char *secname = secstrs + s->sh_name; in module_finalize()
472 if (!(s->sh_flags & SHF_ALLOC) || in module_finalize()
473 s->sh_type != ELF_SECTION_UNWIND) in module_finalize()
484 unwind_table_add(s->sh_addr, in module_finalize()
485 s->sh_size, in module_finalize()
486 txt_sec->sh_addr, in module_finalize()
487 txt_sec->sh_size); in module_finalize()
489 list_add(&table->mod_list, unwind_list); in module_finalize()
493 mod->arch.init_table = table; in module_finalize()
500 fixup_pv_table((void *)s->sh_addr, s->sh_size); in module_finalize()
505 fixup_smp((void *)s->sh_addr, s->sh_size); in module_finalize()
507 return -EINVAL; in module_finalize()
520 &mod->arch.unwind_list, mod_list) { in module_arch_cleanup()
521 list_del(&tmp->mod_list); in module_arch_cleanup()
524 mod->arch.init_table = NULL; in module_arch_cleanup()
531 struct unwind_table *init = mod->arch.init_table; in module_arch_freeing_init()
534 mod->arch.init_table = NULL; in module_arch_freeing_init()
535 list_del(&init->mod_list); in module_arch_freeing_init()