elf_machdep.c revision 178172
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 178172 2008-04-13 07:27:37Z 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 50178172Simpstruct sysentvec elf32_freebsd_sysvec = { 51178172Simp SYS_MAXSYSCALL, 52178172Simp sysent, 53178172Simp 0, 54178172Simp 0, 55178172Simp NULL, 56178172Simp 0, 57178172Simp NULL, 58178172Simp NULL, 59178172Simp __elfN(freebsd_fixup), 60178172Simp sendsig, 61178172Simp sigcode, 62178172Simp &szsigcode, 63178172Simp NULL, 64178172Simp "FreeBSD ELF32", 65178172Simp __elfN(coredump), 66178172Simp NULL, 67178172Simp MINSIGSTKSZ, 68178172Simp PAGE_SIZE, 69178172Simp VM_MIN_ADDRESS, 70178172Simp VM_MAXUSER_ADDRESS, 71178172Simp USRSTACK, 72178172Simp PS_STRINGS, 73178172Simp VM_PROT_ALL, 74178172Simp exec_copyout_strings, 75178172Simp exec_setregs, 76178172Simp NULL 77178172Simp}; 78178172Simp 79178172Simpstatic Elf32_Brandinfo freebsd_brand_info = { 80178172Simp ELFOSABI_FREEBSD, 81178172Simp EM_MIPS, 82178172Simp "FreeBSD", 83178172Simp NULL, 84178172Simp "/libexec/ld-elf.so.1", 85178172Simp &elf32_freebsd_sysvec, 86178172Simp NULL, 87178172Simp }; 88178172Simp 89178172SimpSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY, 90178172Simp (sysinit_cfunc_t) elf32_insert_brand_entry, 91178172Simp &freebsd_brand_info); 92178172Simp 93178172Simpstatic Elf32_Brandinfo freebsd_brand_oinfo = { 94178172Simp ELFOSABI_FREEBSD, 95178172Simp EM_MIPS, 96178172Simp "FreeBSD", 97178172Simp NULL, 98178172Simp "/usr/libexec/ld-elf.so.1", 99178172Simp &elf32_freebsd_sysvec, 100178172Simp NULL, 101178172Simp }; 102178172Simp 103178172SimpSYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY, 104178172Simp (sysinit_cfunc_t) elf32_insert_brand_entry, 105178172Simp &freebsd_brand_oinfo); 106178172Simp 107178172Simp 108178172Simpvoid 109178172Simpelf32_dump_thread(struct thread *td __unused, void *dst __unused, 110178172Simp size_t *off __unused) 111178172Simp{ 112178172Simp} 113178172Simp 114178172Simp/* Process one elf relocation with addend. */ 115178172Simpstatic int 116178172Simpelf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, 117178172Simp int type, int local, elf_lookup_fn lookup) 118178172Simp{ 119178172Simp Elf_Addr *where = (Elf_Addr *)NULL;; 120178172Simp Elf_Addr addr; 121178172Simp Elf_Addr addend = (Elf_Addr)0; 122178172Simp Elf_Word rtype = (Elf_Word)0, symidx; 123178172Simp const Elf_Rel *rel; 124178172Simp const Elf_Rela *rela; 125178172Simp 126178172Simp switch (type) { 127178172Simp case ELF_RELOC_REL: 128178172Simp rel = (const Elf_Rel *)data; 129178172Simp where = (Elf_Addr *) (relocbase + rel->r_offset); 130178172Simp addend = *where; 131178172Simp rtype = ELF_R_TYPE(rel->r_info); 132178172Simp symidx = ELF_R_SYM(rel->r_info); 133178172Simp break; 134178172Simp case ELF_RELOC_RELA: 135178172Simp rela = (const Elf_Rela *)data; 136178172Simp where = (Elf_Addr *) (relocbase + rela->r_offset); 137178172Simp addend = rela->r_addend; 138178172Simp rtype = ELF_R_TYPE(rela->r_info); 139178172Simp symidx = ELF_R_SYM(rela->r_info); 140178172Simp break; 141178172Simp default: 142178172Simp panic("unknown reloc type %d\n", type); 143178172Simp } 144178172Simp 145178172Simp if (local) { 146178172Simp#if 0 /* TBD */ 147178172Simp if (rtype == R_386_RELATIVE) { /* A + B */ 148178172Simp addr = relocbase + addend; 149178172Simp if (*where != addr) 150178172Simp *where = addr; 151178172Simp } 152178172Simp return (0); 153178172Simp#endif 154178172Simp } 155178172Simp 156178172Simp switch (rtype) { 157178172Simp 158178172Simp case R_MIPS_NONE: /* none */ 159178172Simp break; 160178172Simp 161178172Simp case R_MIPS_16: /* S + sign-extend(A) */ 162178172Simp /* 163178172Simp * There shouldn't be R_MIPS_16 relocs in kernel objects. 164178172Simp */ 165178172Simp printf("kldload: unexpected R_MIPS_16 relocation\n"); 166178172Simp return -1; 167178172Simp break; 168178172Simp 169178172Simp case R_MIPS_32: /* S + A - P */ 170178172Simp addr = lookup(lf, symidx, 1); 171178172Simp if (addr == 0) 172178172Simp return -1; 173178172Simp addr += addend; 174178172Simp if (*where != addr) 175178172Simp *where = addr; 176178172Simp break; 177178172Simp 178178172Simp case R_MIPS_REL32: /* A - EA + S */ 179178172Simp /* 180178172Simp * There shouldn't be R_MIPS_REL32 relocs in kernel objects? 181178172Simp */ 182178172Simp printf("kldload: unexpected R_MIPS_REL32 relocation\n"); 183178172Simp return -1; 184178172Simp break; 185178172Simp 186178172Simp case R_MIPS_26: /* ((A << 2) | (P & 0xf0000000) + S) >> 2 */ 187178172Simp break; 188178172Simp 189178172Simp case R_MIPS_HI16: 190178172Simp /* extern/local: ((AHL + S) - ((short)(AHL + S)) >> 16 */ 191178172Simp /* _gp_disp: ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 */ 192178172Simp break; 193178172Simp 194178172Simp case R_MIPS_LO16: 195178172Simp /* extern/local: AHL + S */ 196178172Simp /* _gp_disp: AHL + GP - P + 4 */ 197178172Simp break; 198178172Simp 199178172Simp case R_MIPS_GPREL16: 200178172Simp /* extern/local: ((AHL + S) - ((short)(AHL + S)) >> 16 */ 201178172Simp /* _gp_disp: ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 */ 202178172Simp break; 203178172Simp 204178172Simp case R_MIPS_LITERAL: /* sign-extend(A) + L */ 205178172Simp break; 206178172Simp 207178172Simp case R_MIPS_GOT16: /* external: G */ 208178172Simp /* local: tbd */ 209178172Simp break; 210178172Simp 211178172Simp case R_MIPS_PC16: /* sign-extend(A) + S - P */ 212178172Simp break; 213178172Simp 214178172Simp case R_MIPS_CALL16: /* G */ 215178172Simp break; 216178172Simp 217178172Simp case R_MIPS_GPREL32: /* A + S + GP0 - GP */ 218178172Simp break; 219178172Simp 220178172Simp case R_MIPS_GOTHI16: /* (G - (short)G) >> 16 + A */ 221178172Simp break; 222178172Simp 223178172Simp case R_MIPS_GOTLO16: /* G & 0xffff */ 224178172Simp break; 225178172Simp 226178172Simp case R_MIPS_CALLHI16: /* (G - (short)G) >> 16 + A */ 227178172Simp break; 228178172Simp 229178172Simp case R_MIPS_CALLLO16: /* G & 0xffff */ 230178172Simp break; 231178172Simp 232178172Simp default: 233178172Simp printf("kldload: unexpected relocation type %d\n", 234178172Simp rtype); 235178172Simp return (-1); 236178172Simp } 237178172Simp return(0); 238178172Simp} 239178172Simp 240178172Simpint 241178172Simpelf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, 242178172Simp elf_lookup_fn lookup) 243178172Simp{ 244178172Simp 245178172Simp return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); 246178172Simp} 247178172Simp 248178172Simpint 249178172Simpelf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, 250178172Simp int type, elf_lookup_fn lookup) 251178172Simp{ 252178172Simp 253178172Simp return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); 254178172Simp} 255178172Simp 256178172Simpint 257178172Simpelf_cpu_load_file(linker_file_t lf __unused) 258178172Simp{ 259178172Simp 260178172Simp return (0); 261178172Simp} 262178172Simp 263178172Simpint 264178172Simpelf_cpu_unload_file(linker_file_t lf __unused) 265178172Simp{ 266178172Simp 267178172Simp return (0); 268178172Simp} 269