elf_machdep.c revision 129282
118334Speter/*- 218334Speter * Copyright 1996-1998 John D. Polstra. 3132718Skan * All rights reserved. 4169689Skan * 5132718Skan * Redistribution and use in source and binary forms, with or without 618334Speter * modification, are permitted provided that the following conditions 7132718Skan * are met: 818334Speter * 1. Redistributions of source code must retain the above copyright 918334Speter * notice, this list of conditions and the following disclaimer. 1018334Speter * 2. Redistributions in binary form must reproduce the above copyright 1118334Speter * notice, this list of conditions and the following disclaimer in the 12132718Skan * documentation and/or other materials provided with the distribution. 1318334Speter * 1418334Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1518334Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1618334Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1718334Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18132718Skan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19169689Skan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20169689Skan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2118334Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2218334Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2350397Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24132718Skan */ 25132718Skan 2618334Speter#include <sys/cdefs.h> 2718334Speter__FBSDID("$FreeBSD: head/sys/arm/arm/elf_machdep.c 129282 2004-05-16 20:00:28Z peter $"); 2890075Sobrien 2950397Sobrien#include <sys/param.h> 3090075Sobrien#include <sys/kernel.h> 3190075Sobrien#include <sys/systm.h> 32117395Skan#include <sys/exec.h> 33132718Skan#include <sys/imgact.h> 3418334Speter#include <sys/linker.h> 35169689Skan#include <sys/sysent.h> 3618334Speter#include <sys/imgact_elf.h> 3790075Sobrien#include <sys/syscall.h> 3890075Sobrien#include <sys/signalvar.h> 3990075Sobrien#include <sys/vnode.h> 40132718Skan 41132718Skan#include <vm/vm.h> 4218334Speter#include <vm/pmap.h> 4390075Sobrien#include <vm/vm_param.h> 4418334Speter 45132718Skan#include <machine/elf.h> 46132718Skan#include <machine/md_var.h> 47132718Skan 48132718Skanstruct sysentvec elf32_freebsd_sysvec = { 49132718Skan SYS_MAXSYSCALL, 50132718Skan sysent, 51132718Skan 0, 52132718Skan 0, 53132718Skan NULL, 54132718Skan 0, 5552284Sobrien NULL, 56132718Skan NULL, 57132718Skan __elfN(freebsd_fixup), 58132718Skan sendsig, 59132718Skan NULL, 60132718Skan NULL, 61132718Skan NULL, 62132718Skan "FreeBSD ELF32", 63132718Skan __elfN(coredump), 64132718Skan NULL, 65132718Skan MINSIGSTKSZ, 66169689Skan PAGE_SIZE, 67132718Skan VM_MIN_ADDRESS, 68132718Skan VM_MAXUSER_ADDRESS, 69132718Skan USRSTACK, 70132718Skan PS_STRINGS, 71132718Skan VM_PROT_ALL, 72132718Skan exec_copyout_strings, 73132718Skan exec_setregs, 74132718Skan NULL 75132718Skan}; 76132718Skan 77132718Skanstatic Elf32_Brandinfo freebsd_brand_info = { 78132718Skan ELFOSABI_FREEBSD, 7918334Speter EM_ARM, 80132718Skan "FreeBSD", 81132718Skan NULL, 82132718Skan "/libexec/ld-elf.so.1", 83132718Skan &elf32_freebsd_sysvec, 84169689Skan NULL, 85132718Skan }; 86132718Skan 87132718SkanSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY, 8818334Speter (sysinit_cfunc_t) elf32_insert_brand_entry, 89169689Skan &freebsd_brand_info); 90169689Skan 91132718Skanstatic Elf32_Brandinfo freebsd_brand_oinfo = { 9250397Sobrien ELFOSABI_FREEBSD, 9318334Speter EM_ARM, 94132718Skan "FreeBSD", 9518334Speter NULL, 9690075Sobrien "/usr/libexec/ld-elf.so.1", 9790075Sobrien &elf32_freebsd_sysvec, 9890075Sobrien NULL, 9990075Sobrien }; 100132718Skan 101132718SkanSYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY, 10218334Speter (sysinit_cfunc_t) elf32_insert_brand_entry, 10318334Speter &freebsd_brand_oinfo); 10490075Sobrien 10552284Sobrien/* Process one elf relocation with addend. */ 10690075Sobrienstatic int 107132718Skanelf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, 10852284Sobrien int type, int local, elf_lookup_fn lookup) 10990075Sobrien{ 11052284Sobrien Elf_Addr *where; 11190075Sobrien Elf_Addr addr; 11290075Sobrien Elf_Addr addend; 11390075Sobrien Elf_Word rtype, symidx; 11490075Sobrien const Elf_Rel *rel; 11590075Sobrien const Elf_Rela *rela; 11690075Sobrien 117169689Skan switch (type) { 118169689Skan case ELF_RELOC_REL: 119169689Skan rel = (const Elf_Rel *)data; 120169689Skan where = (Elf_Addr *) (relocbase + rel->r_offset); 12190075Sobrien addend = *where; 12290075Sobrien rtype = ELF_R_TYPE(rel->r_info); 12390075Sobrien symidx = ELF_R_SYM(rel->r_info); 12490075Sobrien break; 125169689Skan case ELF_RELOC_RELA: 12690075Sobrien rela = (const Elf_Rela *)data; 12790075Sobrien where = (Elf_Addr *) (relocbase + rela->r_offset); 12890075Sobrien addend = rela->r_addend; 12990075Sobrien rtype = ELF_R_TYPE(rela->r_info); 130169689Skan symidx = ELF_R_SYM(rela->r_info); 13190075Sobrien break; 13252284Sobrien default: 13352284Sobrien panic("unknown reloc type %d\n", type); 13490075Sobrien } 13552284Sobrien 13690075Sobrien if (local) { 137132718Skan if (rtype == R_ARM_RELATIVE) { /* A + B */ 13890075Sobrien addr = relocbase + addend; 13990075Sobrien if (*where != addr) 14090075Sobrien *where = addr; 14190075Sobrien } 14290075Sobrien return (0); 14390075Sobrien } 14452284Sobrien 14590075Sobrien switch (rtype) { 14690075Sobrien 14752284Sobrien case R_ARM_NONE: /* none */ 14890075Sobrien break; 149132718Skan 15090075Sobrien case R_ARM_PC24: /* S + A - P */ 15190075Sobrien addr = lookup(lf, symidx, 1); 15290075Sobrien if (addr == 0) 15390075Sobrien return -1; 15452284Sobrien addr += addend - (Elf_Addr)where; 15590075Sobrien if (*where != addr) 15690075Sobrien *where = addr; 15790075Sobrien break; 158169689Skan 15990075Sobrien case R_ARM_COPY: /* none */ 16090075Sobrien /* 16190075Sobrien * There shouldn't be copy relocations in kernel 16290075Sobrien * objects. 16352284Sobrien */ 16490075Sobrien printf("kldload: unexpected R_COPY relocation\n"); 16590075Sobrien return -1; 16690075Sobrien break; 167132718Skan 16890075Sobrien case R_ARM_GLOB_DAT: /* S */ 169169689Skan addr = lookup(lf, symidx, 1); 170169689Skan if (addr == 0) 17190075Sobrien return -1; 172169689Skan if (*where != addr) 173169689Skan *where = addr; 174169689Skan break; 175169689Skan 176169689Skan case R_ARM_RELATIVE: 177169689Skan break; 17890075Sobrien 17990075Sobrien default: 18090075Sobrien printf("kldload: unexpected relocation type %d\n", 181169689Skan rtype); 182169689Skan return -1; 183169689Skan } 184169689Skan return(0); 185169689Skan} 18690075Sobrien 187169689Skanint 18890075Sobrienelf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, 189169689Skan elf_lookup_fn lookup) 19090075Sobrien{ 19190075Sobrien 19290075Sobrien return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); 19390075Sobrien} 19490075Sobrien 19590075Sobrienint 196169689Skanelf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, 197169689Skan int type, elf_lookup_fn lookup) 198169689Skan{ 19990075Sobrien 200169689Skan return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); 20190075Sobrien} 202169689Skan 20390075Sobrienint 20490075Sobrienelf_cpu_load_file(linker_file_t lf __unused) 20590075Sobrien{ 20690075Sobrien 20790075Sobrien return (0); 20890075Sobrien} 20990075Sobrien 21090075Sobrienint 211132718Skanelf_cpu_unload_file(linker_file_t lf __unused) 21290075Sobrien{ 21390075Sobrien 21490075Sobrien return (0); 21590075Sobrien} 21690075Sobrien