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 2940129Speter#include <sys/param.h> 30100384Speter#include <sys/kernel.h> 3140129Speter#include <sys/systm.h> 32102808Sjake#include <sys/exec.h> 33102808Sjake#include <sys/imgact.h> 3440129Speter#include <sys/linker.h> 35208453Skib#include <sys/proc.h> 36100384Speter#include <sys/sysent.h> 37100384Speter#include <sys/imgact_elf.h> 38100384Speter#include <sys/syscall.h> 39100384Speter#include <sys/signalvar.h> 40100384Speter#include <sys/vnode.h> 41102808Sjake 42102808Sjake#include <vm/vm.h> 43102808Sjake#include <vm/pmap.h> 44102808Sjake#include <vm/vm_param.h> 45102808Sjake 4640129Speter#include <machine/elf.h> 47100384Speter#include <machine/md_var.h> 4840129Speter 49100384Speterstruct sysentvec elf32_freebsd_sysvec = { 50183322Skib .sv_size = SYS_MAXSYSCALL, 51183322Skib .sv_table = sysent, 52183322Skib .sv_mask = 0, 53183322Skib .sv_sigsize = 0, 54183322Skib .sv_sigtbl = NULL, 55183322Skib .sv_errsize = 0, 56183322Skib .sv_errtbl = NULL, 57183322Skib .sv_transtrap = NULL, 58183322Skib .sv_fixup = __elfN(freebsd_fixup), 59183322Skib .sv_sendsig = sendsig, 60183322Skib .sv_sigcode = sigcode, 61183322Skib .sv_szsigcode = &szsigcode, 62183322Skib .sv_prepsyscall = NULL, 63183322Skib .sv_name = "FreeBSD ELF32", 64183322Skib .sv_coredump = __elfN(coredump), 65183322Skib .sv_imgact_try = NULL, 66183322Skib .sv_minsigstksz = MINSIGSTKSZ, 67183322Skib .sv_pagesize = PAGE_SIZE, 68183322Skib .sv_minuser = VM_MIN_ADDRESS, 69183322Skib .sv_maxuser = VM_MAXUSER_ADDRESS, 70183322Skib .sv_usrstack = USRSTACK, 71183322Skib .sv_psstrings = PS_STRINGS, 72183322Skib .sv_stackprot = VM_PROT_ALL, 73183322Skib .sv_copyout_strings = exec_copyout_strings, 74183322Skib .sv_setregs = exec_setregs, 75183322Skib .sv_fixlimit = NULL, 76185169Skib .sv_maxssiz = NULL, 77237435Skib .sv_flags = SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 | SV_SHP, 78208453Skib .sv_set_syscall_retval = cpu_set_syscall_retval, 79208453Skib .sv_fetch_syscall_args = cpu_fetch_syscall_args, 80208453Skib .sv_syscallnames = syscallnames, 81237435Skib .sv_shared_page_base = SHAREDPAGE, 82237435Skib .sv_shared_page_len = PAGE_SIZE, 83219405Sdchagin .sv_schedtail = NULL, 84100384Speter}; 85237435SkibINIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); 86100384Speter 87100384Speterstatic Elf32_Brandinfo freebsd_brand_info = { 88183322Skib .brand = ELFOSABI_FREEBSD, 89183322Skib .machine = EM_386, 90183322Skib .compat_3_brand = "FreeBSD", 91183322Skib .emul_path = NULL, 92183322Skib .interp_path = "/libexec/ld-elf.so.1", 93183322Skib .sysvec = &elf32_freebsd_sysvec, 94183322Skib .interp_newpath = NULL, 95189771Sdchagin .brand_note = &elf32_freebsd_brandnote, 96190708Sdchagin .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 97183322Skib}; 98100384Speter 99197729SbzSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST, 100100384Speter (sysinit_cfunc_t) elf32_insert_brand_entry, 101100384Speter &freebsd_brand_info); 102100384Speter 103123742Speterstatic Elf32_Brandinfo freebsd_brand_oinfo = { 104183322Skib .brand = ELFOSABI_FREEBSD, 105183322Skib .machine = EM_386, 106183322Skib .compat_3_brand = "FreeBSD", 107183322Skib .emul_path = NULL, 108183322Skib .interp_path = "/usr/libexec/ld-elf.so.1", 109183322Skib .sysvec = &elf32_freebsd_sysvec, 110183322Skib .interp_newpath = NULL, 111189771Sdchagin .brand_note = &elf32_freebsd_brandnote, 112190708Sdchagin .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 113183322Skib}; 114123742Speter 115123742SpeterSYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY, 116123742Speter (sysinit_cfunc_t) elf32_insert_brand_entry, 117123742Speter &freebsd_brand_oinfo); 118123742Speter 119196512Sbzstatic Elf32_Brandinfo kfreebsd_brand_info = { 120196512Sbz .brand = ELFOSABI_FREEBSD, 121196512Sbz .machine = EM_386, 122196512Sbz .compat_3_brand = "FreeBSD", 123196512Sbz .emul_path = NULL, 124196512Sbz .interp_path = "/lib/ld.so.1", 125196512Sbz .sysvec = &elf32_freebsd_sysvec, 126196512Sbz .interp_newpath = NULL, 127196512Sbz .brand_note = &elf32_kfreebsd_brandnote, 128196653Sbz .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY 129196512Sbz}; 130133464Smarcel 131196512SbzSYSINIT(kelf32, SI_SUB_EXEC, SI_ORDER_ANY, 132196512Sbz (sysinit_cfunc_t) elf32_insert_brand_entry, 133196512Sbz &kfreebsd_brand_info); 134196512Sbz 135196512Sbz 136133464Smarcelvoid 137133464Smarcelelf32_dump_thread(struct thread *td __unused, void *dst __unused, 138133464Smarcel size_t *off __unused) 139133464Smarcel{ 140133464Smarcel} 141133464Smarcel 142133464Smarcel 14340130Speter/* Process one elf relocation with addend. */ 144109605Sjakestatic int 145129282Speterelf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, 146129282Speter int type, int local, elf_lookup_fn lookup) 14740129Speter{ 14840435Speter Elf_Addr *where; 14941591Sarchie Elf_Addr addr; 15040435Speter Elf_Addr addend; 15195410Smarcel Elf_Word rtype, symidx; 15240435Speter const Elf_Rel *rel; 15340435Speter const Elf_Rela *rela; 15440129Speter 15540435Speter switch (type) { 15640435Speter case ELF_RELOC_REL: 15743314Sdillon rel = (const Elf_Rel *)data; 15840435Speter where = (Elf_Addr *) (relocbase + rel->r_offset); 15940435Speter addend = *where; 16040435Speter rtype = ELF_R_TYPE(rel->r_info); 16195410Smarcel symidx = ELF_R_SYM(rel->r_info); 16240435Speter break; 16340435Speter case ELF_RELOC_RELA: 16443314Sdillon rela = (const Elf_Rela *)data; 16540435Speter where = (Elf_Addr *) (relocbase + rela->r_offset); 16640435Speter addend = rela->r_addend; 16740435Speter rtype = ELF_R_TYPE(rela->r_info); 16895410Smarcel symidx = ELF_R_SYM(rela->r_info); 16940435Speter break; 17040435Speter default: 17140435Speter panic("unknown reloc type %d\n", type); 17240435Speter } 17340129Speter 174109605Sjake if (local) { 175109605Sjake if (rtype == R_386_RELATIVE) { /* A + B */ 176194784Sjeff addr = elf_relocaddr(lf, relocbase + addend); 177109605Sjake if (*where != addr) 178109605Sjake *where = addr; 179109605Sjake } 180109605Sjake return (0); 181109605Sjake } 182109605Sjake 18340435Speter switch (rtype) { 18440435Speter 18540435Speter case R_386_NONE: /* none */ 18640129Speter break; 18740129Speter 18840435Speter case R_386_32: /* S + A */ 189129282Speter addr = lookup(lf, symidx, 1); 19054952Seivind if (addr == 0) 19140129Speter return -1; 19240435Speter addr += addend; 19340129Speter if (*where != addr) 19440129Speter *where = addr; 19540129Speter break; 19640129Speter 19740435Speter case R_386_PC32: /* S + A - P */ 198129282Speter addr = lookup(lf, symidx, 1); 19954952Seivind if (addr == 0) 20040129Speter return -1; 20140435Speter addr += addend - (Elf_Addr)where; 20240129Speter if (*where != addr) 20340129Speter *where = addr; 20440129Speter break; 20540129Speter 20640435Speter case R_386_COPY: /* none */ 20740129Speter /* 20840129Speter * There shouldn't be copy relocations in kernel 20940129Speter * objects. 21040129Speter */ 21140129Speter printf("kldload: unexpected R_COPY relocation\n"); 21240129Speter return -1; 21340129Speter break; 21440129Speter 21540435Speter case R_386_GLOB_DAT: /* S */ 216129282Speter addr = lookup(lf, symidx, 1); 21754952Seivind if (addr == 0) 21840129Speter return -1; 21940129Speter if (*where != addr) 22040129Speter *where = addr; 22140129Speter break; 22240129Speter 223109605Sjake case R_386_RELATIVE: 22440129Speter break; 22540129Speter 22640129Speter default: 22740129Speter printf("kldload: unexpected relocation type %d\n", 22840435Speter rtype); 22940129Speter return -1; 23040129Speter } 23140129Speter return(0); 23240129Speter} 233105469Smarcel 234105469Smarcelint 235129282Speterelf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, 236129282Speter elf_lookup_fn lookup) 237109605Sjake{ 238109605Sjake 239129282Speter return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); 240109605Sjake} 241109605Sjake 242109605Sjakeint 243129282Speterelf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, 244129282Speter int type, elf_lookup_fn lookup) 245109605Sjake{ 246109605Sjake 247129282Speter return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); 248109605Sjake} 249109605Sjake 250109605Sjakeint 251105469Smarcelelf_cpu_load_file(linker_file_t lf __unused) 252105469Smarcel{ 253105469Smarcel 254105469Smarcel return (0); 255105469Smarcel} 256105469Smarcel 257105469Smarcelint 258105469Smarcelelf_cpu_unload_file(linker_file_t lf __unused) 259105469Smarcel{ 260105469Smarcel 261105469Smarcel return (0); 262105469Smarcel} 263