/*-1* Copyright (c) 2008-2010 Rui Paulo <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <sys/types.h>27#include <elf.h>28#include <bootstrap.h>2930#if defined(__aarch64__) || defined(__amd64__) || defined(__riscv)31#define ElfW_Rel Elf64_Rela32#define ElfW_Dyn Elf64_Dyn33#define ELFW_R_TYPE ELF64_R_TYPE34#define ELF_RELA35#elif defined(__arm__) || defined(__i386__)36#define ElfW_Rel Elf32_Rel37#define ElfW_Dyn Elf32_Dyn38#define ELFW_R_TYPE ELF32_R_TYPE39#else40#error architecture not supported41#endif42#if defined(__aarch64__)43#define RELOC_TYPE_NONE R_AARCH64_NONE44#define RELOC_TYPE_RELATIVE R_AARCH64_RELATIVE45#elif defined(__amd64__)46#define RELOC_TYPE_NONE R_X86_64_NONE47#define RELOC_TYPE_RELATIVE R_X86_64_RELATIVE48#elif defined(__arm__)49#define RELOC_TYPE_NONE R_ARM_NONE50#define RELOC_TYPE_RELATIVE R_ARM_RELATIVE51#elif defined(__i386__)52#define RELOC_TYPE_NONE R_386_NONE53#define RELOC_TYPE_RELATIVE R_386_RELATIVE54#elif defined(__riscv)55#define RELOC_TYPE_NONE R_RISCV_NONE56#define RELOC_TYPE_RELATIVE R_RISCV_RELATIVE57#endif5859void self_reloc(Elf_Addr baseaddr, ElfW_Dyn *dynamic);6061/*62* A simple elf relocator.63*/64void65self_reloc(Elf_Addr baseaddr, ElfW_Dyn *dynamic)66{67Elf_Word relsz, relent;68Elf_Addr *newaddr;69ElfW_Rel *rel;70ElfW_Dyn *dynp;7172/*73* Find the relocation address, its size and the relocation entry.74*/75relsz = 0;76relent = 0;77for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) {78switch (dynp->d_tag) {79case DT_REL:80case DT_RELA:81rel = (ElfW_Rel *)(dynp->d_un.d_ptr + baseaddr);82break;83case DT_RELSZ:84case DT_RELASZ:85relsz = dynp->d_un.d_val;86break;87case DT_RELENT:88case DT_RELAENT:89relent = dynp->d_un.d_val;90break;91default:92break;93}94}9596/*97* Perform the actual relocation. We rely on the object having been98* linked at 0, so that the difference between the load and link99* address is the same as the load address.100*/101for (; relsz > 0; relsz -= relent) {102switch (ELFW_R_TYPE(rel->r_info)) {103case RELOC_TYPE_NONE:104/* No relocation needs be performed. */105break;106107case RELOC_TYPE_RELATIVE:108newaddr = (Elf_Addr *)(rel->r_offset + baseaddr);109#ifdef ELF_RELA110/* Addend relative to the base address. */111*newaddr = baseaddr + rel->r_addend;112#else113/* Address relative to the base address. */114*newaddr += baseaddr;115#endif116break;117default:118/* XXX: do we need other relocations ? */119break;120}121rel = (ElfW_Rel *)(void *)((caddr_t) rel + relent);122}123}124125126