elf32_machdep.c revision 132282
125428Speter/*- 250477Speter * Copyright 1996-1998 John D. Polstra. 325428Speter * All rights reserved. 425428Speter * 525428Speter * Redistribution and use in source and binary forms, with or without 625428Speter * modification, are permitted provided that the following conditions 725428Speter * are met: 825428Speter * 1. Redistributions of source code must retain the above copyright 925428Speter * notice, this list of conditions and the following disclaimer. 1025428Speter * 2. Redistributions in binary form must reproduce the above copyright 1125428Speter * notice, this list of conditions and the following disclaimer in the 1225428Speter * documentation and/or other materials provided with the distribution. 1325428Speter * 1425428Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1525428Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1625428Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1725428Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1825428Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1925428Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2025428Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2125428Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2225428Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2325428Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2425428Speter * 2525428Speter * $FreeBSD: head/sys/powerpc/powerpc/elf_machdep.c 132282 2004-07-17 07:26:32Z grehan $ 2625428Speter */ 2725428Speter 2825428Speter#include <sys/param.h> 2925428Speter#include <sys/kernel.h> 3025428Speter#include <sys/systm.h> 3125428Speter#include <sys/exec.h> 3225428Speter#include <sys/imgact.h> 3325428Speter#include <sys/malloc.h> 3425428Speter#include <sys/proc.h> 3525428Speter#include <sys/namei.h> 3625428Speter#include <sys/fcntl.h> 3725428Speter#include <sys/sysent.h> 3825428Speter#include <sys/imgact_elf.h> 3925428Speter#include <sys/syscall.h> 4025428Speter#include <sys/signalvar.h> 4125428Speter#include <sys/vnode.h> 4225428Speter#include <sys/linker.h> 4325428Speter 4425428Speter#include <vm/vm.h> 4525428Speter#include <vm/vm_param.h> 4625428Speter 4725428Speter#include <machine/cpu.h> 4825428Speter#include <machine/elf.h> 4925428Speter#include <machine/md_var.h> 5025428Speter 5125428Speterstruct sysentvec elf32_freebsd_sysvec = { 5225428Speter SYS_MAXSYSCALL, 5355205Speter sysent, 5425428Speter 0, 5525428Speter 0, 5625428Speter NULL, 5725428Speter 0, 5825428Speter NULL, 5925428Speter NULL, 6025428Speter __elfN(freebsd_fixup), 6125428Speter sendsig, 6225428Speter sigcode, 6325428Speter &szsigcode, 6425428Speter NULL, 6525428Speter "FreeBSD ELF32", 6625428Speter __elfN(coredump), 6725428Speter NULL, 6825428Speter MINSIGSTKSZ, 6925428Speter PAGE_SIZE, 7025428Speter VM_MIN_ADDRESS, 7125428Speter VM_MAXUSER_ADDRESS, 7225428Speter USRSTACK, 7325428Speter PS_STRINGS, 7425428Speter VM_PROT_ALL, 7525428Speter exec_copyout_strings, 7625428Speter exec_setregs, 7725428Speter NULL 7825428Speter}; 7925428Speter 8025428Speterstatic Elf32_Brandinfo freebsd_brand_info = { 8125428Speter ELFOSABI_FREEBSD, 8225428Speter EM_PPC, 8325428Speter "FreeBSD", 8425428Speter NULL, 8525428Speter "/libexec/ld-elf.so.1", 8625428Speter &elf32_freebsd_sysvec, 8725428Speter NULL, 8825428Speter }; 8925428Speter 9045720SpeterSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY, 9145720Speter (sysinit_cfunc_t) elf32_insert_brand_entry, 9245720Speter &freebsd_brand_info); 9325428Speter 9425428Speterstatic Elf32_Brandinfo freebsd_brand_oinfo = { 9525428Speter ELFOSABI_FREEBSD, 9625428Speter EM_PPC, 9725428Speter "FreeBSD", 9825428Speter NULL, 9925428Speter "/usr/libexec/ld-elf.so.1", 10025428Speter &elf32_freebsd_sysvec, 10125428Speter NULL, 10225428Speter }; 10325428Speter 10425428SpeterSYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY, 10525428Speter (sysinit_cfunc_t) elf32_insert_brand_entry, 10625428Speter &freebsd_brand_oinfo); 10755205Speter 10825428Speter/* Process one elf relocation with addend. */ 10925428Speterstatic int 11025428Speterelf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, 11125428Speter int type, int local, elf_lookup_fn lookup) 11225428Speter{ 11353649Sjulian Elf_Addr *where; 11425428Speter Elf_Half *hwhere; 11525428Speter Elf_Addr addr; 11625428Speter Elf_Addr addend; 11725428Speter Elf_Word rtype, symidx; 11825428Speter const Elf_Rela *rela; 11925428Speter 12025428Speter switch (type) { 12125428Speter case ELF_RELOC_REL: 12225428Speter panic("PPC only supports RELA relocations"); 12325428Speter break; 12425428Speter case ELF_RELOC_RELA: 12525428Speter rela = (const Elf_Rela *)data; 12625428Speter where = (Elf_Addr *) (relocbase + rela->r_offset); 12725428Speter hwhere = (Elf_Half *) (relocbase + rela->r_offset); 12825428Speter addend = rela->r_addend; 12925428Speter rtype = ELF_R_TYPE(rela->r_info); 13025428Speter symidx = ELF_R_SYM(rela->r_info); 13125428Speter break; 13225428Speter default: 13344521Swpaul panic("elf_reloc: unknown relocation mode %d\n", type); 13444521Swpaul } 13544521Swpaul 13644542Swpaul switch (rtype) { 13744542Swpaul 13844542Swpaul case R_PPC_NONE: 13944542Swpaul break; 14053649Sjulian 14153649Sjulian case R_PPC_ADDR32: /* word32 S + A */ 14225428Speter addr = lookup(lf, symidx, 1); 14325428Speter if (addr == 0) 14425428Speter return -1; 14525428Speter addr += addend; 14625428Speter *where = addr; 14725428Speter break; 14825428Speter 14925428Speter case R_PPC_ADDR16_LO: /* #lo(S) */ 15025428Speter if (addend != 0) { 15144165Sjulian addr = relocbase + addend; 15244165Sjulian } else { 15325428Speter addr = lookup(lf, symidx, 1); 15425428Speter if (addr == 0) 15525428Speter return -1; 15644165Sjulian } 15744165Sjulian *hwhere = addr & 0xffff; 15844165Sjulian break; 15925428Speter 16025428Speter case R_PPC_ADDR16_HA: /* #ha(S) */ 16125428Speter if (addend != 0) { 16225428Speter addr = relocbase + addend; 16325428Speter } else { 16425428Speter addr = lookup(lf, symidx, 1); 16525428Speter if (addr == 0) 16625428Speter return -1; 16725428Speter } 16825428Speter *hwhere = ((addr >> 16) + ((addr & 0x8000) ? 1 : 0)) 16925428Speter & 0xffff; 17025428Speter break; 17125428Speter 17225428Speter case R_PPC_RELATIVE: /* word32 B + A */ 17325428Speter *where = relocbase + addend; 17425428Speter break; 17525428Speter 17625428Speter default: 17725428Speter printf("kldload: unexpected relocation type %d\n", 17825428Speter (int) rtype); 17925428Speter return -1; 18025428Speter } 18125428Speter return(0); 18225428Speter} 18325428Speter 18425428Speterint 18525428Speterelf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, 18625428Speter elf_lookup_fn lookup) 18725428Speter{ 18825428Speter 18925428Speter return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); 19053649Sjulian} 19125428Speter 19225428Speterint 19325428Speterelf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, 19425428Speter int type, elf_lookup_fn lookup) 19525428Speter{ 19625428Speter 19725428Speter return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); 19825428Speter} 19925428Speter 20025428Speterint 20125428Speterelf_cpu_load_file(linker_file_t lf __unused) 20225428Speter{ 20325428Speter 20425428Speter __syncicache(lf->address, lf->size); 20544165Sjulian return (0); 20644165Sjulian} 20744165Sjulian 20844165Sjulianint 20944521Swpaulelf_cpu_unload_file(linker_file_t lf __unused) 21025428Speter{ 21144521Swpaul 21244521Swpaul return (0); 21325428Speter} 21444521Swpaul