Lines Matching +full:loc +full:- +full:code
1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * The best reference for this stuff is probably the Processor-
5 * Specific ELF Supplement for PA-RISC:
6 * https://parisc.wiki.kernel.org/index.php/File:Elf-pa-hp.pdf
8 * Linux/PA-RISC Project
13 * - PLT stub handling
19 * of the code sections where the stubs are actually called.
26 * - SEGREL32 handling
30 * val -= (uint32_t)me->mem[MOD_INIT_TEXT].base;
32 * val -= (uint32_t)me->mem[MOD_TEXT].base;
56 (( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \
57 ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) ? \
63 me->name, strtab + sym->st_name, (unsigned long)val, bits); \
64 return -ENOEXEC; \
107 #define rrsel(v,a) ((((v)+rnd(a))&0x7ff)+((a)-rnd(a)))
109 #define mask(x,sz) ((x) & ~((1<<(sz))-1))
113 insertion into an opcode. pa-risc uses all sorts of weird bitfields
119 len_ones = (1 << len) - 1; in sign_unext()
127 sign = (x >> (len-1)) & 1; in low_sign_unext()
128 temp = sign_unext(x, len-1); in low_sign_unext()
142 /* Unusual 16-bit encoding, for wide mode only. */ in reassemble_16a()
190 for (; n > 0; n--, rela++) in count_stubs()
192 switch (ELF32_R_TYPE(rela->r_info)) { in count_stubs()
206 for (; n > 0; n--, rela++) in count_gots()
208 switch (ELF64_R_TYPE(rela->r_info)) { in count_gots()
223 for (; n > 0; n--, rela++) in count_fdescs()
225 switch (ELF64_R_TYPE(rela->r_info)) { in count_fdescs()
238 for (; n > 0; n--, rela++) in count_stubs()
240 switch (ELF64_R_TYPE(rela->r_info)) { in count_stubs()
252 kfree(mod->arch.section); in module_arch_freeing_init()
253 mod->arch.section = NULL; in module_arch_freeing_init()
262 return (mod->arch.section[section].stub_entries + 1) in arch_mod_section_prepend()
276 len = hdr->e_shnum * sizeof(me->arch.section[0]); in module_frob_arch_sections()
277 me->arch.section = kzalloc(len, GFP_KERNEL); in module_frob_arch_sections()
278 if (!me->arch.section) in module_frob_arch_sections()
279 return -ENOMEM; in module_frob_arch_sections()
281 for (i = 1; i < hdr->e_shnum; i++) { in module_frob_arch_sections()
288 me->arch.unwind_section = i; in module_frob_arch_sections()
293 /* some of these are not relevant for 32-bit/64-bit in module_frob_arch_sections()
294 * we leave them here to make the code common. the in module_frob_arch_sections()
312 /* each code section should only have one relocation section */ in module_frob_arch_sections()
313 WARN_ON(me->arch.section[s].stub_entries); in module_frob_arch_sections()
316 me->arch.section[s].stub_entries += count; in module_frob_arch_sections()
319 mod_mem = &me->mem[MOD_TEXT]; in module_frob_arch_sections()
321 mod_mem->size = ALIGN(mod_mem->size, 16); in module_frob_arch_sections()
322 me->arch.got_offset = mod_mem->size; in module_frob_arch_sections()
323 mod_mem->size += gots * sizeof(struct got_entry); in module_frob_arch_sections()
325 mod_mem->size = ALIGN(mod_mem->size, 16); in module_frob_arch_sections()
326 me->arch.fdesc_offset = mod_mem->size; in module_frob_arch_sections()
327 mod_mem->size += fdescs * sizeof(Elf_Fdesc); in module_frob_arch_sections()
329 me->arch.got_max = gots; in module_frob_arch_sections()
330 me->arch.fdesc_max = fdescs; in module_frob_arch_sections()
345 got = me->mem[MOD_TEXT].base + me->arch.got_offset; in get_got()
350 BUG_ON(++me->arch.got_count > me->arch.got_max); in get_got()
363 Elf_Fdesc *fdesc = me->mem[MOD_TEXT].base + me->arch.fdesc_offset; in get_fdesc()
366 printk(KERN_ERR "%s: zero OPD requested!\n", me->name); in get_fdesc()
371 while (fdesc->addr) { in get_fdesc()
372 if (fdesc->addr == value) in get_fdesc()
377 BUG_ON(++me->arch.fdesc_count > me->arch.fdesc_max); in get_fdesc()
380 fdesc->addr = value; in get_fdesc()
381 fdesc->gp = (Elf_Addr)me->mem[MOD_TEXT].base + me->arch.got_offset; in get_fdesc()
399 if (!me->arch.section[targetsec].stub_offset) { in get_stub()
400 loc0 -= (me->arch.section[targetsec].stub_entries + 1) * in get_stub()
404 me->arch.section[targetsec].stub_offset = loc0; in get_stub()
408 stub = (void *) me->arch.section[targetsec].stub_offset; in get_stub()
409 me->arch.section[targetsec].stub_offset += sizeof(struct stub_entry); in get_stub()
412 BUG_ON(0 == me->arch.section[targetsec].stub_entries--); in get_stub()
416 /* for 32-bit the stub looks like this: in get_stub()
422 stub->insns[0] = 0x20200000; /* ldil L'XXX,%r1 */ in get_stub()
423 stub->insns[1] = 0xe0202002; /* be,n R'XXX(%sr4,%r1) */ in get_stub()
425 stub->insns[0] |= reassemble_21(lrsel(value, addend)); in get_stub()
426 stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4); in get_stub()
429 /* for 64-bit we have three kinds of stubs: in get_stub()
453 stub->insns[0] = 0x0f6010db; /* ldd 0(%dp),%dp */ in get_stub()
454 stub->insns[0] |= low_sign_unext(d, 5) << 16; in get_stub()
457 stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp */ in get_stub()
458 stub->insns[0] |= reassemble_16a(d); in get_stub()
460 stub->insns[1] = 0x53610020; /* ldd 10(%dp),%r1 */ in get_stub()
461 stub->insns[2] = 0xe820d000; /* bve (%r1) */ in get_stub()
462 stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */ in get_stub()
465 stub->insns[0] = 0x20200000; /* ldil 0,%r1 */ in get_stub()
466 stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */ in get_stub()
467 stub->insns[2] = 0x50210020; /* ldd 10(%r1),%r1 */ in get_stub()
468 stub->insns[3] = 0xe820d002; /* bve,n (%r1) */ in get_stub()
470 stub->insns[0] |= reassemble_21(lrsel(value, addend)); in get_stub()
471 stub->insns[1] |= reassemble_14(rrsel(value, addend)); in get_stub()
474 stub->insns[0] = 0x20200000; /* ldil 0,%r1 */ in get_stub()
475 stub->insns[1] = 0x34210000; /* ldo 0(%r1), %r1 */ in get_stub()
476 stub->insns[2] = 0xe820d002; /* bve,n (%r1) */ in get_stub()
478 stub->insns[0] |= reassemble_21(lrsel(value, addend)); in get_stub()
479 stub->insns[1] |= reassemble_14(rrsel(value, addend)); in get_stub()
498 Elf32_Word *loc; in apply_relocate_add() local
511 loc = (void *)sechdrs[targetsec].sh_addr in apply_relocate_add()
518 if (!sym->st_value) { in apply_relocate_add()
520 me->name, strtab + sym->st_name); in apply_relocate_add()
521 return -ENOENT; in apply_relocate_add()
523 //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03; in apply_relocate_add()
524 dot = (Elf32_Addr)loc & ~0x03; in apply_relocate_add()
526 val = sym->st_value; in apply_relocate_add()
531 pr_debug("Symbol %s loc 0x%x val 0x%x addend 0x%x: %s\n", in apply_relocate_add()
532 strtab + sym->st_name, in apply_relocate_add()
533 (uint32_t)loc, val, addend, in apply_relocate_add()
549 /* 32-bit function address */ in apply_relocate_add()
551 *loc = fsel(val, addend); in apply_relocate_add()
554 /* direct 32-bit ref */ in apply_relocate_add()
555 *loc = fsel(val, addend); in apply_relocate_add()
560 *loc = mask(*loc, 21) | reassemble_21(val); in apply_relocate_add()
565 *loc = mask(*loc, 14) | reassemble_14(val); in apply_relocate_add()
568 /* 32-bit segment relative address */ in apply_relocate_add()
572 *loc = fsel(val, addend); in apply_relocate_add()
575 /* 32-bit section relative address. */ in apply_relocate_add()
576 *loc = fsel(val, addend); in apply_relocate_add()
580 val = lrsel(val - dp, addend); in apply_relocate_add()
581 *loc = mask(*loc, 21) | reassemble_21(val); in apply_relocate_add()
585 val = rrsel(val - dp, addend); in apply_relocate_add()
586 *loc = mask(*loc, 14) | reassemble_14(val); in apply_relocate_add()
589 /* 17-bit PC relative address */ in apply_relocate_add()
592 val = (val - dot - 8)/4; in apply_relocate_add()
596 val = get_stub(me, sym->st_value, addend, in apply_relocate_add()
598 val = (val - dot - 8)/4; in apply_relocate_add()
601 *loc = (*loc & ~0x1f1ffd) | reassemble_17(val); in apply_relocate_add()
604 /* 22-bit PC relative address; only defined for pa20 */ in apply_relocate_add()
607 val = (val - dot - 8)/4; in apply_relocate_add()
611 val = get_stub(me, sym->st_value, addend, in apply_relocate_add()
613 val = (val - dot - 8)/4; in apply_relocate_add()
616 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); in apply_relocate_add()
619 /* 32-bit PC relative address */ in apply_relocate_add()
620 *loc = val - dot - 8 + addend; in apply_relocate_add()
625 me->name, ELF32_R_TYPE(rel[i].r_info)); in apply_relocate_add()
626 return -ENOEXEC; in apply_relocate_add()
643 Elf64_Word *loc; in apply_relocate_add() local
655 loc = (void *)sechdrs[targetsec].sh_addr in apply_relocate_add()
662 if (!sym->st_value) { in apply_relocate_add()
664 me->name, strtab + sym->st_name); in apply_relocate_add()
665 return -ENOENT; in apply_relocate_add()
667 //dot = (sechdrs[relsec].sh_addr + rel->r_offset) & ~0x03; in apply_relocate_add()
668 dot = (Elf64_Addr)loc & ~0x03; in apply_relocate_add()
669 loc64 = (Elf64_Xword *)loc; in apply_relocate_add()
671 val = sym->st_value; in apply_relocate_add()
676 printk("Symbol %s loc %p val 0x%Lx addend 0x%Lx: %s\n", in apply_relocate_add()
677 strtab + sym->st_name, in apply_relocate_add()
678 loc, val, addend, in apply_relocate_add()
691 /* LT-relative; left 21 bits */ in apply_relocate_add()
693 pr_debug("LTOFF21L Symbol %s loc %p val %llx\n", in apply_relocate_add()
694 strtab + sym->st_name, in apply_relocate_add()
695 loc, val); in apply_relocate_add()
697 *loc = mask(*loc, 21) | reassemble_21(val); in apply_relocate_add()
701 /* LT-relative; right 14 bits */ in apply_relocate_add()
704 pr_debug("LTOFF14R Symbol %s loc %p val %llx\n", in apply_relocate_add()
705 strtab + sym->st_name, in apply_relocate_add()
706 loc, val); in apply_relocate_add()
707 *loc = mask(*loc, 14) | reassemble_14(val); in apply_relocate_add()
710 /* PC-relative; 22 bits */ in apply_relocate_add()
711 pr_debug("PCREL22F Symbol %s loc %p val %llx\n", in apply_relocate_add()
712 strtab + sym->st_name, in apply_relocate_add()
713 loc, val); in apply_relocate_add()
721 val = (val - dot - 8)/4; in apply_relocate_add()
725 val = get_stub(me, sym->st_value, in apply_relocate_add()
730 val = sym->st_value; in apply_relocate_add()
734 val = sym->st_value; in apply_relocate_add()
735 if (strncmp(strtab + sym->st_name, "$$", 2) in apply_relocate_add()
743 pr_debug("STUB FOR %s loc %px, val %llx+%llx at %llx\n", in apply_relocate_add()
744 strtab + sym->st_name, loc, sym->st_value, in apply_relocate_add()
746 val = (val - dot - 8)/4; in apply_relocate_add()
748 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); in apply_relocate_add()
751 /* 32-bit PC relative address */ in apply_relocate_add()
752 *loc = val - dot - 8 + addend; in apply_relocate_add()
755 /* 64-bit PC relative address */ in apply_relocate_add()
756 *loc64 = val - dot - 8 + addend; in apply_relocate_add()
759 /* 64-bit effective address */ in apply_relocate_add()
763 /* 32-bit segment relative address */ in apply_relocate_add()
767 *loc = fsel(val, addend); in apply_relocate_add()
770 /* 32-bit section relative address. */ in apply_relocate_add()
771 *loc = fsel(val, addend); in apply_relocate_add()
774 /* 64-bit function address */ in apply_relocate_add()
778 strtab + sym->st_name, *loc64, in apply_relocate_add()
779 ((Elf_Fdesc *)*loc64)->addr); in apply_relocate_add()
784 pr_debug("Non local FPTR64 Symbol %s loc %p val %llx\n", in apply_relocate_add()
785 strtab + sym->st_name, in apply_relocate_add()
786 loc, val); in apply_relocate_add()
793 me->name, ELF64_R_TYPE(rel[i].r_info)); in apply_relocate_add()
794 return -ENOEXEC; in apply_relocate_add()
808 if (!me->arch.unwind_section) in register_unwind_table()
811 table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr; in register_unwind_table()
812 end = table + sechdrs[me->arch.unwind_section].sh_size; in register_unwind_table()
813 gp = (Elf_Addr)me->mem[MOD_TEXT].base + me->arch.got_offset; in register_unwind_table()
815 pr_debug("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n", in register_unwind_table()
816 me->arch.unwind_section, table, end, gp); in register_unwind_table()
817 me->arch.unwind = unwind_table_add(me->name, 0, gp, table, end); in register_unwind_table()
823 if (me->arch.unwind) in deregister_unwind_table()
824 unwind_table_remove(me->arch.unwind); in deregister_unwind_table()
836 int symindex __maybe_unused = -1; in module_finalize()
843 entry = (Elf_Fdesc *)me->init; in module_finalize()
844 printk("FINALIZE, ->init FPTR is %p, GP %lx ADDR %lx\n", entry, in module_finalize()
845 entry->gp, entry->addr); in module_finalize()
846 addr = (u32 *)entry->addr; in module_finalize()
851 me->arch.got_count, me->arch.got_max, in module_finalize()
852 me->arch.fdesc_count, me->arch.fdesc_max); in module_finalize()
857 /* haven't filled in me->symtab yet, so have to find it in module_finalize()
859 for (i = 1; i < hdr->e_shnum; i++) { in module_finalize()
874 me->name, strtab, symhdr); in module_finalize()
876 if(me->arch.got_count > MAX_GOTS) { in module_finalize()
878 me->name, me->arch.got_count, MAX_GOTS); in module_finalize()
879 return -EINVAL; in module_finalize()
882 kfree(me->arch.section); in module_finalize()
883 me->arch.section = NULL; in module_finalize()
889 oldptr = (void *)symhdr->sh_addr; in module_finalize()
891 nsyms = symhdr->sh_size / sizeof(Elf_Sym); in module_finalize()
896 if(strncmp(strtab + oldptr->st_name, in module_finalize()
906 nsyms = newptr - (Elf_Sym *)symhdr->sh_addr; in module_finalize()
908 symhdr->sh_size = nsyms * sizeof(Elf_Sym); in module_finalize()
911 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; in module_finalize()
912 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { in module_finalize()
913 void *aseg = (void *) s->sh_addr; in module_finalize()
914 char *secname = secstrings + s->sh_name; in module_finalize()
918 apply_alternatives(aseg, aseg + s->sh_size, me->name); in module_finalize()
922 * -ffunction-sections so we must relocate the addresses in the in module_finalize()
925 if (symindex != -1 && !strcmp(secname, FTRACE_CALLSITE_SECTION)) { in module_finalize()
927 if (s->sh_type == SHT_REL) in module_finalize()
930 s - sechdrs, me); in module_finalize()
931 else if (s->sh_type == SHT_RELA) in module_finalize()
934 s - sechdrs, me); in module_finalize()
951 unsigned long start_opd = (Elf64_Addr)mod->mem[MOD_TEXT].base + in dereference_module_function_descriptor()
952 mod->arch.fdesc_offset; in dereference_module_function_descriptor()
954 mod->arch.fdesc_count * sizeof(Elf64_Fdesc); in dereference_module_function_descriptor()