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_SHARED_LIBRARY_H |
| 6 #define CRAZY_LINKER_SHARED_LIBRARY_H |
| 7 |
| 8 #include <link.h> |
| 9 |
| 10 #include "crazy_linker_elf_relro.h" |
| 11 #include "crazy_linker_elf_symbols.h" |
| 12 #include "crazy_linker_elf_view.h" |
| 13 #include "crazy_linker_error.h" |
| 14 #include "crazy_linker_rdebug.h" |
| 15 #include "crazy_linker_util.h" |
| 16 #include "elf_traits.h" |
| 17 |
| 18 namespace crazy { |
| 19 |
| 20 class LibraryList; |
| 21 class LibraryView; |
| 22 |
| 23 // A class that models a shared library loaded by the crazy linker. |
| 24 |
| 25 // Libraries have dependencies (which are listed in their dynamic section |
| 26 // as DT_NEEDED entries). Circular dependencies are forbidden, so they |
| 27 // form an ADG, where the root is the crazy linker itself, since all |
| 28 // libraries that it loads will depend on it (to ensure their |
| 29 // dlopen/dlsym/dlclose calls are properly wrapped). |
| 30 |
| 31 class SharedLibrary { |
| 32 public: |
| 33 SharedLibrary(); |
| 34 ~SharedLibrary(); |
| 35 |
| 36 size_t load_address() const { return view_.load_address(); } |
| 37 size_t load_size() const { return view_.load_size(); } |
| 38 size_t load_bias() const { return view_.load_bias(); } |
| 39 const ELF::Phdr* phdr() const { return view_.phdr(); } |
| 40 size_t phdr_count() const { return view_.phdr_count(); } |
| 41 const char* base_name() const { return base_name_; } |
| 42 |
| 43 // Load a library (without its dependents) from an ELF file. |
| 44 // Note: This does not apply relocations, nor runs constructors. |
| 45 // |full_path| if the file full path. |
| 46 // |load_address| is the page-aligned load address in memory, or 0. |
| 47 // |file_offset| is the page-aligned file offset. |
| 48 // On failure, return false and set |error| message. |
| 49 // |
| 50 // After this, the caller should load all library dependencies, |
| 51 // Then call Relocate() and CallConstructors() to complete the |
| 52 // operation. |
| 53 bool Load(const char* full_path, |
| 54 size_t load_address, |
| 55 size_t file_offset, |
| 56 Error* error); |
| 57 |
| 58 // Relocate this library, assuming all its dependencies are already |
| 59 // loaded in |lib_list|. On failure, return false and set |error| |
| 60 // message. |
| 61 bool Relocate(LibraryList* lib_list, |
| 62 Vector<LibraryView*>* preloads, |
| 63 Vector<LibraryView*>* dependencies, |
| 64 Error* error); |
| 65 |
| 66 void GetInfo(size_t* load_address, |
| 67 size_t* load_size, |
| 68 size_t* relro_start, |
| 69 size_t* relro_size) { |
| 70 *load_address = view_.load_address(); |
| 71 *load_size = view_.load_size(); |
| 72 *relro_start = relro_start_; |
| 73 *relro_size = relro_size_; |
| 74 } |
| 75 |
| 76 // Returns true iff a given library is mapped to a virtual address range |
| 77 // that contains a given address. |
| 78 bool ContainsAddress(void* address) const { |
| 79 size_t addr = reinterpret_cast<size_t>(address); |
| 80 return load_address() <= addr && addr <= load_address() + load_size(); |
| 81 } |
| 82 |
| 83 // Call all constructors in the library. |
| 84 void CallConstructors(); |
| 85 |
| 86 // Call all destructors in the library. |
| 87 void CallDestructors(); |
| 88 |
| 89 // Return the ELF symbol entry for a given symbol, if defined by |
| 90 // this library, or NULL otherwise. |
| 91 const ELF::Sym* LookupSymbolEntry(const char* symbol_name); |
| 92 |
| 93 // Find the nearest symbol near a given |address|. On success, return |
| 94 // true and set |*sym_name| to the symbol name, |*sym_addr| to its address |
| 95 // in memory, and |*sym_size| to its size in bytes, if any. |
| 96 bool FindNearestSymbolForAddress(void* address, |
| 97 const char** sym_name, |
| 98 void** sym_addr, |
| 99 size_t* sym_size) { |
| 100 return symbols_.LookupNearestByAddress( |
| 101 address, load_bias(), sym_name, sym_addr, sym_size); |
| 102 } |
| 103 |
| 104 // Return the address of a given |symbol_name| if it is exported |
| 105 // by the library, NULL otherwise. |
| 106 void* FindAddressForSymbol(const char* symbol_name); |
| 107 |
| 108 // Create a new Ashmem region holding a copy of the library's RELRO section, |
| 109 // potentially relocated for a new |load_address|. On success, return true |
| 110 // and sets |*relro_start|, |*relro_size| and |*relro_fd|. Note that the |
| 111 // RELRO start address is adjusted for |load_address|, and that the caller |
| 112 // becomes the owner of |*relro_fd|. On failure, return false and set |
| 113 // |error| message. |
| 114 bool CreateSharedRelro(size_t load_address, |
| 115 size_t* relro_start, |
| 116 size_t* relro_size, |
| 117 int* relro_fd, |
| 118 Error* error); |
| 119 |
| 120 // Try to use a shared relro section from another process. |
| 121 // On success, return true. On failure return false and |
| 122 // sets |error| message. |
| 123 bool UseSharedRelro(size_t relro_start, |
| 124 size_t relro_size, |
| 125 int relro_fd, |
| 126 Error* error); |
| 127 |
| 128 // Look for a symbol named 'JNI_OnLoad' in this library, and if it |
| 129 // exists, call it with |java_vm| as the first parameter. If the |
| 130 // function result is less than |minimum_jni_version|, fail with |
| 131 // a message in |error|. On success, return true, and record |
| 132 // |java_vm| to call 'JNI_OnUnload' at unload time, if present. |
| 133 bool SetJavaVM(void* java_vm, int minimum_jni_version, Error* error); |
| 134 |
| 135 // Call 'JNI_OnUnload()' is necessary, i.e. if there was a succesful call |
| 136 // to SetJavaVM() before. This will pass the same |java_vm| value to the |
| 137 // callback, if it is present in the library. |
| 138 void CallJniOnUnload(); |
| 139 |
| 140 // Helper class to iterate over dependencies in a given SharedLibrary. |
| 141 // Usage: |
| 142 // SharedLibary::DependencyIterator iter(lib); |
| 143 // while (iter.GetNext() { |
| 144 // dependency_name = iter.GetName(); |
| 145 // ... |
| 146 // } |
| 147 class DependencyIterator { |
| 148 public: |
| 149 explicit DependencyIterator(SharedLibrary* lib) |
| 150 : iter_(&lib->view_), symbols_(&lib->symbols_), dep_name_(NULL) {} |
| 151 |
| 152 bool GetNext(); |
| 153 |
| 154 const char* GetName() const { return dep_name_; } |
| 155 |
| 156 private: |
| 157 DependencyIterator(); |
| 158 DependencyIterator(const DependencyIterator&); |
| 159 DependencyIterator& operator=(const DependencyIterator&); |
| 160 |
| 161 ElfView::DynamicIterator iter_; |
| 162 const ElfSymbols* symbols_; |
| 163 const char* dep_name_; |
| 164 }; |
| 165 |
| 166 typedef void (*linker_function_t)(); |
| 167 |
| 168 private: |
| 169 friend class LibraryList; |
| 170 |
| 171 ElfView view_; |
| 172 ElfSymbols symbols_; |
| 173 |
| 174 ELF::Addr relro_start_; |
| 175 ELF::Addr relro_size_; |
| 176 bool relro_used_; |
| 177 |
| 178 SharedLibrary* list_next_; |
| 179 SharedLibrary* list_prev_; |
| 180 unsigned flags_; |
| 181 |
| 182 linker_function_t* preinit_array_; |
| 183 size_t preinit_array_count_; |
| 184 linker_function_t* init_array_; |
| 185 size_t init_array_count_; |
| 186 linker_function_t* fini_array_; |
| 187 size_t fini_array_count_; |
| 188 linker_function_t init_func_; |
| 189 linker_function_t fini_func_; |
| 190 |
| 191 #ifdef __arm__ |
| 192 // ARM EABI section used for stack unwinding. |
| 193 unsigned* arm_exidx_; |
| 194 size_t arm_exidx_count_; |
| 195 #endif |
| 196 |
| 197 link_map_t link_map_; |
| 198 |
| 199 bool has_DT_SYMBOLIC_; |
| 200 |
| 201 void* java_vm_; |
| 202 |
| 203 const char* base_name_; |
| 204 char full_path_[512]; |
| 205 }; |
| 206 |
| 207 } // namespace crazy |
| 208 |
| 209 #endif // CRAZY_LINKER_SHARED_LIBRARY_H |
OLD | NEW |