140129Speter/*- 240129Speter * Copyright 1996-1998 John D. Polstra. 340129Speter * All rights reserved. 440129Speter * 540129Speter * Redistribution and use in source and binary forms, with or without 640129Speter * modification, are permitted provided that the following conditions 740129Speter * are met: 840129Speter * 1. Redistributions of source code must retain the above copyright 940129Speter * notice, this list of conditions and the following disclaimer. 1040129Speter * 2. Redistributions in binary form must reproduce the above copyright 1140129Speter * notice, this list of conditions and the following disclaimer in the 1240129Speter * documentation and/or other materials provided with the distribution. 1340129Speter * 1440129Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1540129Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1640129Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1740129Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1840129Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1940129Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2040129Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2140129Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2240129Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2340129Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2440129Speter */ 2540129Speter 26115683Sobrien#include <sys/cdefs.h> 27115683Sobrien__FBSDID("$FreeBSD$"); 28115683Sobrien 29279211Sjhb#include "opt_cpu.h" 30279211Sjhb 3140129Speter#include <sys/param.h> 32100384Speter#include <sys/kernel.h> 3340129Speter#include <sys/systm.h> 34102808Sjake#include <sys/exec.h> 35102808Sjake#include <sys/imgact.h> 3640129Speter#include <sys/linker.h> 37208453Skib#include <sys/proc.h> 38100384Speter#include <sys/sysent.h> 39100384Speter#include <sys/imgact_elf.h> 40100384Speter#include <sys/syscall.h> 41100384Speter#include <sys/signalvar.h> 42100384Speter#include <sys/vnode.h> 43102808Sjake 44102808Sjake#include <vm/vm.h> 45102808Sjake#include <vm/pmap.h> 46102808Sjake#include <vm/vm_param.h> 47102808Sjake 4840129Speter#include <machine/elf.h> 49100384Speter#include <machine/md_var.h> 50279211Sjhb#include <machine/npx.h> 5140129Speter 52279211Sjhb#if !defined(CPU_DISABLE_SSE) && defined(I686_CPU) 53279211Sjhb#define CPU_ENABLE_SSE 54279211Sjhb#endif 55279211Sjhb 56100384Speterstruct sysentvec elf32_freebsd_sysvec = { 57183322Skib .sv_size = SYS_MAXSYSCALL, 58183322Skib .sv_table = sysent, 59183322Skib .sv_mask = 0, 60183322Skib .sv_sigsize = 0, 61183322Skib .sv_sigtbl = NULL, 62183322Skib .sv_errsize = 0, 63183322Skib .sv_errtbl = NULL, 64183322Skib .sv_transtrap = NULL, 65183322Skib .sv_fixup = __elfN(freebsd_fixup), 66183322Skib .sv_sendsig = sendsig, 67183322Skib .sv_sigcode = sigcode, 68183322Skib .sv_szsigcode = &szsigcode, 69183322Skib .sv_prepsyscall = NULL, 70183322Skib .sv_name = "FreeBSD ELF32", 71183322Skib .sv_coredump = __elfN(coredump), 72183322Skib .sv_imgact_try = NULL, 73183322Skib .sv_minsigstksz = MINSIGSTKSZ, 74183322Skib .sv_pagesize = PAGE_SIZE, 75183322Skib .sv_minuser = VM_MIN_ADDRESS, 76183322Skib .sv_maxuser = VM_MAXUSER_ADDRESS, 77183322Skib .sv_usrstack = USRSTACK, 78183322Skib .sv_psstrings = PS_STRINGS, 79183322Skib .sv_stackprot = VM_PROT_ALL, 80183322Skib .sv_copyout_strings = exec_copyout_strings, 81183322Skib .sv_setregs = exec_setregs, 82183322Skib .sv_fixlimit = NULL, 83185169Skib .sv_maxssiz = NULL, 84237435Skib .sv_flags = SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 | SV_SHP, 85208453Skib .sv_set_syscall_retval = cpu_set_syscall_retval, 86208453Skib .sv_fetch_syscall_args = cpu_fetch_syscall_args, 87208453Skib .sv_syscallnames = syscallnames, 88237435Skib .sv_shared_page_base = SHAREDPAGE, 89237435Skib .sv_shared_page_len = PAGE_SIZE, 90219405Sdchagin .sv_schedtail = NULL, 91293490Sdchagin .sv_thread_detach = NULL, 92294136Sdchagin .sv_trap = NULL, 93100384Speter}; 94237435SkibINIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); 95100384Speter 96100384Speterstatic Elf32_Brandinfo freebsd_brand_info = { 97183322Skib .brand = ELFOSABI_FREEBSD, 98183322Skib .machine = EM_386, 99183322Skib .compat_3_brand = "FreeBSD", 100183322Skib .emul_path = NULL, 101183322Skib .interp_path = "/libexec/ld-elf.so.1", 102183322Skib .sysvec = &elf32_freebsd_sysvec, 103183322Skib .interp_newpath = NULL, 104189771Sdchagin .brand_note = &elf32_freebsd_brandnote, 105190708Sdchagin .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 106183322Skib}; 107100384Speter 108197729SbzSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST, 109100384Speter (sysinit_cfunc_t) elf32_insert_brand_entry, 110100384Speter &freebsd_brand_info); 111100384Speter 112123742Speterstatic Elf32_Brandinfo freebsd_brand_oinfo = { 113183322Skib .brand = ELFOSABI_FREEBSD, 114183322Skib .machine = EM_386, 115183322Skib .compat_3_brand = "FreeBSD", 116183322Skib .emul_path = NULL, 117183322Skib .interp_path = "/usr/libexec/ld-elf.so.1", 118183322Skib .sysvec = &elf32_freebsd_sysvec, 119183322Skib .interp_newpath = NULL, 120189771Sdchagin .brand_note = &elf32_freebsd_brandnote, 121190708Sdchagin .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 122183322Skib}; 123123742Speter 124123742SpeterSYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY, 125123742Speter (sysinit_cfunc_t) elf32_insert_brand_entry, 126123742Speter &freebsd_brand_oinfo); 127123742Speter 128196512Sbzstatic Elf32_Brandinfo kfreebsd_brand_info = { 129196512Sbz .brand = ELFOSABI_FREEBSD, 130196512Sbz .machine = EM_386, 131196512Sbz .compat_3_brand = "FreeBSD", 132196512Sbz .emul_path = NULL, 133196512Sbz .interp_path = "/lib/ld.so.1", 134196512Sbz .sysvec = &elf32_freebsd_sysvec, 135196512Sbz .interp_newpath = NULL, 136196512Sbz .brand_note = &elf32_kfreebsd_brandnote, 137196653Sbz .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY 138196512Sbz}; 139133464Smarcel 140196512SbzSYSINIT(kelf32, SI_SUB_EXEC, SI_ORDER_ANY, 141196512Sbz (sysinit_cfunc_t) elf32_insert_brand_entry, 142196512Sbz &kfreebsd_brand_info); 143196512Sbz 144196512Sbz 145133464Smarcelvoid 146279211Sjhbelf32_dump_thread(struct thread *td, void *dst, size_t *off) 147133464Smarcel{ 148279211Sjhb#ifdef CPU_ENABLE_SSE 149279211Sjhb void *buf; 150279211Sjhb#endif 151279211Sjhb size_t len; 152279211Sjhb 153279211Sjhb len = 0; 154279211Sjhb#ifdef CPU_ENABLE_SSE 155279211Sjhb if (use_xsave) { 156279211Sjhb if (dst != NULL) { 157279211Sjhb npxgetregs(td); 158279211Sjhb len += elf32_populate_note(NT_X86_XSTATE, 159279211Sjhb get_pcb_user_save_td(td), dst, 160279211Sjhb cpu_max_ext_state_size, &buf); 161279211Sjhb *(uint64_t *)((char *)buf + X86_XSTATE_XCR0_OFFSET) = 162279211Sjhb xsave_mask; 163279211Sjhb } else 164279211Sjhb len += elf32_populate_note(NT_X86_XSTATE, NULL, NULL, 165279211Sjhb cpu_max_ext_state_size, NULL); 166279211Sjhb } 167279211Sjhb#endif 168279211Sjhb *off = len; 169133464Smarcel} 170133464Smarcel 17140130Speter/* Process one elf relocation with addend. */ 172109605Sjakestatic int 173129282Speterelf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, 174129282Speter int type, int local, elf_lookup_fn lookup) 17540129Speter{ 17640435Speter Elf_Addr *where; 17741591Sarchie Elf_Addr addr; 17840435Speter Elf_Addr addend; 17995410Smarcel Elf_Word rtype, symidx; 18040435Speter const Elf_Rel *rel; 18140435Speter const Elf_Rela *rela; 182288287Skib int error; 18340129Speter 18440435Speter switch (type) { 18540435Speter case ELF_RELOC_REL: 18643314Sdillon rel = (const Elf_Rel *)data; 18740435Speter where = (Elf_Addr *) (relocbase + rel->r_offset); 18840435Speter addend = *where; 18940435Speter rtype = ELF_R_TYPE(rel->r_info); 19095410Smarcel symidx = ELF_R_SYM(rel->r_info); 19140435Speter break; 19240435Speter case ELF_RELOC_RELA: 19343314Sdillon rela = (const Elf_Rela *)data; 19440435Speter where = (Elf_Addr *) (relocbase + rela->r_offset); 19540435Speter addend = rela->r_addend; 19640435Speter rtype = ELF_R_TYPE(rela->r_info); 19795410Smarcel symidx = ELF_R_SYM(rela->r_info); 19840435Speter break; 19940435Speter default: 20040435Speter panic("unknown reloc type %d\n", type); 20140435Speter } 20240129Speter 203109605Sjake if (local) { 204109605Sjake if (rtype == R_386_RELATIVE) { /* A + B */ 205194784Sjeff addr = elf_relocaddr(lf, relocbase + addend); 206109605Sjake if (*where != addr) 207109605Sjake *where = addr; 208109605Sjake } 209109605Sjake return (0); 210109605Sjake } 211109605Sjake 21240435Speter switch (rtype) { 21340435Speter 21440435Speter case R_386_NONE: /* none */ 21540129Speter break; 21640129Speter 21740435Speter case R_386_32: /* S + A */ 218288287Skib error = lookup(lf, symidx, 1, &addr); 219288287Skib if (error != 0) 22040129Speter return -1; 22140435Speter addr += addend; 22240129Speter if (*where != addr) 22340129Speter *where = addr; 22440129Speter break; 22540129Speter 22640435Speter case R_386_PC32: /* S + A - P */ 227288287Skib error = lookup(lf, symidx, 1, &addr); 228288287Skib if (error != 0) 22940129Speter return -1; 23040435Speter addr += addend - (Elf_Addr)where; 23140129Speter if (*where != addr) 23240129Speter *where = addr; 23340129Speter break; 23440129Speter 23540435Speter case R_386_COPY: /* none */ 23640129Speter /* 23740129Speter * There shouldn't be copy relocations in kernel 23840129Speter * objects. 23940129Speter */ 24040129Speter printf("kldload: unexpected R_COPY relocation\n"); 24140129Speter return -1; 24240129Speter break; 24340129Speter 24440435Speter case R_386_GLOB_DAT: /* S */ 245288287Skib error = lookup(lf, symidx, 1, &addr); 246288287Skib if (error != 0) 24740129Speter return -1; 24840129Speter if (*where != addr) 24940129Speter *where = addr; 25040129Speter break; 25140129Speter 252109605Sjake case R_386_RELATIVE: 25340129Speter break; 25440129Speter 25540129Speter default: 25640129Speter printf("kldload: unexpected relocation type %d\n", 25740435Speter rtype); 25840129Speter return -1; 25940129Speter } 26040129Speter return(0); 26140129Speter} 262105469Smarcel 263105469Smarcelint 264129282Speterelf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, 265129282Speter elf_lookup_fn lookup) 266109605Sjake{ 267109605Sjake 268129282Speter return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); 269109605Sjake} 270109605Sjake 271109605Sjakeint 272129282Speterelf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, 273129282Speter int type, elf_lookup_fn lookup) 274109605Sjake{ 275109605Sjake 276129282Speter return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); 277109605Sjake} 278109605Sjake 279109605Sjakeint 280105469Smarcelelf_cpu_load_file(linker_file_t lf __unused) 281105469Smarcel{ 282105469Smarcel 283105469Smarcel return (0); 284105469Smarcel} 285105469Smarcel 286105469Smarcelint 287105469Smarcelelf_cpu_unload_file(linker_file_t lf __unused) 288105469Smarcel{ 289105469Smarcel 290105469Smarcel return (0); 291105469Smarcel} 292