1033f58dfSPeter Wemm /*- 2c49761ddSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3c49761ddSPedro F. Giffuni * 4033f58dfSPeter Wemm * Copyright 1996-1998 John D. Polstra. 5033f58dfSPeter Wemm * All rights reserved. 6033f58dfSPeter Wemm * 7033f58dfSPeter Wemm * Redistribution and use in source and binary forms, with or without 8033f58dfSPeter Wemm * modification, are permitted provided that the following conditions 9033f58dfSPeter Wemm * are met: 10033f58dfSPeter Wemm * 1. Redistributions of source code must retain the above copyright 11033f58dfSPeter Wemm * notice, this list of conditions and the following disclaimer. 12033f58dfSPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 13033f58dfSPeter Wemm * notice, this list of conditions and the following disclaimer in the 14033f58dfSPeter Wemm * documentation and/or other materials provided with the distribution. 15033f58dfSPeter Wemm * 16033f58dfSPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17033f58dfSPeter Wemm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18033f58dfSPeter Wemm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19033f58dfSPeter Wemm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20033f58dfSPeter Wemm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21033f58dfSPeter Wemm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22033f58dfSPeter Wemm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23033f58dfSPeter Wemm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24033f58dfSPeter Wemm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25033f58dfSPeter Wemm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26033f58dfSPeter Wemm */ 27033f58dfSPeter Wemm 2856ae44c5SDavid E. O'Brien #include <sys/cdefs.h> 2956ae44c5SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3056ae44c5SDavid E. O'Brien 31033f58dfSPeter Wemm #include <sys/param.h> 323ebc1248SPeter Wemm #include <sys/kernel.h> 33033f58dfSPeter Wemm #include <sys/systm.h> 34f36ba452SJake Burkholder #include <sys/exec.h> 35f36ba452SJake Burkholder #include <sys/imgact.h> 36033f58dfSPeter Wemm #include <sys/linker.h> 37afe1a688SKonstantin Belousov #include <sys/proc.h> 383ebc1248SPeter Wemm #include <sys/sysent.h> 393ebc1248SPeter Wemm #include <sys/imgact_elf.h> 403ebc1248SPeter Wemm #include <sys/syscall.h> 413ebc1248SPeter Wemm #include <sys/signalvar.h> 423ebc1248SPeter Wemm #include <sys/vnode.h> 43f36ba452SJake Burkholder 44f36ba452SJake Burkholder #include <vm/vm.h> 45f36ba452SJake Burkholder #include <vm/pmap.h> 46f36ba452SJake Burkholder #include <vm/vm_param.h> 47f36ba452SJake Burkholder 48033f58dfSPeter Wemm #include <machine/elf.h> 49180e57e5SJohn Baldwin #include <machine/fpu.h> 503ebc1248SPeter Wemm #include <machine/md_var.h> 513ebc1248SPeter Wemm 529ce875d9SKonstantin Belousov struct sysentvec elf64_freebsd_sysvec_la48 = { 53a8d403e1SKonstantin Belousov .sv_size = SYS_MAXSYSCALL, 54a8d403e1SKonstantin Belousov .sv_table = sysent, 55a8d403e1SKonstantin Belousov .sv_transtrap = NULL, 56a8d403e1SKonstantin Belousov .sv_fixup = __elfN(freebsd_fixup), 57a8d403e1SKonstantin Belousov .sv_sendsig = sendsig, 58a8d403e1SKonstantin Belousov .sv_sigcode = sigcode, 59a8d403e1SKonstantin Belousov .sv_szsigcode = &szsigcode, 60a8d403e1SKonstantin Belousov .sv_name = "FreeBSD ELF64", 61a8d403e1SKonstantin Belousov .sv_coredump = __elfN(coredump), 62435754a5SEdward Tomasz Napierala .sv_elf_core_osabi = ELFOSABI_FREEBSD, 63435754a5SEdward Tomasz Napierala .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, 64435754a5SEdward Tomasz Napierala .sv_elf_core_prepare_notes = __elfN(prepare_notes), 65a8d403e1SKonstantin Belousov .sv_imgact_try = NULL, 66a8d403e1SKonstantin Belousov .sv_minsigstksz = MINSIGSTKSZ, 67a8d403e1SKonstantin Belousov .sv_minuser = VM_MIN_ADDRESS, 689ce875d9SKonstantin Belousov .sv_maxuser = VM_MAXUSER_ADDRESS_LA48, 699ce875d9SKonstantin Belousov .sv_usrstack = USRSTACK_LA48, 709ce875d9SKonstantin Belousov .sv_psstrings = PS_STRINGS_LA48, 71a8d403e1SKonstantin Belousov .sv_stackprot = VM_PROT_ALL, 72e3532331SJohn Baldwin .sv_copyout_auxargs = __elfN(freebsd_copyout_auxargs), 73a8d403e1SKonstantin Belousov .sv_copyout_strings = exec_copyout_strings, 74a8d403e1SKonstantin Belousov .sv_setregs = exec_setregs, 75a8d403e1SKonstantin Belousov .sv_fixlimit = NULL, 76b4cf0e62SKonstantin Belousov .sv_maxssiz = NULL, 77fa50a355SKonstantin Belousov .sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_LP64 | SV_SHP | 78f8e8a06dSConrad Meyer SV_TIMEKEEP | SV_RNG_SEED_VER, 79afe1a688SKonstantin Belousov .sv_set_syscall_retval = cpu_set_syscall_retval, 80afe1a688SKonstantin Belousov .sv_fetch_syscall_args = cpu_fetch_syscall_args, 81afe1a688SKonstantin Belousov .sv_syscallnames = syscallnames, 829ce875d9SKonstantin Belousov .sv_shared_page_base = SHAREDPAGE_LA48, 836297a3d8SKonstantin Belousov .sv_shared_page_len = PAGE_SIZE, 84e5d81ef1SDmitry Chagin .sv_schedtail = NULL, 8591d1786fSDmitry Chagin .sv_thread_detach = NULL, 86038c7205SDmitry Chagin .sv_trap = NULL, 87fc83c5a7SKonstantin Belousov .sv_stackgap = elf64_stackgap, 8828a66fc3SKonstantin Belousov .sv_onexec_old = exec_onexec_old, 8928a66fc3SKonstantin Belousov .sv_onexit = exit_onexit, 903ebc1248SPeter Wemm }; 919ce875d9SKonstantin Belousov 929ce875d9SKonstantin Belousov struct sysentvec elf64_freebsd_sysvec_la57 = { 939ce875d9SKonstantin Belousov .sv_size = SYS_MAXSYSCALL, 949ce875d9SKonstantin Belousov .sv_table = sysent, 959ce875d9SKonstantin Belousov .sv_transtrap = NULL, 969ce875d9SKonstantin Belousov .sv_fixup = __elfN(freebsd_fixup), 979ce875d9SKonstantin Belousov .sv_sendsig = sendsig, 989ce875d9SKonstantin Belousov .sv_sigcode = sigcode, 999ce875d9SKonstantin Belousov .sv_szsigcode = &szsigcode, 1009ce875d9SKonstantin Belousov .sv_name = "FreeBSD ELF64", 1019ce875d9SKonstantin Belousov .sv_coredump = __elfN(coredump), 102435754a5SEdward Tomasz Napierala .sv_elf_core_osabi = ELFOSABI_FREEBSD, 103435754a5SEdward Tomasz Napierala .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR, 104435754a5SEdward Tomasz Napierala .sv_elf_core_prepare_notes = __elfN(prepare_notes), 1059ce875d9SKonstantin Belousov .sv_imgact_try = NULL, 1069ce875d9SKonstantin Belousov .sv_minsigstksz = MINSIGSTKSZ, 1079ce875d9SKonstantin Belousov .sv_minuser = VM_MIN_ADDRESS, 1089ce875d9SKonstantin Belousov .sv_maxuser = VM_MAXUSER_ADDRESS_LA57, 1099ce875d9SKonstantin Belousov .sv_usrstack = USRSTACK_LA57, 1109ce875d9SKonstantin Belousov .sv_psstrings = PS_STRINGS_LA57, 1119ce875d9SKonstantin Belousov .sv_stackprot = VM_PROT_ALL, 1129ce875d9SKonstantin Belousov .sv_copyout_auxargs = __elfN(freebsd_copyout_auxargs), 1139ce875d9SKonstantin Belousov .sv_copyout_strings = exec_copyout_strings, 1149ce875d9SKonstantin Belousov .sv_setregs = exec_setregs, 1159ce875d9SKonstantin Belousov .sv_fixlimit = NULL, 1169ce875d9SKonstantin Belousov .sv_maxssiz = NULL, 1179ce875d9SKonstantin Belousov .sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_LP64 | SV_SHP | 118f8e8a06dSConrad Meyer SV_TIMEKEEP | SV_RNG_SEED_VER, 1199ce875d9SKonstantin Belousov .sv_set_syscall_retval = cpu_set_syscall_retval, 1209ce875d9SKonstantin Belousov .sv_fetch_syscall_args = cpu_fetch_syscall_args, 1219ce875d9SKonstantin Belousov .sv_syscallnames = syscallnames, 1229ce875d9SKonstantin Belousov .sv_shared_page_base = SHAREDPAGE_LA57, 1239ce875d9SKonstantin Belousov .sv_shared_page_len = PAGE_SIZE, 1249ce875d9SKonstantin Belousov .sv_schedtail = NULL, 1259ce875d9SKonstantin Belousov .sv_thread_detach = NULL, 1269ce875d9SKonstantin Belousov .sv_trap = NULL, 1279ce875d9SKonstantin Belousov .sv_stackgap = elf64_stackgap, 12828a66fc3SKonstantin Belousov .sv_onexec_old = exec_onexec_old, 12928a66fc3SKonstantin Belousov .sv_onexit = exit_onexit, 1309ce875d9SKonstantin Belousov }; 1319ce875d9SKonstantin Belousov 1329ce875d9SKonstantin Belousov static void 1339ce875d9SKonstantin Belousov amd64_init_sysvecs(void *arg) 1349ce875d9SKonstantin Belousov { 1359ce875d9SKonstantin Belousov amd64_lower_shared_page(&elf64_freebsd_sysvec_la48); 1369ce875d9SKonstantin Belousov if (la57) { 1379ce875d9SKonstantin Belousov exec_sysvec_init(&elf64_freebsd_sysvec_la57); 1389ce875d9SKonstantin Belousov exec_sysvec_init_secondary(&elf64_freebsd_sysvec_la57, 1399ce875d9SKonstantin Belousov &elf64_freebsd_sysvec_la48); 1409ce875d9SKonstantin Belousov } else { 1419ce875d9SKonstantin Belousov exec_sysvec_init(&elf64_freebsd_sysvec_la48); 1429ce875d9SKonstantin Belousov } 1439ce875d9SKonstantin Belousov } 1449ce875d9SKonstantin Belousov SYSINIT(elf64_sysvec, SI_SUB_EXEC, SI_ORDER_ANY, amd64_init_sysvecs, NULL); 1453ebc1248SPeter Wemm 146cd155b56SDon Lewis void 147cd155b56SDon Lewis amd64_lower_shared_page(struct sysentvec *sv) 148cd155b56SDon Lewis { 149cd155b56SDon Lewis if (hw_lower_amd64_sharedpage != 0) { 150cd155b56SDon Lewis sv->sv_maxuser -= PAGE_SIZE; 151cd155b56SDon Lewis sv->sv_shared_page_base -= PAGE_SIZE; 152cd155b56SDon Lewis sv->sv_usrstack -= PAGE_SIZE; 153cd155b56SDon Lewis sv->sv_psstrings -= PAGE_SIZE; 154cd155b56SDon Lewis } 155cd155b56SDon Lewis } 156cd155b56SDon Lewis 1579ce875d9SKonstantin Belousov static boolean_t 1589ce875d9SKonstantin Belousov freebsd_brand_info_la57_img_compat(struct image_params *imgp, 1599ce875d9SKonstantin Belousov int32_t *osrel __unused, uint32_t *fctl0) 1609ce875d9SKonstantin Belousov { 1619ce875d9SKonstantin Belousov if ((imgp->proc->p_md.md_flags & P_MD_LA57) != 0) 1629ce875d9SKonstantin Belousov return (TRUE); 1639ce875d9SKonstantin Belousov if (fctl0 == NULL || (*fctl0 & NT_FREEBSD_FCTL_LA48) != 0) 1649ce875d9SKonstantin Belousov return (FALSE); 1659ce875d9SKonstantin Belousov if ((imgp->proc->p_md.md_flags & P_MD_LA48) != 0) 1669ce875d9SKonstantin Belousov return (FALSE); 1679ce875d9SKonstantin Belousov return (TRUE); 1689ce875d9SKonstantin Belousov } 169cd155b56SDon Lewis 1709ce875d9SKonstantin Belousov static Elf64_Brandinfo freebsd_brand_info_la48 = { 171a8d403e1SKonstantin Belousov .brand = ELFOSABI_FREEBSD, 172a8d403e1SKonstantin Belousov .machine = EM_X86_64, 173a8d403e1SKonstantin Belousov .compat_3_brand = "FreeBSD", 174a8d403e1SKonstantin Belousov .emul_path = NULL, 175a8d403e1SKonstantin Belousov .interp_path = "/libexec/ld-elf.so.1", 1769ce875d9SKonstantin Belousov .sysvec = &elf64_freebsd_sysvec_la48, 177a8d403e1SKonstantin Belousov .interp_newpath = NULL, 17832c01de2SDmitry Chagin .brand_note = &elf64_freebsd_brandnote, 1799ce875d9SKonstantin Belousov .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE, 1803ebc1248SPeter Wemm }; 1813ebc1248SPeter Wemm 1829ce875d9SKonstantin Belousov static Elf64_Brandinfo freebsd_brand_info_la57 = { 1839ce875d9SKonstantin Belousov .brand = ELFOSABI_FREEBSD, 1849ce875d9SKonstantin Belousov .machine = EM_X86_64, 1859ce875d9SKonstantin Belousov .compat_3_brand = "FreeBSD", 1869ce875d9SKonstantin Belousov .emul_path = NULL, 1879ce875d9SKonstantin Belousov .interp_path = "/libexec/ld-elf.so.1", 1889ce875d9SKonstantin Belousov .sysvec = &elf64_freebsd_sysvec_la57, 1899ce875d9SKonstantin Belousov .interp_newpath = NULL, 1909ce875d9SKonstantin Belousov .brand_note = &elf64_freebsd_brandnote, 1919ce875d9SKonstantin Belousov .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE, 1929ce875d9SKonstantin Belousov .header_supported = freebsd_brand_info_la57_img_compat, 1939ce875d9SKonstantin Belousov }; 1949ce875d9SKonstantin Belousov 1959ce875d9SKonstantin Belousov static void 1969ce875d9SKonstantin Belousov sysinit_register_elf64_brand_entries(void *arg __unused) 1979ce875d9SKonstantin Belousov { 1989ce875d9SKonstantin Belousov /* 1999ce875d9SKonstantin Belousov * _57 must go first so it can either claim the image or hand 2009ce875d9SKonstantin Belousov * it to _48. 2019ce875d9SKonstantin Belousov */ 2029ce875d9SKonstantin Belousov if (la57) 2039ce875d9SKonstantin Belousov elf64_insert_brand_entry(&freebsd_brand_info_la57); 2049ce875d9SKonstantin Belousov elf64_insert_brand_entry(&freebsd_brand_info_la48); 2059ce875d9SKonstantin Belousov } 20652bf2041SBjoern A. Zeeb SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_FIRST, 2079ce875d9SKonstantin Belousov sysinit_register_elf64_brand_entries, NULL); 208033f58dfSPeter Wemm 2099b68618dSPeter Wemm static Elf64_Brandinfo freebsd_brand_oinfo = { 210a8d403e1SKonstantin Belousov .brand = ELFOSABI_FREEBSD, 211a8d403e1SKonstantin Belousov .machine = EM_X86_64, 212a8d403e1SKonstantin Belousov .compat_3_brand = "FreeBSD", 213a8d403e1SKonstantin Belousov .emul_path = NULL, 214a8d403e1SKonstantin Belousov .interp_path = "/usr/libexec/ld-elf.so.1", 2159ce875d9SKonstantin Belousov .sysvec = &elf64_freebsd_sysvec_la48, 216a8d403e1SKonstantin Belousov .interp_newpath = NULL, 21732c01de2SDmitry Chagin .brand_note = &elf64_freebsd_brandnote, 218cd899aadSDmitry Chagin .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 2199b68618dSPeter Wemm }; 2209b68618dSPeter Wemm 2219b68618dSPeter Wemm SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY, 2229ce875d9SKonstantin Belousov (sysinit_cfunc_t)elf64_insert_brand_entry, &freebsd_brand_oinfo); 2239b68618dSPeter Wemm 22489ffc202SBjoern A. Zeeb static Elf64_Brandinfo kfreebsd_brand_info = { 22589ffc202SBjoern A. Zeeb .brand = ELFOSABI_FREEBSD, 22689ffc202SBjoern A. Zeeb .machine = EM_X86_64, 22789ffc202SBjoern A. Zeeb .compat_3_brand = "FreeBSD", 22889ffc202SBjoern A. Zeeb .emul_path = NULL, 22989ffc202SBjoern A. Zeeb .interp_path = "/lib/ld-kfreebsd-x86-64.so.1", 2309ce875d9SKonstantin Belousov .sysvec = &elf64_freebsd_sysvec_la48, 23189ffc202SBjoern A. Zeeb .interp_newpath = NULL, 23289ffc202SBjoern A. Zeeb .brand_note = &elf64_kfreebsd_brandnote, 233ecc2fda8SBjoern A. Zeeb .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY 23489ffc202SBjoern A. Zeeb }; 23589ffc202SBjoern A. Zeeb 23689ffc202SBjoern A. Zeeb SYSINIT(kelf64, SI_SUB_EXEC, SI_ORDER_ANY, 2379ce875d9SKonstantin Belousov (sysinit_cfunc_t)elf64_insert_brand_entry, &kfreebsd_brand_info); 23889ffc202SBjoern A. Zeeb 2394da47b2fSMarcel Moolenaar void 240180e57e5SJohn Baldwin elf64_dump_thread(struct thread *td, void *dst, size_t *off) 2414da47b2fSMarcel Moolenaar { 242180e57e5SJohn Baldwin void *buf; 243180e57e5SJohn Baldwin size_t len; 2444da47b2fSMarcel Moolenaar 245180e57e5SJohn Baldwin len = 0; 246180e57e5SJohn Baldwin if (use_xsave) { 247180e57e5SJohn Baldwin if (dst != NULL) { 248180e57e5SJohn Baldwin fpugetregs(td); 249180e57e5SJohn Baldwin len += elf64_populate_note(NT_X86_XSTATE, 250180e57e5SJohn Baldwin get_pcb_user_save_td(td), dst, 251180e57e5SJohn Baldwin cpu_max_ext_state_size, &buf); 252180e57e5SJohn Baldwin *(uint64_t *)((char *)buf + X86_XSTATE_XCR0_OFFSET) = 253180e57e5SJohn Baldwin xsave_mask; 254180e57e5SJohn Baldwin } else 255180e57e5SJohn Baldwin len += elf64_populate_note(NT_X86_XSTATE, NULL, NULL, 256180e57e5SJohn Baldwin cpu_max_ext_state_size, NULL); 257180e57e5SJohn Baldwin } 258180e57e5SJohn Baldwin *off = len; 259180e57e5SJohn Baldwin } 2604da47b2fSMarcel Moolenaar 26136716fe2SMark Johnston bool 26236716fe2SMark Johnston elf_is_ifunc_reloc(Elf_Size r_info) 26336716fe2SMark Johnston { 26436716fe2SMark Johnston 26536716fe2SMark Johnston return (ELF_R_TYPE(r_info) == R_X86_64_IRELATIVE); 26636716fe2SMark Johnston } 2677035cf14SKonstantin Belousov 268bde362f5SPeter Wemm /* Process one elf relocation with addend. */ 2697251b4bfSJake Burkholder static int 270e8855d4fSPeter Wemm elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, 271fcf7a481SAndrew Turner int type, bool late_ifunc, elf_lookup_fn lookup) 272033f58dfSPeter Wemm { 273e8855d4fSPeter Wemm Elf64_Addr *where, val; 274e8855d4fSPeter Wemm Elf32_Addr *where32, val32; 275f1d19042SArchie Cobbs Elf_Addr addr; 276aa855a59SPeter Wemm Elf_Addr addend; 277757686b1SMarcel Moolenaar Elf_Size rtype, symidx; 278aa855a59SPeter Wemm const Elf_Rel *rel; 279aa855a59SPeter Wemm const Elf_Rela *rela; 280cff8c6f2SKonstantin Belousov int error; 281033f58dfSPeter Wemm 282aa855a59SPeter Wemm switch (type) { 283aa855a59SPeter Wemm case ELF_RELOC_REL: 2840a5e03ddSMatthew Dillon rel = (const Elf_Rel *)data; 285aa855a59SPeter Wemm where = (Elf_Addr *) (relocbase + rel->r_offset); 286aa855a59SPeter Wemm rtype = ELF_R_TYPE(rel->r_info); 287d297ad16SMarcel Moolenaar symidx = ELF_R_SYM(rel->r_info); 288910bb7dbSPeter Wemm /* Addend is 32 bit on 32 bit relocs */ 289910bb7dbSPeter Wemm switch (rtype) { 290910bb7dbSPeter Wemm case R_X86_64_PC32: 291910bb7dbSPeter Wemm case R_X86_64_32S: 292f9875149SGleb Smirnoff case R_X86_64_PLT32: 293910bb7dbSPeter Wemm addend = *(Elf32_Addr *)where; 294910bb7dbSPeter Wemm break; 295910bb7dbSPeter Wemm default: 296910bb7dbSPeter Wemm addend = *where; 297910bb7dbSPeter Wemm break; 298910bb7dbSPeter Wemm } 299aa855a59SPeter Wemm break; 300aa855a59SPeter Wemm case ELF_RELOC_RELA: 3010a5e03ddSMatthew Dillon rela = (const Elf_Rela *)data; 302aa855a59SPeter Wemm where = (Elf_Addr *) (relocbase + rela->r_offset); 303aa855a59SPeter Wemm addend = rela->r_addend; 304aa855a59SPeter Wemm rtype = ELF_R_TYPE(rela->r_info); 305d297ad16SMarcel Moolenaar symidx = ELF_R_SYM(rela->r_info); 306aa855a59SPeter Wemm break; 307aa855a59SPeter Wemm default: 308aa855a59SPeter Wemm panic("unknown reloc type %d\n", type); 309aa855a59SPeter Wemm } 310033f58dfSPeter Wemm 311fcf7a481SAndrew Turner if (late_ifunc) { 312fcf7a481SAndrew Turner KASSERT(type == ELF_RELOC_RELA, 313fcf7a481SAndrew Turner ("Only RELA ifunc relocations are supported")); 314fcf7a481SAndrew Turner if (rtype != R_X86_64_IRELATIVE) 315fcf7a481SAndrew Turner return (0); 316fcf7a481SAndrew Turner } 317fcf7a481SAndrew Turner 318aa855a59SPeter Wemm switch (rtype) { 319afa88623SPeter Wemm case R_X86_64_NONE: /* none */ 320033f58dfSPeter Wemm break; 321033f58dfSPeter Wemm 322afa88623SPeter Wemm case R_X86_64_64: /* S + A */ 323cff8c6f2SKonstantin Belousov error = lookup(lf, symidx, 1, &addr); 324e8855d4fSPeter Wemm val = addr + addend; 325cff8c6f2SKonstantin Belousov if (error != 0) 3268481aab1SMitchell Horne return (-1); 327e8855d4fSPeter Wemm if (*where != val) 328e8855d4fSPeter Wemm *where = val; 329033f58dfSPeter Wemm break; 330033f58dfSPeter Wemm 331afa88623SPeter Wemm case R_X86_64_PC32: /* S + A - P */ 332f9875149SGleb Smirnoff case R_X86_64_PLT32: /* L + A - P, L is PLT location for 333f9875149SGleb Smirnoff the symbol, which we treat as S */ 334cff8c6f2SKonstantin Belousov error = lookup(lf, symidx, 1, &addr); 335e8855d4fSPeter Wemm where32 = (Elf32_Addr *)where; 336e8855d4fSPeter Wemm val32 = (Elf32_Addr)(addr + addend - (Elf_Addr)where); 337cff8c6f2SKonstantin Belousov if (error != 0) 3388481aab1SMitchell Horne return (-1); 339e8855d4fSPeter Wemm if (*where32 != val32) 340e8855d4fSPeter Wemm *where32 = val32; 341e8855d4fSPeter Wemm break; 342e8855d4fSPeter Wemm 343e8855d4fSPeter Wemm case R_X86_64_32S: /* S + A sign extend */ 344cff8c6f2SKonstantin Belousov error = lookup(lf, symidx, 1, &addr); 345e8855d4fSPeter Wemm val32 = (Elf32_Addr)(addr + addend); 346e8855d4fSPeter Wemm where32 = (Elf32_Addr *)where; 347cff8c6f2SKonstantin Belousov if (error != 0) 3488481aab1SMitchell Horne return (-1); 349e8855d4fSPeter Wemm if (*where32 != val32) 350e8855d4fSPeter Wemm *where32 = val32; 351033f58dfSPeter Wemm break; 352033f58dfSPeter Wemm 353afa88623SPeter Wemm case R_X86_64_COPY: /* none */ 354033f58dfSPeter Wemm /* 355033f58dfSPeter Wemm * There shouldn't be copy relocations in kernel 356033f58dfSPeter Wemm * objects. 357033f58dfSPeter Wemm */ 3588481aab1SMitchell Horne printf("kldload: unexpected R_COPY relocation, " 3598481aab1SMitchell Horne "symbol index %ld\n", symidx); 3609ea63320SKonstantin Belousov return (-1); 361033f58dfSPeter Wemm 362afa88623SPeter Wemm case R_X86_64_GLOB_DAT: /* S */ 363901b68c1SPeter Wemm case R_X86_64_JMP_SLOT: /* XXX need addend + offset */ 364cff8c6f2SKonstantin Belousov error = lookup(lf, symidx, 1, &addr); 365cff8c6f2SKonstantin Belousov if (error != 0) 3668481aab1SMitchell Horne return (-1); 367033f58dfSPeter Wemm if (*where != addr) 368033f58dfSPeter Wemm *where = addr; 369033f58dfSPeter Wemm break; 370033f58dfSPeter Wemm 371afa88623SPeter Wemm case R_X86_64_RELATIVE: /* B + A */ 37238dae42cSMark Johnston addr = elf_relocaddr(lf, relocbase + addend); 373e8855d4fSPeter Wemm val = addr; 374e8855d4fSPeter Wemm if (*where != val) 375e8855d4fSPeter Wemm *where = val; 376033f58dfSPeter Wemm break; 377033f58dfSPeter Wemm 3787035cf14SKonstantin Belousov case R_X86_64_IRELATIVE: 3797035cf14SKonstantin Belousov addr = relocbase + addend; 3807035cf14SKonstantin Belousov val = ((Elf64_Addr (*)(void))addr)(); 3817035cf14SKonstantin Belousov if (*where != val) 3827035cf14SKonstantin Belousov *where = val; 3837035cf14SKonstantin Belousov break; 3847035cf14SKonstantin Belousov 385033f58dfSPeter Wemm default: 3868481aab1SMitchell Horne printf("kldload: unexpected relocation type %ld, " 3878481aab1SMitchell Horne "symbol index %ld\n", rtype, symidx); 3889ea63320SKonstantin Belousov return (-1); 389033f58dfSPeter Wemm } 390033f58dfSPeter Wemm return (0); 391033f58dfSPeter Wemm } 3921aeb23cdSMarcel Moolenaar 3931aeb23cdSMarcel Moolenaar int 394e8855d4fSPeter Wemm elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, 395e8855d4fSPeter Wemm elf_lookup_fn lookup) 3967251b4bfSJake Burkholder { 3977251b4bfSJake Burkholder 398fcf7a481SAndrew Turner return (elf_reloc_internal(lf, relocbase, data, type, false, lookup)); 3997251b4bfSJake Burkholder } 4007251b4bfSJake Burkholder 4017251b4bfSJake Burkholder int 402e8855d4fSPeter Wemm elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, 403e8855d4fSPeter Wemm int type, elf_lookup_fn lookup) 4047251b4bfSJake Burkholder { 4057251b4bfSJake Burkholder 406fcf7a481SAndrew Turner return (elf_reloc_internal(lf, relocbase, data, type, false, lookup)); 407fcf7a481SAndrew Turner } 408fcf7a481SAndrew Turner 409fcf7a481SAndrew Turner int 410fcf7a481SAndrew Turner elf_reloc_late(linker_file_t lf, Elf_Addr relocbase, const void *data, 411fcf7a481SAndrew Turner int type, elf_lookup_fn lookup) 412fcf7a481SAndrew Turner { 413fcf7a481SAndrew Turner 414fcf7a481SAndrew Turner return (elf_reloc_internal(lf, relocbase, data, type, true, lookup)); 4157251b4bfSJake Burkholder } 4167251b4bfSJake Burkholder 4177251b4bfSJake Burkholder int 4181aeb23cdSMarcel Moolenaar elf_cpu_load_file(linker_file_t lf __unused) 4191aeb23cdSMarcel Moolenaar { 4201aeb23cdSMarcel Moolenaar 4211aeb23cdSMarcel Moolenaar return (0); 4221aeb23cdSMarcel Moolenaar } 4231aeb23cdSMarcel Moolenaar 4241aeb23cdSMarcel Moolenaar int 4251aeb23cdSMarcel Moolenaar elf_cpu_unload_file(linker_file_t lf __unused) 4261aeb23cdSMarcel Moolenaar { 4271aeb23cdSMarcel Moolenaar 4281aeb23cdSMarcel Moolenaar return (0); 4291aeb23cdSMarcel Moolenaar } 43038f69a61SBrandon Bergren 43138f69a61SBrandon Bergren int 43230693808SBrandon Bergren elf_cpu_parse_dynamic(caddr_t loadbase __unused, Elf_Dyn *dynamic __unused) 43338f69a61SBrandon Bergren { 43438f69a61SBrandon Bergren 43538f69a61SBrandon Bergren return (0); 43638f69a61SBrandon Bergren } 437