1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_elf_relocations.h" 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <errno.h> 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_debug.h" 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_elf_symbols.h" 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_elf_view.h" 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_error.h" 1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "crazy_linker_leb128.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "crazy_linker_system.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_util.h" 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "linker_phdr.h" 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DEBUG_RELOCATIONS 0 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define RLOG(...) LOG_IF(DEBUG_RELOCATIONS, __VA_ARGS__) 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define RLOG_ERRNO(...) LOG_ERRNO_IF(DEBUG_RELOCATIONS, __VA_ARGS__) 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DF_SYMBOLIC 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DF_SYMBOLIC 2 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DF_TEXTREL 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DF_TEXTREL 4 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef DT_FLAGS 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define DT_FLAGS 30 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Processor-specific relocation types supported by the linker. 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __arm__ 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/* arm32 relocations */ 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_ARM_ABS32 2 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_ARM_REL32 3 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_ARM_GLOB_DAT 21 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_ARM_JUMP_SLOT 22 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_ARM_COPY 20 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_ARM_RELATIVE 23 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define RELATIVE_RELOCATION_CODE R_ARM_RELATIVE 4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // __arm__ 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __aarch64__ 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/* arm64 relocations */ 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_AARCH64_ABS64 257 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_AARCH64_COPY 1024 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_AARCH64_GLOB_DAT 1025 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_AARCH64_JUMP_SLOT 1026 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_AARCH64_RELATIVE 1027 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define RELATIVE_RELOCATION_CODE R_AARCH64_RELATIVE 6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // __aarch64__ 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __i386__ 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/* i386 relocations */ 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_386_32 1 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_386_PC32 2 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_386_GLOB_DAT 6 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_386_JMP_SLOT 7 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define R_386_RELATIVE 8 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // __i386__ 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef __x86_64__ 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* x86_64 relocations */ 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define R_X86_64_64 1 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define R_X86_64_PC32 2 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define R_X86_64_GLOB_DAT 6 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define R_X86_64_JMP_SLOT 7 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define R_X86_64_RELATIVE 8 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif // __x86_64__ 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace crazy { 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace { 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// List of known relocation types the relocator knows about. 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)enum RelocationType { 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RELOCATION_TYPE_UNKNOWN = 0, 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RELOCATION_TYPE_ABSOLUTE = 1, 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RELOCATION_TYPE_RELATIVE = 2, 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RELOCATION_TYPE_PC_RELATIVE = 3, 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RELOCATION_TYPE_COPY = 4, 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Convert an ELF relocation type info a RelocationType value. 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)RelocationType GetRelocationType(ELF::Word r_type) { 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (r_type) { 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __arm__ 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_JUMP_SLOT: 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_GLOB_DAT: 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_ABS32: 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RELOCATION_TYPE_ABSOLUTE; 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_REL32: 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_RELATIVE: 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RELOCATION_TYPE_RELATIVE; 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_COPY: 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RELOCATION_TYPE_COPY; 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __aarch64__ 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_AARCH64_JUMP_SLOT: 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_AARCH64_GLOB_DAT: 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_AARCH64_ABS64: 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RELOCATION_TYPE_ABSOLUTE; 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_AARCH64_RELATIVE: 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RELOCATION_TYPE_RELATIVE; 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_AARCH64_COPY: 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RELOCATION_TYPE_COPY; 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __i386__ 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_386_JMP_SLOT: 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_386_GLOB_DAT: 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_386_32: 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RELOCATION_TYPE_ABSOLUTE; 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_386_RELATIVE: 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RELOCATION_TYPE_RELATIVE; 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_386_PC32: 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RELOCATION_TYPE_PC_RELATIVE; 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef __x86_64__ 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case R_X86_64_JMP_SLOT: 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case R_X86_64_GLOB_DAT: 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case R_X86_64_64: 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return RELOCATION_TYPE_ABSOLUTE; 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case R_X86_64_RELATIVE: 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return RELOCATION_TYPE_RELATIVE; 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case R_X86_64_PC32: 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return RELOCATION_TYPE_PC_RELATIVE; 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __mips__ 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_MIPS_REL32: 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RELOCATION_TYPE_RELATIVE; 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) default: 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return RELOCATION_TYPE_UNKNOWN; 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool ElfRelocations::Init(const ElfView* view, Error* error) { 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Save these for later. 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) phdr_ = view->phdr(); 169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) phdr_count_ = view->phdr_count(); 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) load_bias_ = view->load_bias(); 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // We handle only Rel or Rela, but not both. If DT_RELA or DT_RELASZ 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // then we require DT_PLTREL to agree. 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool has_rela_relocations = false; 175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool has_rel_relocations = false; 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Parse the dynamic table. 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ElfView::DynamicIterator dyn(view); 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (; dyn.HasNext(); dyn.GetNext()) { 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr dyn_value = dyn.GetValue(); 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uintptr_t dyn_addr = dyn.GetAddress(view->load_bias()); 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Addr tag = dyn.GetTag(); 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (tag) { 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_PLTREL: 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" DT_PLTREL value=%d\n", dyn_value); 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dyn_value != DT_REL && dyn_value != DT_RELA) { 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *error = "Invalid DT_PLTREL value in dynamic section"; 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) relocations_type_ = dyn_value; 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_JMPREL: 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" DT_JMPREL addr=%p\n", dyn_addr); 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) plt_relocations_ = dyn_addr; 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_PLTRELSZ: 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) plt_relocations_size_ = dyn_value; 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" DT_PLTRELSZ size=%d\n", dyn_value); 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_RELA: 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_REL: 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" %s addr=%p\n", 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (tag == DT_RELA) ? "DT_RELA" : "DT_REL", 205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dyn_addr); 206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (relocations_) { 207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *error = "Unsupported DT_RELA/DT_REL combination in dynamic section"; 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) relocations_ = dyn_addr; 211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (tag == DT_RELA) 212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) has_rela_relocations = true; 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) else 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) has_rel_relocations = true; 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_RELASZ: 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_RELSZ: 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" %s size=%d\n", 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (tag == DT_RELASZ) ? "DT_RELASZ" : "DT_RELSZ", 220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dyn_addr); 221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (relocations_size_) { 222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *error = "Unsupported DT_RELASZ/DT_RELSZ combination in dyn section"; 223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) relocations_size_ = dyn_value; 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (tag == DT_RELASZ) 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) has_rela_relocations = true; 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) else 229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) has_rel_relocations = true; 230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_PLTGOT: 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Only used on MIPS currently. Could also be used on other platforms 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // when lazy binding (i.e. RTLD_LAZY) is implemented. 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" DT_PLTGOT addr=%p\n", dyn_addr); 235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) plt_got_ = reinterpret_cast<ELF::Addr*>(dyn_addr); 236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_TEXTREL: 238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" DT_TEXTREL\n"); 239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) has_text_relocations_ = true; 240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_SYMBOLIC: 242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" DT_SYMBOLIC\n"); 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) has_symbolic_ = true; 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_FLAGS: 246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dyn_value & DF_TEXTREL) 247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) has_text_relocations_ = true; 248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dyn_value & DF_SYMBOLIC) 249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) has_symbolic_ = true; 250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" DT_FLAGS has_text_relocations=%s has_symbolic=%s\n", 251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) has_text_relocations_ ? "true" : "false", 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) has_symbolic_ ? "true" : "false"); 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(__mips__) 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_MIPS_SYMTABNO: 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" DT_MIPS_SYMTABNO value=%d\n", dyn_value); 257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mips_symtab_count_ = dyn_value; 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_MIPS_LOCAL_GOTNO: 261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" DT_MIPS_LOCAL_GOTNO value=%d\n", dyn_value); 262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mips_local_got_count_ = dyn_value; 263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case DT_MIPS_GOTSYM: 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" DT_MIPS_GOTSYM value=%d\n", dyn_value); 267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mips_gotsym_ = dyn_value; 268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) default: 271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ; 272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (has_rel_relocations && has_rela_relocations) { 276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *error = "Combining DT_REL and DT_RELA is not currently supported"; 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If DT_PLTREL did not explicitly assign relocations_type_, set it 281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // here based on the type of relocations found. 282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (relocations_type_ != DT_REL && relocations_type_ != DT_RELA) { 283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (has_rel_relocations) 284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch relocations_type_ = DT_REL; 285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch else if (has_rela_relocations) 286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch relocations_type_ = DT_RELA; 287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (relocations_type_ == DT_REL && has_rela_relocations) { 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *error = "Found DT_RELA in dyn section, but DT_PLTREL is DT_REL"; 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (relocations_type_ == DT_RELA && has_rel_relocations) { 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *error = "Found DT_REL in dyn section, but DT_PLTREL is DT_RELA"; 295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool ElfRelocations::ApplyAll(const ElfSymbols* symbols, 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SymbolResolver* resolver, 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG("%s: Enter\n", __FUNCTION__); 305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (has_text_relocations_) { 307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (phdr_table_unprotect_segments(phdr_, phdr_count_, load_bias_) < 0) { 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Can't unprotect loadable segments: %s", strerror(errno)); 309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (relocations_type_ == DT_REL) { 314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(plt_relocations_), 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) plt_relocations_size_ / sizeof(ELF::Rel), 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) symbols, 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) resolver, 318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error)) 319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!ApplyRelRelocs(reinterpret_cast<ELF::Rel*>(relocations_), 321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) relocations_size_ / sizeof(ELF::Rel), 322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) symbols, 323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) resolver, 324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error)) 325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (relocations_type_ == DT_RELA) { 329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(plt_relocations_), 330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) plt_relocations_size_ / sizeof(ELF::Rela), 331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) symbols, 332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) resolver, 333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error)) 334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!ApplyRelaRelocs(reinterpret_cast<ELF::Rela*>(relocations_), 336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) relocations_size_ / sizeof(ELF::Rela), 337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) symbols, 338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) resolver, 339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error)) 340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 34303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if defined(__arm__) || defined(__aarch64__) 34403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ApplyPackedRelocations(error)) 345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif 347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __mips__ 349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!RelocateMipsGot(symbols, resolver, error)) 350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (has_text_relocations_) { 354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (phdr_table_protect_segments(phdr_, phdr_count_, load_bias_) < 0) { 355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Can't reprotect loadable segments: %s", strerror(errno)); 356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG("%s: Done\n", __FUNCTION__); 361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 36403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if defined(__arm__) || defined(__aarch64__) 365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 36603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ElfRelocations::RegisterPackedRelocations(uint8_t* packed_relocations) { 36703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) packed_relocations_ = packed_relocations; 368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 37003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ElfRelocations::ApplyPackedRel(const uint8_t* packed_relocations, 37103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Error* error) { 37203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Leb128Decoder decoder(packed_relocations); 373116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Find the count of pairs and the start address. 375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t pairs = decoder.Dequeue(); 37603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const ELF::Addr start_address = decoder.Dequeue(); 377116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 37803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Emit initial relative relocation. 37903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ELF::Rel relocation; 38003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) relocation.r_offset = start_address; 38103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE); 382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ELF::Addr sym_addr = 0; 383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const bool resolved = false; 384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) 385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 386116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t unpacked_count = 1; 388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Emit relocations for each count-delta pair. 390116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch while (pairs) { 391116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t count = decoder.Dequeue(); 392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const size_t delta = decoder.Dequeue(); 393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 39403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Emit count relative relocations with delta offset. 395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch while (count) { 396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch relocation.r_offset += delta; 397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) 398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch unpacked_count++; 400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch count--; 401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pairs--; 403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count); 406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 40803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 40903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ElfRelocations::ApplyPackedRela(const uint8_t* packed_relocations, 41003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Error* error) { 41103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Sleb128Decoder decoder(packed_relocations); 41203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 41303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Find the count of pairs. 41403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t pairs = decoder.Dequeue(); 41503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 41603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ELF::Addr offset = 0; 41703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ELF::Sxword addend = 0; 41803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 41903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const ELF::Addr sym_addr = 0; 42003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const bool resolved = false; 42103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 42203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t unpacked_count = 0; 42303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 42403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Emit relocations for each deltas pair. 42503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (pairs) { 42603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) offset += decoder.Dequeue(); 42703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) addend += decoder.Dequeue(); 42803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 42903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ELF::Rela relocation; 43003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) relocation.r_offset = offset; 43103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE); 43203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) relocation.r_addend = addend; 43303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!ApplyRelaReloc(&relocation, sym_addr, resolved, error)) 43403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 43503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) unpacked_count++; 43603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) pairs--; 43703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 43803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 43903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) RLOG("%s: unpacked_count=%d\n", __FUNCTION__, unpacked_count); 44003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 44103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 44203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 44303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ElfRelocations::ApplyPackedRelocations(Error* error) { 44403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!packed_relocations_) 44503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 44603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 44703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Check for an initial APR1 header, packed relocations. 44803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (packed_relocations_[0] == 'A' && 44903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) packed_relocations_[1] == 'P' && 45003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) packed_relocations_[2] == 'R' && 45103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) packed_relocations_[3] == '1') { 45203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return ApplyPackedRel(packed_relocations_ + 4, error); 45303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 45403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 45503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Check for an initial APA1 header, packed relocations with addend. 45603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (packed_relocations_[0] == 'A' && 45703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) packed_relocations_[1] == 'P' && 45803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) packed_relocations_[2] == 'A' && 45903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) packed_relocations_[3] == '1') { 46003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return ApplyPackedRela(packed_relocations_ + 4, error); 46103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 46203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 46303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) error->Format("Bad packed relocations ident, expected APR1 or APA1"); 46403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 46503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 46603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif // __arm__ || __aarch64__ 467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool ElfRelocations::ApplyRelaReloc(const ELF::Rela* rela, 469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr sym_addr, 470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool resolved CRAZY_UNUSED, 471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word rela_type = ELF_R_TYPE(rela->r_info); 473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word CRAZY_UNUSED rela_symbol = ELF_R_SYM(rela->r_info); 474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Sword CRAZY_UNUSED addend = rela->r_addend; 475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); 477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" rela reloc=%p offset=%p type=%d addend=%p\n", 479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) reloc, 480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rela->r_offset, 481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rela_type, 482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) addend); 483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Apply the relocation. 485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr* CRAZY_UNUSED target = reinterpret_cast<ELF::Addr*>(reloc); 486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (rela_type) { 487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __aarch64__ 488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_AARCH64_JUMP_SLOT: 489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" R_AARCH64_JUMP_SLOT target=%p addr=%p\n", 490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) target, 491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) sym_addr + addend); 492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target = sym_addr + addend; 493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_AARCH64_GLOB_DAT: 496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" R_AARCH64_GLOB_DAT target=%p addr=%p\n", 497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) target, 498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) sym_addr + addend); 499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target = sym_addr + addend; 500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_AARCH64_ABS64: 503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" R_AARCH64_ABS64 target=%p (%p) addr=%p\n", 504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) target, 505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target, 506f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) sym_addr + addend); 507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target += sym_addr + addend; 508f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 509f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_AARCH64_RELATIVE: 511f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" R_AARCH64_RELATIVE target=%p (%p) bias=%p\n", 512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) target, 513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target, 514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) load_bias_ + addend); 515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (__builtin_expect(rela_symbol, 0)) { 516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *error = "Invalid relative relocation with symbol"; 517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target = load_bias_ + addend; 520f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 521f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_AARCH64_COPY: 523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // NOTE: These relocations are forbidden in shared libraries. 524f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" R_AARCH64_COPY\n"); 525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *error = "Invalid R_AARCH64_COPY relocation in shared library"; 526f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // __aarch64__ 528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef __x86_64__ 5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case R_X86_64_JMP_SLOT: 5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *target = sym_addr + addend; 5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case R_X86_64_GLOB_DAT: 5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *target = sym_addr + addend; 5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case R_X86_64_RELATIVE: 5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (rela_symbol) { 5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *error = "Invalid relative relocation with symbol"; 5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *target = load_bias_ + addend; 5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case R_X86_64_64: 5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *target = sym_addr + addend; 5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case R_X86_64_PC32: 5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *target = sym_addr + (addend - reloc); 5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 5535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif // __x86_64__ 5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) default: 556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Invalid relocation type (%d)", rela_type); 557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 558f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 559f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 560f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 561f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 562f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool ElfRelocations::ApplyRelReloc(const ELF::Rel* rel, 564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr sym_addr, 565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool resolved CRAZY_UNUSED, 566f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 567f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); 568f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word CRAZY_UNUSED rel_symbol = ELF_R_SYM(rel->r_info); 569f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 570f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); 571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 572f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" rel reloc=%p offset=%p type=%d\n", reloc, rel->r_offset, rel_type); 573f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 574f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Apply the relocation. 575f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr* CRAZY_UNUSED target = reinterpret_cast<ELF::Addr*>(reloc); 576f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (rel_type) { 577f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __arm__ 578f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_JUMP_SLOT: 579f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" R_ARM_JUMP_SLOT target=%p addr=%p\n", target, sym_addr); 580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target = sym_addr; 581f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 582f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_GLOB_DAT: 584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" R_ARM_GLOB_DAT target=%p addr=%p\n", target, sym_addr); 585f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target = sym_addr; 586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_ABS32: 589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" R_ARM_ABS32 target=%p (%p) addr=%p\n", 590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) target, 591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target, 592f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) sym_addr); 593f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target += sym_addr; 594f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 595f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 596f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_REL32: 597f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" R_ARM_REL32 target=%p (%p) addr=%p offset=%p\n", 598f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) target, 599f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target, 600f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) sym_addr, 601f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rel->r_offset); 602f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target += sym_addr - rel->r_offset; 603f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 604f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 605f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_RELATIVE: 606f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" R_ARM_RELATIVE target=%p (%p) bias=%p\n", 607f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) target, 608f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target, 609f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) load_bias_); 610f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (__builtin_expect(rel_symbol, 0)) { 611f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *error = "Invalid relative relocation with symbol"; 612f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 613f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 614f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target += load_bias_; 615f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 616f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 617f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_COPY: 618f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // NOTE: These relocations are forbidden in shared libraries. 619f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The Android linker has special code to deal with this, which 620f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // is not needed here. 621f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" R_ARM_COPY\n"); 622f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *error = "Invalid R_ARM_COPY relocation in shared library"; 623f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 624f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // __arm__ 625f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 626f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __i386__ 627f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_386_JMP_SLOT: 628f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target = sym_addr; 629f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 630f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 631f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_386_GLOB_DAT: 632f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target = sym_addr; 633f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 634f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 635f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_386_RELATIVE: 636f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (rel_symbol) { 637f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *error = "Invalid relative relocation with symbol"; 638f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 639f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 640f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target += load_bias_; 641f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 642f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 643f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_386_32: 644f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target += sym_addr; 645f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 646f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 647f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_386_PC32: 648f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target += (sym_addr - reloc); 649f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 650f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // __i386__ 651f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 652f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __mips__ 653f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_MIPS_REL32: 654f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (resolved) 655f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target += sym_addr; 656f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) else 657f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *target += load_bias_; 658f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 659f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // __mips__ 660f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 661f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) default: 662f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Invalid relocation type (%d)", rel_type); 663f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 664f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 665f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 666f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 667f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 668f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 669f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool ElfRelocations::ResolveSymbol(ELF::Word rel_type, 670f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Word rel_symbol, 671f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ElfSymbols* symbols, 672f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SymbolResolver* resolver, 673f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr reloc, 674f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr* sym_addr, 675f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 676f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* sym_name = symbols->LookupNameById(rel_symbol); 677f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" symbol name='%s'\n", sym_name); 678f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* address = resolver->Lookup(sym_name); 679f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 680f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (address) { 681f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The symbol was found, so compute its address. 682f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG("%s: symbol %s resolved to %p\n", __FUNCTION__, sym_name, address); 683f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *sym_addr = reinterpret_cast<ELF::Addr>(address); 684f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 685f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 686f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 687f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The symbol was not found. Normally this is an error except 688f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // if this is a weak reference. 689f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!symbols->IsWeakById(rel_symbol)) { 690f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Could not find symbol '%s'", sym_name); 691f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 692f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 693f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 694f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG("%s: weak reference to unresolved symbol %s\n", __FUNCTION__, sym_name); 695f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 696f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // IHI0044C AAELF 4.5.1.1: 697f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Libraries are not searched to resolve weak references. 698f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // It is not an error for a weak reference to remain 699f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // unsatisfied. 700f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // 701f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // During linking, the value of an undefined weak reference is: 702f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // - Zero if the relocation type is absolute 703f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // - The address of the place if the relocation is pc-relative 704f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // - The address of nominal base address if the relocation 705f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // type is base-relative. 706f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RelocationType r = GetRelocationType(rel_type); 707f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (r == RELOCATION_TYPE_ABSOLUTE || r == RELOCATION_TYPE_RELATIVE) { 708f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *sym_addr = 0; 709f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 710f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 711f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 712f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (r == RELOCATION_TYPE_PC_RELATIVE) { 713f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *sym_addr = reloc; 714f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 715f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 716f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 717f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format( 718f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "Invalid weak relocation type (%d) for unknown symbol '%s'", 719f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) r, 720f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) sym_name); 721f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 722f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 723f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 724f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool ElfRelocations::ApplyRelRelocs(const ELF::Rel* rel, 725f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t rel_count, 726f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ElfSymbols* symbols, 727f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SymbolResolver* resolver, 728f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 729f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG("%s: rel=%p rel_count=%d\n", __FUNCTION__, rel, rel_count); 730f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 731f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!rel) 732f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 733f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 734f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t rel_n = 0; rel_n < rel_count; rel++, rel_n++) { 735f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); 736f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); 737f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 738f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr sym_addr = 0; 739f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); 740f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" %d/%d reloc=%p offset=%p type=%d symbol=%d\n", 741f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rel_n + 1, 742f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rel_count, 743f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) reloc, 744f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rel->r_offset, 745f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rel_type, 746f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rel_symbol); 747f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 748f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (rel_type == 0) 749f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 750f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 751f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool resolved = false; 752f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 753f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If this is a symbolic relocation, compute the symbol's address. 754f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (__builtin_expect(rel_symbol != 0, 0)) { 755116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!ResolveSymbol(rel_type, 756116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rel_symbol, 757116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch symbols, 758116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resolver, 759116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch reloc, 760116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &sym_addr, 761116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch error)) { 762116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 763116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 764116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resolved = true; 765f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 766f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 767f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!ApplyRelReloc(rel, sym_addr, resolved, error)) 768f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 769f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 770f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 771f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 772f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 773f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 774f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool ElfRelocations::ApplyRelaRelocs(const ELF::Rela* rela, 775f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t rela_count, 776f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ElfSymbols* symbols, 777f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SymbolResolver* resolver, 778f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 779f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG("%s: rela=%p rela_count=%d\n", __FUNCTION__, rela, rela_count); 780f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 781f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!rela) 782f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 783f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 784f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t rel_n = 0; rel_n < rela_count; rela++, rel_n++) { 785f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word rel_type = ELF_R_TYPE(rela->r_info); 786f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word rel_symbol = ELF_R_SYM(rela->r_info); 787f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 788f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr sym_addr = 0; 789f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr reloc = static_cast<ELF::Addr>(rela->r_offset + load_bias_); 790f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RLOG(" %d/%d reloc=%p offset=%p type=%d symbol=%d\n", 791f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rel_n + 1, 792f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rela_count, 793f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) reloc, 794f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rela->r_offset, 795f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rel_type, 796f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rel_symbol); 797f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 798f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (rel_type == 0) 799f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 800f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 801f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool resolved = false; 802f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 803f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // If this is a symbolic relocation, compute the symbol's address. 804f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (__builtin_expect(rel_symbol != 0, 0)) { 805116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!ResolveSymbol(rel_type, 806116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rel_symbol, 807116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch symbols, 808116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resolver, 809116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch reloc, 810116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &sym_addr, 811116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch error)) { 812116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 813116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 814116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resolved = true; 815f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 816f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 817f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!ApplyRelaReloc(rela, sym_addr, resolved, error)) 818f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 819f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 820f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 821f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 822f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 823f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 824f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __mips__ 825f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool ElfRelocations::RelocateMipsGot(const ElfSymbols* symbols, 826f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SymbolResolver* resolver, 827f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 828f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!plt_got_) 829f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 830f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 831f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Handle the local GOT entries. 832f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // This mimics what the system linker does. 833f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Note from the system linker: 834f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // got[0]: lazy resolver function address. 835f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // got[1]: may be used for a GNU extension. 836f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Set it to a recognizable address in case someone calls it 837f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // (should be _rtld_bind_start). 838f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr* got = plt_got_; 839f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) got[0] = 0xdeadbeef; 840f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (got[1] & 0x80000000) 841f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) got[1] = 0xdeadbeef; 842f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 843f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (ELF::Addr n = 2; n < mips_local_got_count_; ++n) 844f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) got[n] += load_bias_; 845f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 846f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Handle the global GOT entries. 847f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) got += mips_local_got_count_; 848f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (size_t idx = mips_gotsym_; idx < mips_symtab_count_; idx++, got++) { 849f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* sym_name = symbols->LookupNameById(idx); 850f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* sym_addr = resolver->Lookup(sym_name); 851f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (sym_addr) { 852f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Found symbol, update GOT entry. 853f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *got = reinterpret_cast<ELF::Addr>(sym_addr); 854f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 855f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 856f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 857f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (symbols->IsWeakById(idx)) { 858f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Undefined symbols are only ok if this is a weak reference. 859f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Update GOT entry to 0 though. 860f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *got = 0; 861f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 862f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 863f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 864f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Cannot locate symbol %s", sym_name); 865f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 866f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 867f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 868f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 869f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 870f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // __mips__ 871f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 872f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ElfRelocations::AdjustRelocation(ELF::Word rel_type, 873f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr src_reloc, 874f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t dst_delta, 875f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t map_delta) { 876f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(src_reloc + dst_delta); 877f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 878f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (rel_type) { 879f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __arm__ 880f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_ARM_RELATIVE: 881f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *dst_ptr += map_delta; 882f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 883f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // __arm__ 884f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 885f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __aarch64__ 886f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_AARCH64_RELATIVE: 887f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *dst_ptr += map_delta; 888f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 889f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // __aarch64__ 890f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 891f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __i386__ 892f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_386_RELATIVE: 893f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *dst_ptr += map_delta; 894f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 895f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 896f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 8975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef __x86_64__ 8985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case R_X86_64_RELATIVE: 8995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *dst_ptr += map_delta; 9005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 9015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 9025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 903f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __mips__ 904f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case R_MIPS_REL32: 905f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *dst_ptr += map_delta; 906f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 907f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 908f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) default: 909f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ; 910f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 911f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 912f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 913f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ElfRelocations::RelocateRela(size_t src_addr, 914f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t dst_addr, 915f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t map_addr, 916f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t size) { 917f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Add this value to each source address to get the corresponding 918f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // destination address. 919f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const size_t dst_delta = dst_addr - src_addr; 920f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const size_t map_delta = map_addr - src_addr; 921f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 922f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Ignore PLT relocations, which all target symbols (ignored here). 923f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Rela* rel = reinterpret_cast<ELF::Rela*>(relocations_); 924f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const size_t relocations_count = relocations_size_ / sizeof(ELF::Rela); 925f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Rela* rel_limit = rel + relocations_count; 926f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 927f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (; rel < rel_limit; ++rel) { 928f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); 929f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); 930f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); 931f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 932f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (rel_type == 0 || rel_symbol != 0) { 933f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Ignore empty and symbolic relocations 934f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 935f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 936f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 937f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (src_reloc < src_addr || src_reloc >= src_addr + size) { 938f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Ignore entries that don't relocate addresses inside the source section. 939f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 940f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 941f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 942f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); 943f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 944f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 945f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 946f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ElfRelocations::RelocateRel(size_t src_addr, 947f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t dst_addr, 948f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t map_addr, 949f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t size) { 950f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Add this value to each source address to get the corresponding 951f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // destination address. 952f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const size_t dst_delta = dst_addr - src_addr; 953f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const size_t map_delta = map_addr - src_addr; 954f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 955f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Ignore PLT relocations, which all target symbols (ignored here). 956f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Rel* rel = reinterpret_cast<ELF::Rel*>(relocations_); 957f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const size_t relocations_count = relocations_size_ / sizeof(ELF::Rel); 958f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Rel* rel_limit = rel + relocations_count; 959f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 960f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (; rel < rel_limit; ++rel) { 961f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); 962f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); 963f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); 964f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 965f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (rel_type == 0 || rel_symbol != 0) { 966f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Ignore empty and symbolic relocations 967f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 968f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 969f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 970f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (src_reloc < src_addr || src_reloc >= src_addr + size) { 971f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Ignore entries that don't relocate addresses inside the source section. 972f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 973f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 974f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 975f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); 976f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 977f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 978f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 979f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ElfRelocations::CopyAndRelocate(size_t src_addr, 980f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t dst_addr, 981f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t map_addr, 982f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t size) { 983f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // First, a straight copy. 984f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ::memcpy(reinterpret_cast<void*>(dst_addr), 985f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) reinterpret_cast<void*>(src_addr), 986f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size); 987f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 988f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Relocate relocations. 989f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (relocations_type_ == DT_REL) 990f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RelocateRel(src_addr, dst_addr, map_addr, size); 991f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 992116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (relocations_type_ == DT_RELA) 993f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RelocateRela(src_addr, dst_addr, map_addr, size); 994f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 995f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __mips__ 996f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Add this value to each source address to get the corresponding 997f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // destination address. 998f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const size_t dst_delta = dst_addr - src_addr; 999f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const size_t map_delta = map_addr - src_addr; 1000f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1001f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Only relocate local GOT entries. 1002f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr* got = plt_got_; 1003f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (got) { 1004f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (ELF::Addr n = 2; n < mips_local_got_count_; ++n) { 1005f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t got_addr = reinterpret_cast<size_t>(&got[n]); 1006f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (got_addr < src_addr || got_addr >= src_addr + size) 1007f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) continue; 1008f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ELF::Addr* dst_ptr = reinterpret_cast<ELF::Addr*>(got_addr + dst_delta); 1009f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *dst_ptr += map_delta; 1010f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1011f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1012f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 1013f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 1014f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1015f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace crazy 1016