| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "crazy_linker_shared_library.h" | 5 #include "crazy_linker_shared_library.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 #include <sys/mman.h> | 9 #include <sys/mman.h> |
| 10 #include <elf.h> | 10 #include <elf.h> |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 // An instance of ElfRelocator::SymbolResolver that can be used | 94 // An instance of ElfRelocator::SymbolResolver that can be used |
| 95 // to resolve symbols in a shared library being loaded by | 95 // to resolve symbols in a shared library being loaded by |
| 96 // LibraryList::LoadLibrary. | 96 // LibraryList::LoadLibrary. |
| 97 class SharedLibraryResolver : public ElfRelocations::SymbolResolver { | 97 class SharedLibraryResolver : public ElfRelocations::SymbolResolver { |
| 98 public: | 98 public: |
| 99 SharedLibraryResolver(SharedLibrary* lib, | 99 SharedLibraryResolver(SharedLibrary* lib, |
| 100 LibraryList* lib_list, | 100 LibraryList* lib_list, |
| 101 Vector<LibraryView*>* preloads, | 101 Vector<LibraryView*>* preloads, |
| 102 Vector<LibraryView*>* dependencies) | 102 Vector<LibraryView*>* dependencies) |
| 103 : main_program_handle_(::dlopen(NULL, RTLD_NOW)), | 103 : main_program_handle_(::dlopen(NULL, RTLD_NOW)), |
| 104 sdk_build_version_(*Globals::GetSDKBuildVersion()), | |
| 105 lib_(lib), preloads_(preloads), dependencies_(dependencies) {} | 104 lib_(lib), preloads_(preloads), dependencies_(dependencies) {} |
| 106 | 105 |
| 107 virtual void* Lookup(const char* symbol_name) { | 106 virtual void* Lookup(const char* symbol_name) { |
| 108 // First, look inside the current library. | 107 // First, look inside the current library. |
| 109 const ELF::Sym* entry = lib_->LookupSymbolEntry(symbol_name); | 108 const ELF::Sym* entry = lib_->LookupSymbolEntry(symbol_name); |
| 110 if (entry) | 109 if (entry) |
| 111 return reinterpret_cast<void*>(lib_->load_bias() + entry->st_value); | 110 return reinterpret_cast<void*>(lib_->load_bias() + entry->st_value); |
| 112 | 111 |
| 113 // Special case: redirect the dynamic linker symbols to our wrappers. | 112 // Special case: redirect the dynamic linker symbols to our wrappers. |
| 114 // This ensures that loaded libraries can call dlopen() / dlsym() | 113 // This ensures that loaded libraries can call dlopen() / dlsym() |
| 115 // and transparently use the crazy linker to perform their duty. | 114 // and transparently use the crazy linker to perform their duty. |
| 116 void* address = WrapLinkerSymbol(symbol_name); | 115 void* address = WrapLinkerSymbol(symbol_name); |
| 117 if (address) | 116 if (address) |
| 118 return address; | 117 return address; |
| 119 | 118 |
| 120 // Make sure that we do nothing here for non-Lollipop platforms. | 119 // Then look inside the preloads. |
| 121 // In practice, preloads_ will be empty (because we ignore LD_PRELOAD | |
| 122 // when not Lollipop) and searching in the main executable should be | |
| 123 // benign. But crbug/479220 is weird enough that we want to take all | |
| 124 // possible precautions. | |
| 125 // | 120 // |
| 126 // For more, see: | 121 // Note that searching preloads *before* the main executable is opposite |
| 127 // https://code.google.com/p/chromium/issues/detail?id=479220 | 122 // to the search ordering used by the system linker, but it is required |
| 128 if (sdk_build_version_ == SDK_VERSION_CODE_LOLLIPOP) { | 123 // to work round a dlsym() bug in some Android releases (on releases |
| 129 // Then look inside the preloads. | 124 // without this dlsym() bug preloads_ will be empty, making this preloads |
| 130 // | 125 // search a no-op). |
| 131 // Note that searching preloads *before* the main executable is opposite | |
| 132 // to the search ordering used by the system linker, but it is required | |
| 133 // to work round a dlsym() bug in some Android releases (on releases | |
| 134 // without this dlsym() bug preloads_ will be empty, making this preloads | |
| 135 // search a no-op). | |
| 136 // | |
| 137 // For more, see commentary in LibraryList(), and | |
| 138 // https://code.google.com/p/android/issues/detail?id=74255 | |
| 139 for (size_t n = 0; n < preloads_->GetCount(); ++n) { | |
| 140 LibraryView* wrap = (*preloads_)[n]; | |
| 141 // LOG("%s: Looking into preload %p (%s)\n", __FUNCTION__, wrap, | |
| 142 // wrap->GetName()); | |
| 143 address = LookupInWrap(symbol_name, wrap); | |
| 144 if (address) | |
| 145 return address; | |
| 146 } | |
| 147 } | |
| 148 | |
| 149 // Do not lookup inside the main executable for pre-Lollipop, for | |
| 150 // crbug/479220. We do however want to do it for Lollipop and | |
| 151 // later, because in Lollipop-mr1 the dlsym() bug is fixed, so that | |
| 152 // we don't explicitly handle LD_PRELOADS but instead rely on dlsym | |
| 153 // correctly searching preloads via the main executable. | |
| 154 // | 126 // |
| 155 // For more, see: | 127 // For more, see commentary in LibraryList(), and |
| 156 // https://code.google.com/p/chromium/issues/detail?id=479220 | 128 // https://code.google.com/p/android/issues/detail?id=74255 |
| 157 if (sdk_build_version_ >= SDK_VERSION_CODE_LOLLIPOP) { | 129 for (size_t n = 0; n < preloads_->GetCount(); ++n) { |
| 158 // Then look inside the main executable. | 130 LibraryView* wrap = (*preloads_)[n]; |
| 159 address = ::dlsym(main_program_handle_, symbol_name); | 131 // LOG("%s: Looking into preload %p (%s)\n", __FUNCTION__, wrap, |
| 132 // wrap->GetName()); |
| 133 address = LookupInWrap(symbol_name, wrap); |
| 160 if (address) | 134 if (address) |
| 161 return address; | 135 return address; |
| 162 } | 136 } |
| 163 | 137 |
| 138 // Then lookup inside the main executable. |
| 139 address = ::dlsym(main_program_handle_, symbol_name); |
| 140 if (address) |
| 141 return address; |
| 142 |
| 164 // Then look inside the dependencies. | 143 // Then look inside the dependencies. |
| 165 for (size_t n = 0; n < dependencies_->GetCount(); ++n) { | 144 for (size_t n = 0; n < dependencies_->GetCount(); ++n) { |
| 166 LibraryView* wrap = (*dependencies_)[n]; | 145 LibraryView* wrap = (*dependencies_)[n]; |
| 167 // LOG("%s: Looking into dependency %p (%s)\n", __FUNCTION__, wrap, | 146 // LOG("%s: Looking into dependency %p (%s)\n", __FUNCTION__, wrap, |
| 168 // wrap->GetName()); | 147 // wrap->GetName()); |
| 169 address = LookupInWrap(symbol_name, wrap); | 148 address = LookupInWrap(symbol_name, wrap); |
| 170 if (address) | 149 if (address) |
| 171 return address; | 150 return address; |
| 172 } | 151 } |
| 173 | 152 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 202 if (wrap->IsCrazy()) { | 181 if (wrap->IsCrazy()) { |
| 203 SharedLibrary* crazy = wrap->GetCrazy(); | 182 SharedLibrary* crazy = wrap->GetCrazy(); |
| 204 const ELF::Sym* entry = crazy->LookupSymbolEntry(symbol_name); | 183 const ELF::Sym* entry = crazy->LookupSymbolEntry(symbol_name); |
| 205 if (entry) | 184 if (entry) |
| 206 return reinterpret_cast<void*>(crazy->load_bias() + entry->st_value); | 185 return reinterpret_cast<void*>(crazy->load_bias() + entry->st_value); |
| 207 } | 186 } |
| 208 | 187 |
| 209 return NULL; | 188 return NULL; |
| 210 } | 189 } |
| 211 | 190 |
| 212 const int sdk_build_version_; | |
| 213 void* main_program_handle_; | 191 void* main_program_handle_; |
| 214 SharedLibrary* lib_; | 192 SharedLibrary* lib_; |
| 215 Vector<LibraryView*>* preloads_; | 193 Vector<LibraryView*>* preloads_; |
| 216 Vector<LibraryView*>* dependencies_; | 194 Vector<LibraryView*>* dependencies_; |
| 217 }; | 195 }; |
| 218 | 196 |
| 219 #if defined(__arm__) || defined(__aarch64__) | 197 #if defined(__arm__) || defined(__aarch64__) |
| 220 | 198 |
| 221 // Helper class to provide a simple scoped buffer. ScopedPtr is not | 199 // Helper class to provide a simple scoped buffer. ScopedPtr is not |
| 222 // usable here because it calls delete, not delete []. | 200 // usable here because it calls delete, not delete []. |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 if (iter_.GetTag() == DT_NEEDED) { | 585 if (iter_.GetTag() == DT_NEEDED) { |
| 608 dep_name_ = symbols_->GetStringById(iter_.GetValue()); | 586 dep_name_ = symbols_->GetStringById(iter_.GetValue()); |
| 609 iter_.GetNext(); | 587 iter_.GetNext(); |
| 610 return true; | 588 return true; |
| 611 } | 589 } |
| 612 } | 590 } |
| 613 return false; | 591 return false; |
| 614 } | 592 } |
| 615 | 593 |
| 616 } // namespace crazy | 594 } // namespace crazy |
| OLD | NEW |