1 1.1 nonaka /* $NetBSD: self_reloc.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ 2 1.1 nonaka 3 1.1 nonaka /*- 4 1.1 nonaka * Copyright (c) 2008-2010 Rui Paulo <rpaulo (at) FreeBSD.org> 5 1.1 nonaka * All rights reserved. 6 1.1 nonaka * 7 1.1 nonaka * Redistribution and use in source and binary forms, with or without 8 1.1 nonaka * modification, are permitted provided that the following conditions 9 1.1 nonaka * are met: 10 1.1 nonaka * 1. Redistributions of source code must retain the above copyright 11 1.1 nonaka * notice, this list of conditions and the following disclaimer. 12 1.1 nonaka * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 nonaka * notice, this list of conditions and the following disclaimer in the 14 1.1 nonaka * documentation and/or other materials provided with the distribution. 15 1.1 nonaka * 16 1.1 nonaka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 1.1 nonaka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.1 nonaka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 nonaka * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 1.1 nonaka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 nonaka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.1 nonaka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 nonaka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.1 nonaka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 nonaka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 nonaka * SUCH DAMAGE. 27 1.1 nonaka */ 28 1.1 nonaka 29 1.1 nonaka #include <sys/types.h> 30 1.1 nonaka #include <sys/exec_elf.h> 31 1.1 nonaka 32 1.1 nonaka #include <efi.h> 33 1.1 nonaka 34 1.1 nonaka void self_reloc(Elf_Addr, Elf_Dyn *); 35 1.1 nonaka 36 1.1 nonaka #if defined(__aarch64__) 37 1.1 nonaka #define USE_RELA 38 1.1 nonaka #endif 39 1.1 nonaka 40 1.1 nonaka /* 41 1.1 nonaka * A simple elf relocator. 42 1.1 nonaka */ 43 1.1 nonaka void 44 1.1 nonaka self_reloc(Elf_Addr baseaddr, Elf_Dyn *dynamic) 45 1.1 nonaka { 46 1.1 nonaka Elf_Word relsz, relent; 47 1.1 nonaka Elf_Addr *newaddr; 48 1.1 nonaka Elf_Rel *rel = NULL; 49 1.1 nonaka Elf_Dyn *dynp; 50 1.1 nonaka 51 1.1 nonaka /* 52 1.1 nonaka * Find the relocation address, its size and the relocation entry. 53 1.1 nonaka */ 54 1.1 nonaka relsz = 0; 55 1.1 nonaka relent = 0; 56 1.1 nonaka for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) { 57 1.1 nonaka switch (dynp->d_tag) { 58 1.1 nonaka case DT_REL: 59 1.1 nonaka case DT_RELA: 60 1.1 nonaka rel = (Elf_Rel *)(dynp->d_un.d_ptr + baseaddr); 61 1.1 nonaka break; 62 1.1 nonaka case DT_RELSZ: 63 1.1 nonaka case DT_RELASZ: 64 1.1 nonaka relsz = dynp->d_un.d_val; 65 1.1 nonaka break; 66 1.1 nonaka case DT_RELENT: 67 1.1 nonaka case DT_RELAENT: 68 1.1 nonaka relent = dynp->d_un.d_val; 69 1.1 nonaka break; 70 1.1 nonaka default: 71 1.1 nonaka break; 72 1.1 nonaka } 73 1.1 nonaka } 74 1.1 nonaka 75 1.1 nonaka /* 76 1.1 nonaka * Perform the actual relocation. 77 1.1 nonaka */ 78 1.1 nonaka for (; relsz > 0; relsz -= relent) { 79 1.1 nonaka switch (ELF_R_TYPE(rel->r_info)) { 80 1.1 nonaka case R_TYPE(NONE): 81 1.1 nonaka /* No relocation needs be performed. */ 82 1.1 nonaka break; 83 1.1 nonaka 84 1.1 nonaka case R_TYPE(RELATIVE): 85 1.1 nonaka /* Address relative to the base address. */ 86 1.1 nonaka newaddr = (Elf_Addr *)(rel->r_offset + baseaddr); 87 1.1 nonaka *newaddr += baseaddr; 88 1.1 nonaka #ifdef USE_RELA 89 1.1 nonaka /* Add the addend when the ABI uses them */ 90 1.1 nonaka *newaddr += ((Elf_Rela *)rel)->r_addend; 91 1.1 nonaka #endif 92 1.1 nonaka break; 93 1.1 nonaka default: 94 1.1 nonaka /* XXX: do we need other relocations ? */ 95 1.1 nonaka break; 96 1.1 nonaka } 97 1.1 nonaka rel = (Elf_Rel *) ((char *) rel + relent); 98 1.1 nonaka } 99 1.1 nonaka } 100