1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef CRAZY_LINKER_ELF_RELOCATIONS_H 6#define CRAZY_LINKER_ELF_RELOCATIONS_H 7 8#include <string.h> 9#include <unistd.h> 10 11#include "elf_traits.h" 12 13namespace crazy { 14 15class ElfSymbols; 16class ElfView; 17class Error; 18 19// An ElfRelocations instance holds information about relocations in a mapped 20// ELF binary. 21class ElfRelocations { 22 public: 23 ElfRelocations() { ::memset(this, 0, sizeof(*this)); } 24 ~ElfRelocations() {} 25 26 bool Init(const ElfView* view, Error* error); 27 28 // Abstract class used to resolve symbol names into addresses. 29 // Callers of ::ApplyAll() should pass the address of a derived class 30 // that properly implements the Lookup() method. 31 class SymbolResolver { 32 public: 33 SymbolResolver() {} 34 ~SymbolResolver() {} 35 virtual void* Lookup(const char* symbol_name) = 0; 36 }; 37 38 // Apply all relocations to the target mapped ELF binary. Must be called 39 // after Init(). 40 // |symbols| maps to the symbol entries for the target library only. 41 // |resolver| can resolve symbols out of the current library. 42 // On error, return false and set |error| message. 43 bool ApplyAll(const ElfSymbols* symbols, 44 SymbolResolver* resolver, 45 Error* error); 46 47#if defined(__arm__) || defined(__aarch64__) 48 // Register packed relocations to apply. 49 // |packed_relocs| is a pointer to packed relocations data. 50 void RegisterPackedRelocations(uint8_t* packed_relocations); 51#endif 52 53 // This function is used to adjust relocated addresses in a copy of an 54 // existing section of an ELF binary. I.e. |src_addr|...|src_addr + size| 55 // must be inside the mapped ELF binary, this function will first copy its 56 // content into |dst_addr|...|dst_addr + size|, then adjust all relocated 57 // addresses inside the destination section as if it was loaded/mapped 58 // at |map_addr|...|map_addr + size|. Only relative relocations are processed, 59 // symbolic ones are ignored. 60 void CopyAndRelocate(size_t src_addr, 61 size_t dst_addr, 62 size_t map_addr, 63 size_t size); 64 65 private: 66 bool ResolveSymbol(unsigned rel_type, 67 unsigned rel_symbol, 68 const ElfSymbols* symbols, 69 SymbolResolver* resolver, 70 ELF::Addr reloc, 71 ELF::Addr* sym_addr, 72 Error* error); 73 bool ApplyRelaReloc(const ELF::Rela* rela, 74 ELF::Addr sym_addr, 75 bool resolved, 76 Error* error); 77 bool ApplyRelReloc(const ELF::Rel* rel, 78 ELF::Addr sym_addr, 79 bool resolved, 80 Error* error); 81 bool ApplyRelaRelocs(const ELF::Rela* relocs, 82 size_t relocs_count, 83 const ElfSymbols* symbols, 84 SymbolResolver* resolver, 85 Error* error); 86 bool ApplyRelRelocs(const ELF::Rel* relocs, 87 size_t relocs_count, 88 const ElfSymbols* symbols, 89 SymbolResolver* resolver, 90 Error* error); 91 void AdjustRelocation(ELF::Word rel_type, 92 ELF::Addr src_reloc, 93 size_t dst_delta, 94 size_t map_delta); 95 void RelocateRela(size_t src_addr, 96 size_t dst_addr, 97 size_t map_addr, 98 size_t size); 99 void RelocateRel(size_t src_addr, 100 size_t dst_addr, 101 size_t map_addr, 102 size_t size); 103 104#if defined(__arm__) || defined(__aarch64__) 105 // Apply packed rel or rela relocations. On error, return false. 106 bool ApplyPackedRel(const uint8_t* packed_relocations, Error* error); 107 bool ApplyPackedRela(const uint8_t* packed_relocations, Error* error); 108 109 // Apply packed relocations. 110 // On error, return false and set |error| message. No-op if no packed 111 // relocations were registered. 112 bool ApplyPackedRelocations(Error* error); 113#endif 114 115#if defined(__mips__) 116 bool RelocateMipsGot(const ElfSymbols* symbols, 117 SymbolResolver* resolver, 118 Error* error); 119#endif 120 121 const ELF::Phdr* phdr_; 122 size_t phdr_count_; 123 size_t load_bias_; 124 125 ELF::Addr relocations_type_; 126 ELF::Addr plt_relocations_; 127 size_t plt_relocations_size_; 128 ELF::Addr* plt_got_; 129 130 ELF::Addr relocations_; 131 size_t relocations_size_; 132 133#if defined(__mips__) 134 // MIPS-specific relocation fields. 135 ELF::Word mips_symtab_count_; 136 ELF::Word mips_local_got_count_; 137 ELF::Word mips_gotsym_; 138#endif 139 140#if defined(__arm__) || defined(__aarch64__) 141 uint8_t* packed_relocations_; 142#endif 143 144 bool has_text_relocations_; 145 bool has_symbolic_; 146}; 147 148} // namespace crazy 149 150#endif // CRAZY_LINKER_ELF_RELOCATIONS_H 151