OLD | NEW |
(Empty) | |
| 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 |
| 13 namespace crazy { |
| 14 |
| 15 class ElfSymbols; |
| 16 class ElfView; |
| 17 class Error; |
| 18 |
| 19 // An ElfRelocations instance holds information about relocations in a mapped |
| 20 // ELF binary. |
| 21 class 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 // This function is used to adjust relocated addresses in a copy of an |
| 48 // existing section of an ELF binary. I.e. |src_addr|...|src_addr + size| |
| 49 // must be inside the mapped ELF binary, this function will first copy its |
| 50 // content into |dst_addr|...|dst_addr + size|, then adjust all relocated |
| 51 // addresses inside the destination section as if it was loaded/mapped |
| 52 // at |map_addr|...|map_addr + size|. Only relative relocations are processed, |
| 53 // symbolic ones are ignored. |
| 54 void CopyAndRelocate(size_t src_addr, |
| 55 size_t dst_addr, |
| 56 size_t map_addr, |
| 57 size_t size); |
| 58 |
| 59 private: |
| 60 bool ResolveSymbol(unsigned rel_type, |
| 61 unsigned rel_symbol, |
| 62 const ElfSymbols* symbols, |
| 63 SymbolResolver* resolver, |
| 64 ELF::Addr reloc, |
| 65 ELF::Addr* sym_addr, |
| 66 Error* error); |
| 67 bool ApplyResolvedRelaReloc(const ELF::Rela* rela, |
| 68 ELF::Addr sym_addr, |
| 69 bool resolved, |
| 70 Error* error); |
| 71 bool ApplyResolvedRelReloc(const ELF::Rel* rel, |
| 72 ELF::Addr sym_addr, |
| 73 bool resolved, |
| 74 Error* error); |
| 75 bool ApplyRelaReloc(const ELF::Rela* rela, |
| 76 const ElfSymbols* symbols, |
| 77 SymbolResolver* resolver, |
| 78 Error* error); |
| 79 bool ApplyRelReloc(const ELF::Rel* rel, |
| 80 const ElfSymbols* symbols, |
| 81 SymbolResolver* resolver, |
| 82 Error* error); |
| 83 bool ApplyRelaRelocs(const ELF::Rela* relocs, |
| 84 size_t relocs_count, |
| 85 const ElfSymbols* symbols, |
| 86 SymbolResolver* resolver, |
| 87 Error* error); |
| 88 bool ApplyRelRelocs(const ELF::Rel* relocs, |
| 89 size_t relocs_count, |
| 90 const ElfSymbols* symbols, |
| 91 SymbolResolver* resolver, |
| 92 Error* error); |
| 93 void AdjustRelocation(ELF::Word rel_type, |
| 94 ELF::Addr src_reloc, |
| 95 size_t dst_delta, |
| 96 size_t map_delta); |
| 97 template<typename Rel> |
| 98 void RelocateRelocations(size_t src_addr, |
| 99 size_t dst_addr, |
| 100 size_t map_addr, |
| 101 size_t size); |
| 102 void AdjustAndroidRelocation(const ELF::Rela* relocation, |
| 103 size_t src_addr, |
| 104 size_t dst_addr, |
| 105 size_t map_addr, |
| 106 size_t size); |
| 107 |
| 108 // Android packed relocations unpacker. Calls the given handler for |
| 109 // each relocation in the unpacking stream. |
| 110 typedef bool (*RelocationHandler)(ElfRelocations* relocations, |
| 111 const ELF::Rela* relocation, |
| 112 void* opaque); |
| 113 bool ForEachAndroidRelocation(RelocationHandler handler, |
| 114 void* opaque); |
| 115 |
| 116 // Apply Android packed relocations. |
| 117 // On error, return false and set |error| message. |
| 118 // The static function is the ForEachAndroidRelocation() handler. |
| 119 bool ApplyAndroidRelocations(const ElfSymbols* symbols, |
| 120 SymbolResolver* resolver, |
| 121 Error* error); |
| 122 static bool ApplyAndroidRelocation(ElfRelocations* relocations, |
| 123 const ELF::Rela* relocation, |
| 124 void* opaque); |
| 125 |
| 126 // Relocate Android packed relocations. |
| 127 // The static function is the ForEachAndroidRelocation() handler. |
| 128 void RelocateAndroidRelocations(size_t src_addr, |
| 129 size_t dst_addr, |
| 130 size_t map_addr, |
| 131 size_t size); |
| 132 static bool RelocateAndroidRelocation(ElfRelocations* relocations, |
| 133 const ELF::Rela* relocation, |
| 134 void* opaque); |
| 135 |
| 136 #if defined(__mips__) |
| 137 bool RelocateMipsGot(const ElfSymbols* symbols, |
| 138 SymbolResolver* resolver, |
| 139 Error* error); |
| 140 #endif |
| 141 |
| 142 const ELF::Phdr* phdr_; |
| 143 size_t phdr_count_; |
| 144 size_t load_bias_; |
| 145 |
| 146 ELF::Addr relocations_type_; |
| 147 ELF::Addr plt_relocations_; |
| 148 size_t plt_relocations_size_; |
| 149 ELF::Addr* plt_got_; |
| 150 |
| 151 ELF::Addr relocations_; |
| 152 size_t relocations_size_; |
| 153 |
| 154 #if defined(__mips__) |
| 155 // MIPS-specific relocation fields. |
| 156 ELF::Word mips_symtab_count_; |
| 157 ELF::Word mips_local_got_count_; |
| 158 ELF::Word mips_gotsym_; |
| 159 #endif |
| 160 |
| 161 uint8_t* android_relocations_; |
| 162 size_t android_relocations_size_; |
| 163 |
| 164 bool has_text_relocations_; |
| 165 bool has_symbolic_; |
| 166 }; |
| 167 |
| 168 } // namespace crazy |
| 169 |
| 170 #endif // CRAZY_LINKER_ELF_RELOCATIONS_H |
OLD | NEW |