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 * 25c3aac50fSPeter Wemm * $FreeBSD$ 26033f58dfSPeter Wemm */ 27033f58dfSPeter Wemm 28033f58dfSPeter Wemm #include <sys/param.h> 293ebc1248SPeter Wemm #include <sys/kernel.h> 30033f58dfSPeter Wemm #include <sys/systm.h> 31033f58dfSPeter Wemm #include <sys/linker.h> 323ebc1248SPeter Wemm #include <sys/sysent.h> 333ebc1248SPeter Wemm #include <sys/imgact_elf.h> 343ebc1248SPeter Wemm #include <sys/syscall.h> 353ebc1248SPeter Wemm #include <sys/signalvar.h> 363ebc1248SPeter Wemm #include <sys/vnode.h> 37033f58dfSPeter Wemm #include <machine/elf.h> 383ebc1248SPeter Wemm #include <machine/md_var.h> 393ebc1248SPeter Wemm 403ebc1248SPeter Wemm struct sysentvec elf32_freebsd_sysvec = { 413ebc1248SPeter Wemm SYS_MAXSYSCALL, 423ebc1248SPeter Wemm sysent, 433ebc1248SPeter Wemm 0, 443ebc1248SPeter Wemm 0, 453ebc1248SPeter Wemm 0, 463ebc1248SPeter Wemm 0, 473ebc1248SPeter Wemm 0, 483ebc1248SPeter Wemm 0, 493ebc1248SPeter Wemm elf32_freebsd_fixup, 503ebc1248SPeter Wemm sendsig, 513ebc1248SPeter Wemm sigcode, 523ebc1248SPeter Wemm &szsigcode, 533ebc1248SPeter Wemm 0, 543ebc1248SPeter Wemm "FreeBSD ELF32", 553ebc1248SPeter Wemm __elfN(coredump), 563ebc1248SPeter Wemm NULL, 573ebc1248SPeter Wemm MINSIGSTKSZ 583ebc1248SPeter Wemm }; 593ebc1248SPeter Wemm 603ebc1248SPeter Wemm static Elf32_Brandinfo freebsd_brand_info = { 613ebc1248SPeter Wemm ELFOSABI_FREEBSD, 623ebc1248SPeter Wemm EM_386, 633ebc1248SPeter Wemm "FreeBSD", 643ebc1248SPeter Wemm "", 653ebc1248SPeter Wemm "/usr/libexec/ld-elf.so.1", 663ebc1248SPeter Wemm &elf32_freebsd_sysvec 673ebc1248SPeter Wemm }; 683ebc1248SPeter Wemm 693ebc1248SPeter Wemm SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY, 703ebc1248SPeter Wemm (sysinit_cfunc_t) elf32_insert_brand_entry, 713ebc1248SPeter Wemm &freebsd_brand_info); 72033f58dfSPeter Wemm 73bde362f5SPeter Wemm /* Process one elf relocation with addend. */ 74033f58dfSPeter Wemm int 75d297ad16SMarcel Moolenaar elf_reloc(linker_file_t lf, const void *data, int type) 76033f58dfSPeter Wemm { 77033f58dfSPeter Wemm Elf_Addr relocbase = (Elf_Addr) lf->address; 78aa855a59SPeter Wemm Elf_Addr *where; 79f1d19042SArchie Cobbs Elf_Addr addr; 80aa855a59SPeter Wemm Elf_Addr addend; 81d297ad16SMarcel Moolenaar Elf_Word rtype, symidx; 82aa855a59SPeter Wemm const Elf_Rel *rel; 83aa855a59SPeter Wemm const Elf_Rela *rela; 84033f58dfSPeter Wemm 85aa855a59SPeter Wemm switch (type) { 86aa855a59SPeter Wemm case ELF_RELOC_REL: 870a5e03ddSMatthew Dillon rel = (const Elf_Rel *)data; 88aa855a59SPeter Wemm where = (Elf_Addr *) (relocbase + rel->r_offset); 89aa855a59SPeter Wemm addend = *where; 90aa855a59SPeter Wemm rtype = ELF_R_TYPE(rel->r_info); 91d297ad16SMarcel Moolenaar symidx = ELF_R_SYM(rel->r_info); 92aa855a59SPeter Wemm break; 93aa855a59SPeter Wemm case ELF_RELOC_RELA: 940a5e03ddSMatthew Dillon rela = (const Elf_Rela *)data; 95aa855a59SPeter Wemm where = (Elf_Addr *) (relocbase + rela->r_offset); 96aa855a59SPeter Wemm addend = rela->r_addend; 97aa855a59SPeter Wemm rtype = ELF_R_TYPE(rela->r_info); 98d297ad16SMarcel Moolenaar symidx = ELF_R_SYM(rela->r_info); 99aa855a59SPeter Wemm break; 100aa855a59SPeter Wemm default: 101aa855a59SPeter Wemm panic("unknown reloc type %d\n", type); 102aa855a59SPeter Wemm } 103033f58dfSPeter Wemm 104aa855a59SPeter Wemm switch (rtype) { 105aa855a59SPeter Wemm 106aa855a59SPeter Wemm case R_386_NONE: /* none */ 107033f58dfSPeter Wemm break; 108033f58dfSPeter Wemm 109aa855a59SPeter Wemm case R_386_32: /* S + A */ 110d297ad16SMarcel Moolenaar addr = elf_lookup(lf, symidx, 1); 111369dc8ceSEivind Eklund if (addr == 0) 112033f58dfSPeter Wemm return -1; 113aa855a59SPeter Wemm addr += addend; 114033f58dfSPeter Wemm if (*where != addr) 115033f58dfSPeter Wemm *where = addr; 116033f58dfSPeter Wemm break; 117033f58dfSPeter Wemm 118aa855a59SPeter Wemm case R_386_PC32: /* S + A - P */ 119d297ad16SMarcel Moolenaar addr = elf_lookup(lf, symidx, 1); 120369dc8ceSEivind Eklund if (addr == 0) 121033f58dfSPeter Wemm return -1; 122aa855a59SPeter Wemm addr += addend - (Elf_Addr)where; 123033f58dfSPeter Wemm if (*where != addr) 124033f58dfSPeter Wemm *where = addr; 125033f58dfSPeter Wemm break; 126033f58dfSPeter Wemm 127aa855a59SPeter Wemm case R_386_COPY: /* none */ 128033f58dfSPeter Wemm /* 129033f58dfSPeter Wemm * There shouldn't be copy relocations in kernel 130033f58dfSPeter Wemm * objects. 131033f58dfSPeter Wemm */ 132033f58dfSPeter Wemm printf("kldload: unexpected R_COPY relocation\n"); 133033f58dfSPeter Wemm return -1; 134033f58dfSPeter Wemm break; 135033f58dfSPeter Wemm 136aa855a59SPeter Wemm case R_386_GLOB_DAT: /* S */ 137d297ad16SMarcel Moolenaar addr = elf_lookup(lf, symidx, 1); 138369dc8ceSEivind Eklund if (addr == 0) 139033f58dfSPeter Wemm return -1; 140033f58dfSPeter Wemm if (*where != addr) 141033f58dfSPeter Wemm *where = addr; 142033f58dfSPeter Wemm break; 143033f58dfSPeter Wemm 144aa855a59SPeter Wemm case R_386_RELATIVE: /* B + A */ 145aa855a59SPeter Wemm addr = relocbase + addend; 146aa855a59SPeter Wemm if (*where != addr) 147aa855a59SPeter Wemm *where = addr; 148033f58dfSPeter Wemm break; 149033f58dfSPeter Wemm 150033f58dfSPeter Wemm default: 151033f58dfSPeter Wemm printf("kldload: unexpected relocation type %d\n", 152aa855a59SPeter Wemm rtype); 153033f58dfSPeter Wemm return -1; 154033f58dfSPeter Wemm } 155033f58dfSPeter Wemm return(0); 156033f58dfSPeter Wemm } 157