elf_machdep.c revision 202046
1178172Simp/*- 2178172Simp * Copyright 1996-1998 John D. Polstra. 3178172Simp * All rights reserved. 4178172Simp * 5178172Simp * Redistribution and use in source and binary forms, with or without 6178172Simp * modification, are permitted provided that the following conditions 7178172Simp * are met: 8178172Simp * 1. Redistributions of source code must retain the above copyright 9178172Simp * notice, this list of conditions and the following disclaimer. 10178172Simp * 2. Redistributions in binary form must reproduce the above copyright 11178172Simp * notice, this list of conditions and the following disclaimer in the 12178172Simp * documentation and/or other materials provided with the distribution. 13178172Simp * 14178172Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15178172Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16178172Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17178172Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18178172Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19178172Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20178172Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21178172Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22178172Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23178172Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24178172Simp * 25178172Simp * from: src/sys/i386/i386/elf_machdep.c,v 1.20 2004/08/11 02:35:05 marcel 26178172Simp */ 27178172Simp 28178172Simp#include <sys/cdefs.h> 29178172Simp__FBSDID("$FreeBSD: head/sys/mips/mips/elf_machdep.c 202046 2010-01-10 20:29:20Z imp $"); 30178172Simp 31178172Simp#include <sys/param.h> 32178172Simp#include <sys/kernel.h> 33178172Simp#include <sys/systm.h> 34178172Simp#include <sys/exec.h> 35178172Simp#include <sys/imgact.h> 36178172Simp#include <sys/linker.h> 37178172Simp#include <sys/sysent.h> 38178172Simp#include <sys/imgact_elf.h> 39178172Simp#include <sys/syscall.h> 40178172Simp#include <sys/signalvar.h> 41178172Simp#include <sys/vnode.h> 42178172Simp 43178172Simp#include <vm/vm.h> 44178172Simp#include <vm/pmap.h> 45178172Simp#include <vm/vm_param.h> 46178172Simp 47178172Simp#include <machine/elf.h> 48178172Simp#include <machine/md_var.h> 49178172Simp 50202046Simp#ifdef __mips_n64 51202046Simpstruct sysentvec elf64_freebsd_sysvec = { 52202046Simp .sv_size = SYS_MAXSYSCALL, 53202046Simp .sv_table = sysent, 54202046Simp .sv_mask = 0, 55202046Simp .sv_sigsize = 0, 56202046Simp .sv_sigtbl = NULL, 57202046Simp .sv_errsize = 0, 58202046Simp .sv_errtbl = NULL, 59202046Simp .sv_transtrap = NULL, 60202046Simp .sv_fixup = __elfN(freebsd_fixup), 61202046Simp .sv_sendsig = sendsig, 62202046Simp .sv_sigcode = sigcode, 63202046Simp .sv_szsigcode = &szsigcode, 64202046Simp .sv_prepsyscall = NULL, 65202046Simp .sv_name = "FreeBSD ELF64", 66202046Simp .sv_coredump = __elfN(coredump), 67202046Simp .sv_imgact_try = NULL, 68202046Simp .sv_minsigstksz = MINSIGSTKSZ, 69202046Simp .sv_pagesize = PAGE_SIZE, 70202046Simp .sv_minuser = VM_MIN_ADDRESS, 71202046Simp .sv_maxuser = VM_MAXUSER_ADDRESS, 72202046Simp .sv_usrstack = USRSTACK, 73202046Simp .sv_psstrings = PS_STRINGS, 74202046Simp .sv_stackprot = VM_PROT_ALL, 75202046Simp .sv_copyout_strings = exec_copyout_strings, 76202046Simp .sv_setregs = exec_setregs, 77202046Simp .sv_fixlimit = NULL, 78202046Simp .sv_maxssiz = NULL, 79202046Simp .sv_flags = SV_ABI_FREEBSD | SV_LP64 80202046Simp}; 81202046Simp 82202046Simpstatic Elf64_Brandinfo freebsd_brand_info = { 83202046Simp .brand = ELFOSABI_FREEBSD, 84202046Simp .machine = EM_MIPS, 85202046Simp .compat_3_brand = "FreeBSD", 86202046Simp .emul_path = NULL, 87202046Simp .interp_path = "/libexec/ld-elf.so.1", 88202046Simp .sysvec = &elf64_freebsd_sysvec, 89202046Simp .interp_newpath = NULL, 90202046Simp .flags = 0 91202046Simp}; 92202046Simp 93202046SimpSYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY, 94202046Simp (sysinit_cfunc_t) elf64_insert_brand_entry, 95202046Simp &freebsd_brand_info); 96202046Simp 97202046Simpvoid 98202046Simpelf64_dump_thread(struct thread *td __unused, void *dst __unused, 99202046Simp size_t *off __unused) 100202046Simp{ 101202046Simp} 102202046Simp#else 103178172Simpstruct sysentvec elf32_freebsd_sysvec = { 104183322Skib .sv_size = SYS_MAXSYSCALL, 105183322Skib .sv_table = sysent, 106183322Skib .sv_mask = 0, 107183322Skib .sv_sigsize = 0, 108183322Skib .sv_sigtbl = NULL, 109183322Skib .sv_errsize = 0, 110183322Skib .sv_errtbl = NULL, 111183322Skib .sv_transtrap = NULL, 112183322Skib .sv_fixup = __elfN(freebsd_fixup), 113183322Skib .sv_sendsig = sendsig, 114183322Skib .sv_sigcode = sigcode, 115183322Skib .sv_szsigcode = &szsigcode, 116183322Skib .sv_prepsyscall = NULL, 117183322Skib .sv_name = "FreeBSD ELF32", 118183322Skib .sv_coredump = __elfN(coredump), 119183322Skib .sv_imgact_try = NULL, 120183322Skib .sv_minsigstksz = MINSIGSTKSZ, 121183322Skib .sv_pagesize = PAGE_SIZE, 122183322Skib .sv_minuser = VM_MIN_ADDRESS, 123183322Skib .sv_maxuser = VM_MAXUSER_ADDRESS, 124183322Skib .sv_usrstack = USRSTACK, 125183322Skib .sv_psstrings = PS_STRINGS, 126183322Skib .sv_stackprot = VM_PROT_ALL, 127183322Skib .sv_copyout_strings = exec_copyout_strings, 128183322Skib .sv_setregs = exec_setregs, 129183322Skib .sv_fixlimit = NULL, 130185169Skib .sv_maxssiz = NULL, 131185169Skib .sv_flags = SV_ABI_FREEBSD | SV_ILP32 132178172Simp}; 133178172Simp 134178172Simpstatic Elf32_Brandinfo freebsd_brand_info = { 135183322Skib .brand = ELFOSABI_FREEBSD, 136183322Skib .machine = EM_MIPS, 137183322Skib .compat_3_brand = "FreeBSD", 138183322Skib .emul_path = NULL, 139183322Skib .interp_path = "/libexec/ld-elf.so.1", 140183322Skib .sysvec = &elf32_freebsd_sysvec, 141183322Skib .interp_newpath = NULL, 142202046Simp .flags = 0 143183322Skib}; 144178172Simp 145197729SbzSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST, 146183322Skib (sysinit_cfunc_t) elf32_insert_brand_entry, 147183322Skib &freebsd_brand_info); 148178172Simp 149178172Simpvoid 150178172Simpelf32_dump_thread(struct thread *td __unused, void *dst __unused, 151178172Simp size_t *off __unused) 152178172Simp{ 153178172Simp} 154202046Simp#endif 155178172Simp 156178172Simp/* Process one elf relocation with addend. */ 157178172Simpstatic int 158178172Simpelf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, 159178172Simp int type, int local, elf_lookup_fn lookup) 160178172Simp{ 161202046Simp Elf_Addr *where = (Elf_Addr *)NULL;; 162178172Simp Elf_Addr addr; 163178172Simp Elf_Addr addend = (Elf_Addr)0; 164178172Simp Elf_Word rtype = (Elf_Word)0, symidx; 165178172Simp const Elf_Rel *rel; 166178172Simp const Elf_Rela *rela; 167178172Simp 168178172Simp switch (type) { 169178172Simp case ELF_RELOC_REL: 170178172Simp rel = (const Elf_Rel *)data; 171178172Simp where = (Elf_Addr *) (relocbase + rel->r_offset); 172178172Simp addend = *where; 173178172Simp rtype = ELF_R_TYPE(rel->r_info); 174178172Simp symidx = ELF_R_SYM(rel->r_info); 175178172Simp break; 176178172Simp case ELF_RELOC_RELA: 177178172Simp rela = (const Elf_Rela *)data; 178178172Simp where = (Elf_Addr *) (relocbase + rela->r_offset); 179178172Simp addend = rela->r_addend; 180178172Simp rtype = ELF_R_TYPE(rela->r_info); 181178172Simp symidx = ELF_R_SYM(rela->r_info); 182178172Simp break; 183178172Simp default: 184178172Simp panic("unknown reloc type %d\n", type); 185178172Simp } 186178172Simp 187178172Simp if (local) { 188178172Simp#if 0 /* TBD */ 189178172Simp if (rtype == R_386_RELATIVE) { /* A + B */ 190194784Sjeff addr = elf_relocaddr(lf, relocbase + addend); 191178172Simp if (*where != addr) 192178172Simp *where = addr; 193178172Simp } 194178172Simp return (0); 195178172Simp#endif 196178172Simp } 197178172Simp 198178172Simp switch (rtype) { 199178172Simp 200178172Simp case R_MIPS_NONE: /* none */ 201178172Simp break; 202178172Simp 203178172Simp case R_MIPS_16: /* S + sign-extend(A) */ 204178172Simp /* 205178172Simp * There shouldn't be R_MIPS_16 relocs in kernel objects. 206178172Simp */ 207178172Simp printf("kldload: unexpected R_MIPS_16 relocation\n"); 208178172Simp return -1; 209178172Simp break; 210178172Simp 211178172Simp case R_MIPS_32: /* S + A - P */ 212178172Simp addr = lookup(lf, symidx, 1); 213178172Simp if (addr == 0) 214178172Simp return -1; 215178172Simp addr += addend; 216178172Simp if (*where != addr) 217178172Simp *where = addr; 218178172Simp break; 219178172Simp 220178172Simp case R_MIPS_REL32: /* A - EA + S */ 221178172Simp /* 222178172Simp * There shouldn't be R_MIPS_REL32 relocs in kernel objects? 223178172Simp */ 224178172Simp printf("kldload: unexpected R_MIPS_REL32 relocation\n"); 225178172Simp return -1; 226178172Simp break; 227178172Simp 228178172Simp case R_MIPS_26: /* ((A << 2) | (P & 0xf0000000) + S) >> 2 */ 229178172Simp break; 230178172Simp 231178172Simp case R_MIPS_HI16: 232178172Simp /* extern/local: ((AHL + S) - ((short)(AHL + S)) >> 16 */ 233178172Simp /* _gp_disp: ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 */ 234178172Simp break; 235178172Simp 236178172Simp case R_MIPS_LO16: 237178172Simp /* extern/local: AHL + S */ 238178172Simp /* _gp_disp: AHL + GP - P + 4 */ 239178172Simp break; 240178172Simp 241178172Simp case R_MIPS_GPREL16: 242178172Simp /* extern/local: ((AHL + S) - ((short)(AHL + S)) >> 16 */ 243178172Simp /* _gp_disp: ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 */ 244178172Simp break; 245178172Simp 246178172Simp case R_MIPS_LITERAL: /* sign-extend(A) + L */ 247178172Simp break; 248178172Simp 249178172Simp case R_MIPS_GOT16: /* external: G */ 250178172Simp /* local: tbd */ 251178172Simp break; 252178172Simp 253178172Simp case R_MIPS_PC16: /* sign-extend(A) + S - P */ 254178172Simp break; 255178172Simp 256178172Simp case R_MIPS_CALL16: /* G */ 257178172Simp break; 258178172Simp 259178172Simp case R_MIPS_GPREL32: /* A + S + GP0 - GP */ 260178172Simp break; 261178172Simp 262178172Simp case R_MIPS_GOTHI16: /* (G - (short)G) >> 16 + A */ 263178172Simp break; 264178172Simp 265178172Simp case R_MIPS_GOTLO16: /* G & 0xffff */ 266178172Simp break; 267178172Simp 268178172Simp case R_MIPS_CALLHI16: /* (G - (short)G) >> 16 + A */ 269178172Simp break; 270178172Simp 271178172Simp case R_MIPS_CALLLO16: /* G & 0xffff */ 272178172Simp break; 273178172Simp 274178172Simp default: 275178172Simp printf("kldload: unexpected relocation type %d\n", 276178172Simp rtype); 277178172Simp return (-1); 278178172Simp } 279178172Simp return(0); 280178172Simp} 281178172Simp 282178172Simpint 283178172Simpelf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, 284178172Simp elf_lookup_fn lookup) 285178172Simp{ 286178172Simp 287178172Simp return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); 288178172Simp} 289178172Simp 290178172Simpint 291178172Simpelf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, 292178172Simp int type, elf_lookup_fn lookup) 293178172Simp{ 294178172Simp 295178172Simp return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); 296178172Simp} 297178172Simp 298178172Simpint 299178172Simpelf_cpu_load_file(linker_file_t lf __unused) 300178172Simp{ 301178172Simp 302178172Simp return (0); 303178172Simp} 304178172Simp 305178172Simpint 306178172Simpelf_cpu_unload_file(linker_file_t lf __unused) 307178172Simp{ 308178172Simp 309178172Simp return (0); 310178172Simp} 311