1 // Copyright (c) 2013 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 load_address()36 size_t load_address() const { return view_.load_address(); } load_size()37 size_t load_size() const { return view_.load_size(); } load_bias()38 size_t load_bias() const { return view_.load_bias(); } phdr()39 const ELF::Phdr* phdr() const { return view_.phdr(); } phdr_count()40 size_t phdr_count() const { return view_.phdr_count(); } base_name()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*>* dependencies, 63 Error* error); 64 GetInfo(size_t * load_address,size_t * load_size,size_t * relro_start,size_t * relro_size)65 void GetInfo(size_t* load_address, 66 size_t* load_size, 67 size_t* relro_start, 68 size_t* relro_size) { 69 *load_address = view_.load_address(); 70 *load_size = view_.load_size(); 71 *relro_start = relro_start_; 72 *relro_size = relro_size_; 73 } 74 75 // Returns true iff a given library is mapped to a virtual address range 76 // that contains a given address. ContainsAddress(void * address)77 bool ContainsAddress(void* address) const { 78 size_t addr = reinterpret_cast<size_t>(address); 79 return load_address() <= addr && addr <= load_address() + load_size(); 80 } 81 82 // Call all constructors in the library. 83 void CallConstructors(); 84 85 // Call all destructors in the library. 86 void CallDestructors(); 87 88 // Return the ELF symbol entry for a given symbol, if defined by 89 // this library, or NULL otherwise. 90 const ELF::Sym* LookupSymbolEntry(const char* symbol_name); 91 92 // Find the nearest symbol near a given |address|. On success, return 93 // true and set |*sym_name| to the symbol name, |*sym_addr| to its address 94 // in memory, and |*sym_size| to its size in bytes, if any. FindNearestSymbolForAddress(void * address,const char ** sym_name,void ** sym_addr,size_t * sym_size)95 bool FindNearestSymbolForAddress(void* address, 96 const char** sym_name, 97 void** sym_addr, 98 size_t* sym_size) { 99 return symbols_.LookupNearestByAddress( 100 address, load_bias(), sym_name, sym_addr, sym_size); 101 } 102 103 // Return the address of a given |symbol_name| if it is exported 104 // by the library, NULL otherwise. 105 void* FindAddressForSymbol(const char* symbol_name); 106 107 // Create a new Ashmem region holding a copy of the library's RELRO section, 108 // potentially relocated for a new |load_address|. On success, return true 109 // and sets |*relro_start|, |*relro_size| and |*relro_fd|. Note that the 110 // RELRO start address is adjusted for |load_address|, and that the caller 111 // becomes the owner of |*relro_fd|. On failure, return false and set 112 // |error| message. 113 bool CreateSharedRelro(size_t load_address, 114 size_t* relro_start, 115 size_t* relro_size, 116 int* relro_fd, 117 Error* error); 118 119 // Try to use a shared relro section from another process. 120 // On success, return true. On failure return false and 121 // sets |error| message. 122 bool UseSharedRelro(size_t relro_start, 123 size_t relro_size, 124 int relro_fd, 125 Error* error); 126 127 // Look for a symbol named 'JNI_OnLoad' in this library, and if it 128 // exists, call it with |java_vm| as the first parameter. If the 129 // function result is less than |minimum_jni_version|, fail with 130 // a message in |error|. On success, return true, and record 131 // |java_vm| to call 'JNI_OnUnload' at unload time, if present. 132 bool SetJavaVM(void* java_vm, int minimum_jni_version, Error* error); 133 134 // Call 'JNI_OnUnload()' is necessary, i.e. if there was a succesful call 135 // to SetJavaVM() before. This will pass the same |java_vm| value to the 136 // callback, if it is present in the library. 137 void CallJniOnUnload(); 138 139 // Helper class to iterate over dependencies in a given SharedLibrary. 140 // Usage: 141 // SharedLibary::DependencyIterator iter(lib); 142 // while (iter.GetNext() { 143 // dependency_name = iter.GetName(); 144 // ... 145 // } 146 class DependencyIterator { 147 public: DependencyIterator(SharedLibrary * lib)148 DependencyIterator(SharedLibrary* lib) 149 : iter_(&lib->view_), symbols_(&lib->symbols_), dep_name_(NULL) {} 150 151 bool GetNext(); 152 GetName()153 const char* GetName() const { return dep_name_; } 154 155 private: 156 DependencyIterator(); 157 DependencyIterator(const DependencyIterator&); 158 DependencyIterator& operator=(const DependencyIterator&); 159 160 ElfView::DynamicIterator iter_; 161 const ElfSymbols* symbols_; 162 const char* dep_name_; 163 }; 164 165 typedef void (*linker_function_t)(); 166 167 private: 168 friend class LibraryList; 169 170 ElfView view_; 171 ElfSymbols symbols_; 172 173 ELF::Addr relro_start_; 174 ELF::Addr relro_size_; 175 bool relro_used_; 176 177 SharedLibrary* list_next_; 178 SharedLibrary* list_prev_; 179 unsigned flags_; 180 181 linker_function_t* preinit_array_; 182 size_t preinit_array_count_; 183 linker_function_t* init_array_; 184 size_t init_array_count_; 185 linker_function_t* fini_array_; 186 size_t fini_array_count_; 187 linker_function_t init_func_; 188 linker_function_t fini_func_; 189 190 #ifdef __arm__ 191 // ARM EABI section used for stack unwinding. 192 unsigned* arm_exidx_; 193 size_t arm_exidx_count_; 194 #endif 195 196 link_map_t link_map_; 197 198 bool has_DT_SYMBOLIC_; 199 200 void* java_vm_; 201 202 const char* base_name_; 203 char full_path_[512]; 204 }; 205 206 } // namespace crazy 207 208 #endif // CRAZY_LINKER_SHARED_LIBRARY_H 209