1033f58dfSPeter Wemm /*- 2033f58dfSPeter Wemm * Copyright 1996-1998 John D. Polstra. 3033f58dfSPeter Wemm * All rights reserved. 4033f58dfSPeter Wemm * 5033f58dfSPeter Wemm * Redistribution and use in source and binary forms, with or without 6033f58dfSPeter Wemm * modification, are permitted provided that the following conditions 7033f58dfSPeter Wemm * are met: 8033f58dfSPeter Wemm * 1. Redistributions of source code must retain the above copyright 9033f58dfSPeter Wemm * notice, this list of conditions and the following disclaimer. 10033f58dfSPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 11033f58dfSPeter Wemm * notice, this list of conditions and the following disclaimer in the 12033f58dfSPeter Wemm * documentation and/or other materials provided with the distribution. 13033f58dfSPeter Wemm * 14033f58dfSPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15033f58dfSPeter Wemm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16033f58dfSPeter Wemm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17033f58dfSPeter Wemm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18033f58dfSPeter Wemm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19033f58dfSPeter Wemm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20033f58dfSPeter Wemm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21033f58dfSPeter Wemm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22033f58dfSPeter Wemm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23033f58dfSPeter Wemm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24033f58dfSPeter Wemm * 25f1d19042SArchie Cobbs * $Id: elf_machdep.c,v 1.3 1998/10/16 03:54:59 peter Exp $ 26033f58dfSPeter Wemm */ 27033f58dfSPeter Wemm 28033f58dfSPeter Wemm #include <sys/param.h> 29033f58dfSPeter Wemm #include <sys/kernel.h> 30033f58dfSPeter Wemm #include <sys/systm.h> 31033f58dfSPeter Wemm #include <sys/malloc.h> 32033f58dfSPeter Wemm #include <sys/proc.h> 33033f58dfSPeter Wemm #include <sys/namei.h> 34033f58dfSPeter Wemm #include <sys/fcntl.h> 35033f58dfSPeter Wemm #include <sys/vnode.h> 36033f58dfSPeter Wemm #include <sys/linker.h> 37033f58dfSPeter Wemm #include <machine/elf.h> 38033f58dfSPeter Wemm 39bde362f5SPeter Wemm /* Process one elf relocation with addend. */ 40033f58dfSPeter Wemm int 41aa855a59SPeter Wemm elf_reloc(linker_file_t lf, const void *data, int type, const char *sym) 42033f58dfSPeter Wemm { 43033f58dfSPeter Wemm Elf_Addr relocbase = (Elf_Addr) lf->address; 44aa855a59SPeter Wemm Elf_Addr *where; 45f1d19042SArchie Cobbs Elf_Addr addr; 46aa855a59SPeter Wemm Elf_Addr addend; 47aa855a59SPeter Wemm Elf_Word rtype; 48aa855a59SPeter Wemm const Elf_Rel *rel; 49aa855a59SPeter Wemm const Elf_Rela *rela; 50033f58dfSPeter Wemm 51aa855a59SPeter Wemm switch (type) { 52aa855a59SPeter Wemm case ELF_RELOC_REL: 53aa855a59SPeter Wemm rel = (Elf_Rel *)data; 54aa855a59SPeter Wemm where = (Elf_Addr *) (relocbase + rel->r_offset); 55aa855a59SPeter Wemm addend = *where; 56aa855a59SPeter Wemm rtype = ELF_R_TYPE(rel->r_info); 57aa855a59SPeter Wemm break; 58aa855a59SPeter Wemm case ELF_RELOC_RELA: 59aa855a59SPeter Wemm rela = (Elf_Rela *)data; 60aa855a59SPeter Wemm where = (Elf_Addr *) (relocbase + rela->r_offset); 61aa855a59SPeter Wemm addend = rela->r_addend; 62aa855a59SPeter Wemm rtype = ELF_R_TYPE(rela->r_info); 63aa855a59SPeter Wemm break; 64aa855a59SPeter Wemm default: 65aa855a59SPeter Wemm panic("unknown reloc type %d\n", type); 66aa855a59SPeter Wemm } 67033f58dfSPeter Wemm 68aa855a59SPeter Wemm switch (rtype) { 69aa855a59SPeter Wemm 70aa855a59SPeter Wemm case R_386_NONE: /* none */ 71033f58dfSPeter Wemm break; 72033f58dfSPeter Wemm 73aa855a59SPeter Wemm case R_386_32: /* S + A */ 74aa855a59SPeter Wemm if (sym == NULL) 75aa855a59SPeter Wemm return -1; 76033f58dfSPeter Wemm addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1); 77033f58dfSPeter Wemm if (addr == NULL) 78033f58dfSPeter Wemm return -1; 79aa855a59SPeter Wemm addr += addend; 80033f58dfSPeter Wemm if (*where != addr) 81033f58dfSPeter Wemm *where = addr; 82033f58dfSPeter Wemm break; 83033f58dfSPeter Wemm 84aa855a59SPeter Wemm case R_386_PC32: /* S + A - P */ 85aa855a59SPeter Wemm if (sym == NULL) 86aa855a59SPeter Wemm return -1; 87033f58dfSPeter Wemm addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1); 88033f58dfSPeter Wemm if (addr == NULL) 89033f58dfSPeter Wemm return -1; 90aa855a59SPeter Wemm addr += addend - (Elf_Addr)where; 91033f58dfSPeter Wemm if (*where != addr) 92033f58dfSPeter Wemm *where = addr; 93033f58dfSPeter Wemm break; 94033f58dfSPeter Wemm 95aa855a59SPeter Wemm case R_386_COPY: /* none */ 96033f58dfSPeter Wemm /* 97033f58dfSPeter Wemm * There shouldn't be copy relocations in kernel 98033f58dfSPeter Wemm * objects. 99033f58dfSPeter Wemm */ 100033f58dfSPeter Wemm printf("kldload: unexpected R_COPY relocation\n"); 101033f58dfSPeter Wemm return -1; 102033f58dfSPeter Wemm break; 103033f58dfSPeter Wemm 104aa855a59SPeter Wemm case R_386_GLOB_DAT: /* S */ 105aa855a59SPeter Wemm if (sym == NULL) 106aa855a59SPeter Wemm return -1; 107033f58dfSPeter Wemm addr = (Elf_Addr)linker_file_lookup_symbol(lf, sym, 1); 108033f58dfSPeter Wemm if (addr == NULL) 109033f58dfSPeter Wemm return -1; 110033f58dfSPeter Wemm if (*where != addr) 111033f58dfSPeter Wemm *where = addr; 112033f58dfSPeter Wemm break; 113033f58dfSPeter Wemm 114aa855a59SPeter Wemm case R_386_RELATIVE: /* B + A */ 115aa855a59SPeter Wemm addr = relocbase + addend; 116aa855a59SPeter Wemm if (*where != addr) 117aa855a59SPeter Wemm *where = addr; 118033f58dfSPeter Wemm break; 119033f58dfSPeter Wemm 120033f58dfSPeter Wemm default: 121033f58dfSPeter Wemm printf("kldload: unexpected relocation type %d\n", 122aa855a59SPeter Wemm rtype); 123033f58dfSPeter Wemm return -1; 124033f58dfSPeter Wemm } 125033f58dfSPeter Wemm return(0); 126033f58dfSPeter Wemm } 127