14a5d661aSToomas Soome /*- 24a5d661aSToomas Soome * Copyright (c) 2008-2010 Rui Paulo <rpaulo@FreeBSD.org> 34a5d661aSToomas Soome * All rights reserved. 44a5d661aSToomas Soome * 54a5d661aSToomas Soome * Redistribution and use in source and binary forms, with or without 64a5d661aSToomas Soome * modification, are permitted provided that the following conditions 74a5d661aSToomas Soome * are met: 84a5d661aSToomas Soome * 1. Redistributions of source code must retain the above copyright 94a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer. 104a5d661aSToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 114a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer in the 124a5d661aSToomas Soome * documentation and/or other materials provided with the distribution. 134a5d661aSToomas Soome * 144a5d661aSToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 154a5d661aSToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 164a5d661aSToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 174a5d661aSToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 184a5d661aSToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 194a5d661aSToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 204a5d661aSToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 214a5d661aSToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 224a5d661aSToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 234a5d661aSToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 244a5d661aSToomas Soome * SUCH DAMAGE. 254a5d661aSToomas Soome */ 264a5d661aSToomas Soome 274a5d661aSToomas Soome #include <sys/cdefs.h> 284a5d661aSToomas Soome 294a5d661aSToomas Soome #include <sys/types.h> 304a5d661aSToomas Soome #include <elf.h> 314a5d661aSToomas Soome #include <bootstrap.h> 324a5d661aSToomas Soome 33*d76811beSToomas Soome #if defined(__aarch64__) || defined(__amd64__) 344a5d661aSToomas Soome #define ElfW_Rel Elf64_Rela 354a5d661aSToomas Soome #define ElfW_Dyn Elf64_Dyn 364a5d661aSToomas Soome #define ELFW_R_TYPE ELF64_R_TYPE 374a5d661aSToomas Soome #define ELF_RELA 384a5d661aSToomas Soome #elif defined(__arm__) || defined(__i386__) 394a5d661aSToomas Soome #define ElfW_Rel Elf32_Rel 404a5d661aSToomas Soome #define ElfW_Dyn Elf32_Dyn 414a5d661aSToomas Soome #define ELFW_R_TYPE ELF32_R_TYPE 424a5d661aSToomas Soome #else 434a5d661aSToomas Soome #error architecture not supported 444a5d661aSToomas Soome #endif 454a5d661aSToomas Soome #if defined(__aarch64__) 464a5d661aSToomas Soome #define RELOC_TYPE_NONE R_AARCH64_NONE 474a5d661aSToomas Soome #define RELOC_TYPE_RELATIVE R_AARCH64_RELATIVE 484a5d661aSToomas Soome #elif defined(__amd64__) 494a5d661aSToomas Soome #define RELOC_TYPE_NONE R_X86_64_NONE 504a5d661aSToomas Soome #define RELOC_TYPE_RELATIVE R_X86_64_RELATIVE 514a5d661aSToomas Soome #elif defined(__arm__) 524a5d661aSToomas Soome #define RELOC_TYPE_NONE R_ARM_NONE 534a5d661aSToomas Soome #define RELOC_TYPE_RELATIVE R_ARM_RELATIVE 544a5d661aSToomas Soome #elif defined(__i386__) 554a5d661aSToomas Soome #define RELOC_TYPE_NONE R_386_NONE 564a5d661aSToomas Soome #define RELOC_TYPE_RELATIVE R_386_RELATIVE 574a5d661aSToomas Soome #endif 584a5d661aSToomas Soome 594a5d661aSToomas Soome void self_reloc(Elf_Addr baseaddr, ElfW_Dyn *dynamic); 604a5d661aSToomas Soome 614a5d661aSToomas Soome /* 624a5d661aSToomas Soome * A simple elf relocator. 634a5d661aSToomas Soome */ 644a5d661aSToomas Soome void 654a5d661aSToomas Soome self_reloc(Elf_Addr baseaddr, ElfW_Dyn *dynamic) 664a5d661aSToomas Soome { 674a5d661aSToomas Soome Elf_Word relsz, relent; 684a5d661aSToomas Soome Elf_Addr *newaddr; 694a5d661aSToomas Soome ElfW_Rel *rel = 0; 704a5d661aSToomas Soome ElfW_Dyn *dynp; 714a5d661aSToomas Soome 724a5d661aSToomas Soome /* 734a5d661aSToomas Soome * Find the relocation address, its size and the relocation entry. 744a5d661aSToomas Soome */ 754a5d661aSToomas Soome relsz = 0; 764a5d661aSToomas Soome relent = 0; 774a5d661aSToomas Soome for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) { 784a5d661aSToomas Soome switch (dynp->d_tag) { 794a5d661aSToomas Soome case DT_REL: 804a5d661aSToomas Soome case DT_RELA: 814a5d661aSToomas Soome rel = (ElfW_Rel *)(dynp->d_un.d_ptr + baseaddr); 824a5d661aSToomas Soome break; 834a5d661aSToomas Soome case DT_RELSZ: 844a5d661aSToomas Soome case DT_RELASZ: 854a5d661aSToomas Soome relsz = dynp->d_un.d_val; 864a5d661aSToomas Soome break; 874a5d661aSToomas Soome case DT_RELENT: 884a5d661aSToomas Soome case DT_RELAENT: 894a5d661aSToomas Soome relent = dynp->d_un.d_val; 904a5d661aSToomas Soome break; 914a5d661aSToomas Soome default: 924a5d661aSToomas Soome break; 934a5d661aSToomas Soome } 944a5d661aSToomas Soome } 954a5d661aSToomas Soome 964a5d661aSToomas Soome /* 97*d76811beSToomas Soome * Perform the actual relocation. We rely on the object having been 98*d76811beSToomas Soome * linked at 0, so that the difference between the load and link 99*d76811beSToomas Soome * address is the same as the load address. 1004a5d661aSToomas Soome */ 1014a5d661aSToomas Soome for (; relsz > 0; relsz -= relent) { 1024a5d661aSToomas Soome switch (ELFW_R_TYPE(rel->r_info)) { 1034a5d661aSToomas Soome case RELOC_TYPE_NONE: 1044a5d661aSToomas Soome /* No relocation needs be performed. */ 1054a5d661aSToomas Soome break; 1064a5d661aSToomas Soome 1074a5d661aSToomas Soome case RELOC_TYPE_RELATIVE: 1084a5d661aSToomas Soome newaddr = (Elf_Addr *)(rel->r_offset + baseaddr); 1094a5d661aSToomas Soome #ifdef ELF_RELA 110*d76811beSToomas Soome /* Addend relative to the base address. */ 111*d76811beSToomas Soome *newaddr = baseaddr + rel->r_addend; 112*d76811beSToomas Soome #else 113*d76811beSToomas Soome /* Address relative to the base address. */ 114*d76811beSToomas Soome *newaddr += baseaddr; 1154a5d661aSToomas Soome #endif 1164a5d661aSToomas Soome break; 1174a5d661aSToomas Soome default: 1184a5d661aSToomas Soome /* XXX: do we need other relocations ? */ 1194a5d661aSToomas Soome break; 1204a5d661aSToomas Soome } 1214a5d661aSToomas Soome rel = (ElfW_Rel *)(void *)((caddr_t) rel + relent); 1224a5d661aSToomas Soome } 1234a5d661aSToomas Soome } 124