elf_machdep.c revision 225973
1275970Scy/*- 2275970Scy * Copyright 1996-1998 John D. Polstra. 3275970Scy * All rights reserved. 4275970Scy * 5275970Scy * Redistribution and use in source and binary forms, with or without 6275970Scy * modification, are permitted provided that the following conditions 7275970Scy * are met: 8275970Scy * 1. Redistributions of source code must retain the above copyright 9275970Scy * notice, this list of conditions and the following disclaimer. 10275970Scy * 2. Redistributions in binary form must reproduce the above copyright 11275970Scy * notice, this list of conditions and the following disclaimer in the 12275970Scy * documentation and/or other materials provided with the distribution. 13338531Sdelphij * 14275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15338531Sdelphij * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17338531Sdelphij * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24275970Scy */ 25275970Scy 26275970Scy#include <sys/cdefs.h> 27275970Scy__FBSDID("$FreeBSD: head/sys/arm/arm/elf_machdep.c 225973 2011-10-04 13:14:24Z kib $"); 28275970Scy 29275970Scy#include <sys/param.h> 30275970Scy#include <sys/kernel.h> 31275970Scy#include <sys/systm.h> 32275970Scy#include <sys/exec.h> 33275970Scy#include <sys/imgact.h> 34275970Scy#include <sys/linker.h> 35275970Scy#include <sys/sysent.h> 36275970Scy#include <sys/imgact_elf.h> 37275970Scy#include <sys/proc.h> 38275970Scy#include <sys/syscall.h> 39275970Scy#include <sys/signalvar.h> 40275970Scy#include <sys/vnode.h> 41285612Sdelphij 42275970Scy#include <vm/vm.h> 43275970Scy#include <vm/pmap.h> 44275970Scy#include <vm/vm_param.h> 45285612Sdelphij 46275970Scy#include <machine/elf.h> 47275970Scy#include <machine/md_var.h> 48275970Scy 49275970Scystruct sysentvec elf32_freebsd_sysvec = { 50275970Scy .sv_size = SYS_MAXSYSCALL, 51275970Scy .sv_table = sysent, 52275970Scy .sv_mask = 0, 53275970Scy .sv_sigsize = 0, 54275970Scy .sv_sigtbl = NULL, 55275970Scy .sv_errsize = 0, 56275970Scy .sv_errtbl = NULL, 57275970Scy .sv_transtrap = NULL, 58275970Scy .sv_fixup = __elfN(freebsd_fixup), 59275970Scy .sv_sendsig = sendsig, 60275970Scy .sv_sigcode = sigcode, 61275970Scy .sv_szsigcode = &szsigcode, 62275970Scy .sv_prepsyscall = NULL, 63275970Scy .sv_name = "FreeBSD ELF32", 64275970Scy .sv_coredump = __elfN(coredump), 65275970Scy .sv_imgact_try = NULL, 66275970Scy .sv_minsigstksz = MINSIGSTKSZ, 67275970Scy .sv_pagesize = PAGE_SIZE, 68275970Scy .sv_minuser = VM_MIN_ADDRESS, 69275970Scy .sv_maxuser = VM_MAXUSER_ADDRESS, 70275970Scy .sv_usrstack = USRSTACK, 71275970Scy .sv_psstrings = PS_STRINGS, 72275970Scy .sv_stackprot = VM_PROT_ALL, 73275970Scy .sv_copyout_strings = exec_copyout_strings, 74275970Scy .sv_setregs = exec_setregs, 75275970Scy .sv_fixlimit = NULL, 76275970Scy .sv_maxssiz = NULL, 77275970Scy .sv_flags = SV_ABI_FREEBSD | SV_ILP32, 78275970Scy .sv_set_syscall_retval = cpu_set_syscall_retval, 79275970Scy .sv_fetch_syscall_args = cpu_fetch_syscall_args, 80275970Scy .sv_syscallnames = syscallnames, 81275970Scy .sv_schedtail = NULL, 82275970Scy}; 83275970Scy 84275970Scystatic Elf32_Brandinfo freebsd_brand_info = { 85275970Scy .brand = ELFOSABI_FREEBSD, 86275970Scy .machine = EM_ARM, 87275970Scy .compat_3_brand = "FreeBSD", 88275970Scy .emul_path = NULL, 89275970Scy .interp_path = "/libexec/ld-elf.so.1", 90275970Scy .sysvec = &elf32_freebsd_sysvec, 91275970Scy .interp_newpath = NULL, 92275970Scy .brand_note = &elf32_freebsd_brandnote, 93275970Scy .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 94275970Scy}; 95275970Scy 96275970ScySYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST, 97275970Scy (sysinit_cfunc_t) elf32_insert_brand_entry, 98275970Scy &freebsd_brand_info); 99275970Scy 100275970Scystatic Elf32_Brandinfo freebsd_brand_oinfo = { 101275970Scy .brand = ELFOSABI_FREEBSD, 102275970Scy .machine = EM_ARM, 103275970Scy .compat_3_brand = "FreeBSD", 104275970Scy .emul_path = NULL, 105275970Scy .interp_path = "/usr/libexec/ld-elf.so.1", 106275970Scy .sysvec = &elf32_freebsd_sysvec, 107275970Scy .interp_newpath = NULL, 108275970Scy .brand_note = &elf32_freebsd_brandnote, 109275970Scy .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 110275970Scy}; 111275970Scy 112275970ScySYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY, 113275970Scy (sysinit_cfunc_t) elf32_insert_brand_entry, 114275970Scy &freebsd_brand_oinfo); 115275970Scy 116275970Scy 117275970Scyvoid 118275970Scyelf32_dump_thread(struct thread *td __unused, void *dst __unused, 119275970Scy size_t *off __unused) 120275970Scy{ 121275970Scy} 122275970Scy 123 124/* Process one elf relocation with addend. */ 125static int 126elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, 127 int type, int local, elf_lookup_fn lookup) 128{ 129 Elf_Addr *where; 130 Elf_Addr addr; 131 Elf_Addr addend; 132 Elf_Word rtype, symidx; 133 const Elf_Rel *rel; 134 const Elf_Rela *rela; 135 136 switch (type) { 137 case ELF_RELOC_REL: 138 rel = (const Elf_Rel *)data; 139 where = (Elf_Addr *) (relocbase + rel->r_offset); 140 addend = *where; 141 rtype = ELF_R_TYPE(rel->r_info); 142 symidx = ELF_R_SYM(rel->r_info); 143 break; 144 case ELF_RELOC_RELA: 145 rela = (const Elf_Rela *)data; 146 where = (Elf_Addr *) (relocbase + rela->r_offset); 147 addend = rela->r_addend; 148 rtype = ELF_R_TYPE(rela->r_info); 149 symidx = ELF_R_SYM(rela->r_info); 150 break; 151 default: 152 panic("unknown reloc type %d\n", type); 153 } 154 155 if (local) { 156 if (rtype == R_ARM_RELATIVE) { /* A + B */ 157 addr = elf_relocaddr(lf, relocbase + addend); 158 if (*where != addr) 159 *where = addr; 160 } 161 return (0); 162 } 163 164 switch (rtype) { 165 166 case R_ARM_NONE: /* none */ 167 break; 168 169 case R_ARM_ABS32: 170 addr = lookup(lf, symidx, 1); 171 if (addr == 0) 172 return -1; 173 *where += addr; 174 break; 175 176 case R_ARM_COPY: /* none */ 177 /* 178 * There shouldn't be copy relocations in kernel 179 * objects. 180 */ 181 printf("kldload: unexpected R_COPY relocation\n"); 182 return -1; 183 break; 184 185 case R_ARM_JUMP_SLOT: 186 addr = lookup(lf, symidx, 1); 187 if (addr) { 188 *where = addr; 189 return (0); 190 } 191 return (-1); 192 case R_ARM_RELATIVE: 193 break; 194 195 default: 196 printf("kldload: unexpected relocation type %d\n", 197 rtype); 198 return -1; 199 } 200 return(0); 201} 202 203int 204elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, 205 elf_lookup_fn lookup) 206{ 207 208 return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); 209} 210 211int 212elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, 213 int type, elf_lookup_fn lookup) 214{ 215 216 return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); 217} 218 219int 220elf_cpu_load_file(linker_file_t lf __unused) 221{ 222 223 cpu_idcache_wbinv_all(); 224 cpu_l2cache_wbinv_all(); 225 cpu_tlb_flushID(); 226 return (0); 227} 228 229int 230elf_cpu_unload_file(linker_file_t lf __unused) 231{ 232 233 return (0); 234} 235