elf32_machdep.c revision 100384
1/*- 2 * Copyright 1996-1998 John D. Polstra. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * $FreeBSD: head/sys/powerpc/powerpc/elf_machdep.c 100384 2002-07-20 02:56:12Z peter $ 26 */ 27 28#include <sys/param.h> 29#include <sys/kernel.h> 30#include <sys/systm.h> 31#include <sys/malloc.h> 32#include <sys/proc.h> 33#include <sys/namei.h> 34#include <sys/fcntl.h> 35#include <sys/sysent.h> 36#include <sys/imgact_elf.h> 37#include <sys/syscall.h> 38#include <sys/signalvar.h> 39#include <sys/vnode.h> 40#include <sys/linker.h> 41#include <machine/elf.h> 42#include <machine/md_var.h> 43 44struct sysentvec elf32_freebsd_sysvec = { 45 SYS_MAXSYSCALL, 46 sysent, 47 0, 48 0, 49 0, 50 0, 51 0, 52 0, 53 elf32_freebsd_fixup, 54 sendsig, 55 sigcode, 56 &szsigcode, 57 0, 58 "FreeBSD ELF32", 59 __elfN(coredump), 60 NULL, 61 MINSIGSTKSZ 62}; 63 64static Elf32_Brandinfo freebsd_brand_info = { 65 ELFOSABI_FREEBSD, 66 EM_PPC, 67 "FreeBSD", 68 "", 69 "/usr/libexec/ld-elf.so.1", 70 &elf32_freebsd_sysvec 71 }; 72 73SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY, 74 (sysinit_cfunc_t) elf32_insert_brand_entry, 75 &freebsd_brand_info); 76 77/* Process one elf relocation with addend. */ 78int 79elf_reloc(linker_file_t lf, const void *data, int type) 80{ 81 Elf_Addr relocbase = (Elf_Addr) lf->address; 82 Elf_Addr *where; 83 Elf_Addr addr; 84 Elf_Addr addend; 85 Elf_Word rtype, symidx; 86 const Elf_Rel *rel; 87 const Elf_Rela *rela; 88 89 switch (type) { 90 case ELF_RELOC_REL: 91 rel = (const Elf_Rel *)data; 92 where = (Elf_Addr *) (relocbase + rel->r_offset); 93 addend = *where; 94 rtype = ELF_R_TYPE(rel->r_info); 95 symidx = ELF_R_SYM(rel->r_info); 96 break; 97 case ELF_RELOC_RELA: 98 rela = (const Elf_Rela *)data; 99 where = (Elf_Addr *) (relocbase + rela->r_offset); 100 addend = rela->r_addend; 101 rtype = ELF_R_TYPE(rela->r_info); 102 symidx = ELF_R_SYM(rela->r_info); 103 break; 104 default: 105 panic("elf_reloc: unknown relocation mode %d\n", type); 106 } 107 108 switch (rtype) { 109 110 case R_PPC_NONE: 111 break; 112 113 case R_PPC_GLOB_DAT: 114 addr = elf_lookup(lf, symidx, 1); 115 if (addr == 0) 116 return -1; 117 addr += addend; 118 if (*where != addr) 119 *where = addr; 120 break; 121 122 case R_PPC_JMP_SLOT: 123 /* No point in lazy binding for kernel modules. */ 124 addr = elf_lookup(lf, symidx, 1); 125 if (addr == 0) 126 return -1; 127 if (*where != addr) 128 *where = addr; 129 break; 130 131 case R_PPC_RELATIVE: 132 addr = relocbase + addend + *where; 133 if (*where != addr) 134 *where = addr; 135 break; 136 137 case R_PPC_COPY: 138 /* 139 * There shouldn't be copy relocations in kernel 140 * objects. 141 */ 142 printf("kldload: unexpected R_COPY relocation\n"); 143 return -1; 144 145 default: 146 printf("kldload: unexpected relocation type %d\n", 147 (int) rtype); 148 return -1; 149 } 150 return(0); 151} 152