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.
5 #include "crazy_linker_shared_library.h"
12 #include "crazy_linker_ashmem.h"
13 #include "crazy_linker_debug.h"
14 #include "crazy_linker_elf_loader.h"
15 #include "crazy_linker_elf_relocations.h"
16 #include "crazy_linker_library_list.h"
17 #include "crazy_linker_library_view.h"
18 #include "crazy_linker_globals.h"
19 #include "crazy_linker_memory_mapping.h"
20 #include "crazy_linker_thread.h"
21 #include "crazy_linker_util.h"
22 #include "crazy_linker_wrappers.h"
23 #include "linker_phdr.h"
34 #define DT_INIT_ARRAY 25
37 #ifndef DT_INIT_ARRAYSZ
38 #define DT_INIT_ARRAYSZ 27
42 #define DT_FINI_ARRAY 26
45 #ifndef DT_FINI_ARRAYSZ
46 #define DT_FINI_ARRAYSZ 28
53 #ifndef DT_PREINIT_ARRAY
54 #define DT_PREINIT_ARRAY 32
57 #ifndef DT_PREINIT_ARRAYSZ
58 #define DT_PREINIT_ARRAYSZ 33
62 #define DT_LOOS 0x6000000d
65 // Extension dynamic tags for packed relocations.
66 #if defined(__arm__) || defined(__aarch64__)
68 #define DT_ANDROID_REL_OFFSET (DT_LOOS)
69 #define DT_ANDROID_REL_SIZE (DT_LOOS + 1)
71 #endif // __arm__ || __aarch64__
77 typedef SharedLibrary::linker_function_t linker_function_t;
78 typedef int (*JNI_OnLoadFunctionPtr)(void* vm, void* reserved);
79 typedef void (*JNI_OnUnloadFunctionPtr)(void* vm, void* reserved);
81 // Call a constructor or destructor function pointer. Ignore
82 // NULL and -1 values intentionally. They correspond to markers
83 // in the tables, or deleted values.
84 // |func_type| corresponds to the type of the function, and is only
85 // used for debugging (examples are "DT_INIT", "DT_INIT_ARRAY", etc...).
86 void CallFunction(linker_function_t func, const char* func_type) {
87 uintptr_t func_address = reinterpret_cast<uintptr_t>(func);
89 LOG("%s: %p %s\n", __FUNCTION__, func, func_type);
90 if (func_address != 0 && func_address != uintptr_t(-1))
94 // An instance of ElfRelocator::SymbolResolver that can be used
95 // to resolve symbols in a shared library being loaded by
96 // LibraryList::LoadLibrary.
97 class SharedLibraryResolver : public ElfRelocations::SymbolResolver {
99 SharedLibraryResolver(SharedLibrary* lib,
100 LibraryList* lib_list,
101 Vector<LibraryView*>* dependencies)
102 : lib_(lib), dependencies_(dependencies) {}
104 virtual void* Lookup(const char* symbol_name) {
105 // TODO(digit): Add the ability to lookup inside the main executable.
107 // First, look inside the current library.
108 const ELF::Sym* entry = lib_->LookupSymbolEntry(symbol_name);
110 return reinterpret_cast<void*>(lib_->load_bias() + entry->st_value);
112 // Special case: redirect the dynamic linker symbols to our wrappers.
113 // This ensures that loaded libraries can call dlopen() / dlsym()
114 // and transparently use the crazy linker to perform their duty.
115 void* address = WrapLinkerSymbol(symbol_name);
119 // Then look inside the dependencies.
120 for (size_t n = 0; n < dependencies_->GetCount(); ++n) {
121 LibraryView* wrap = (*dependencies_)[n];
122 // LOG("%s: Looking into dependency %p (%s)\n", __FUNCTION__, wrap,
124 if (wrap->IsSystem()) {
125 address = ::dlsym(wrap->GetSystem(), symbol_name);
127 // Android libm.so defines isnanf as weak. This means that its
128 // address cannot be found by dlsym(), which always returns NULL
129 // for weak symbols. However, libm.so contains the real isnanf
130 // as __isnanf. If we encounter isnanf and fail to resolve it in
131 // libm.so, retry with __isnanf.
133 // This occurs only in clang, which lacks __builtin_isnanf. The
134 // gcc compiler implements isnanf as a builtin, so the symbol
135 // isnanf never need be resolved in gcc builds.
137 // http://code.google.com/p/chromium/issues/detail?id=376828
139 !strcmp(symbol_name, "isnanf") &&
140 !strcmp(wrap->GetName(), "libm.so"))
141 address = ::dlsym(wrap->GetSystem(), "__isnanf");
146 if (wrap->IsCrazy()) {
147 SharedLibrary* dep = wrap->GetCrazy();
148 entry = dep->LookupSymbolEntry(symbol_name);
150 return reinterpret_cast<void*>(dep->load_bias() + entry->st_value);
154 // Nothing found here.
160 Vector<LibraryView*>* dependencies_;
163 #if defined(__arm__) || defined(__aarch64__)
165 // Helper class to provide a simple scoped buffer. ScopedPtr is not
166 // usable here because it calls delete, not delete [].
169 explicit ScopedBuffer(size_t bytes) : buffer_(new uint8_t[bytes]) { }
170 ~ScopedBuffer() { delete [] buffer_; }
172 uint8_t* Get() { return buffer_; }
175 uint8_t* ptr = buffer_;
184 // Read an .android.rel.dyn packed relocations section.
185 // Returns an allocated buffer holding the data, or NULL on error.
186 uint8_t* ReadPackedRelocations(const char* full_path,
191 if (!fd.OpenReadOnly(full_path)) {
192 error->Format("Error opening file '%s'", full_path);
195 if (fd.SeekTo(offset) == -1) {
196 error->Format("Error seeking to %d in file '%s'", offset, full_path);
200 ScopedBuffer buffer(bytes);
201 const ssize_t bytes_read = fd.Read(buffer.Get(), bytes);
202 if (static_cast<size_t>(bytes_read) != bytes) {
203 error->Format("Error reading %d bytes from file '%s'", bytes, full_path);
208 uint8_t* packed_data = buffer.Release();
212 #endif // __arm__ || __aarch64__
216 SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); }
218 SharedLibrary::~SharedLibrary() {
219 // Ensure the library is unmapped on destruction.
220 if (view_.load_address())
221 munmap(reinterpret_cast<void*>(view_.load_address()), view_.load_size());
223 #if defined(__arm__) || defined(__aarch64__)
224 delete [] packed_relocations_;
228 bool SharedLibrary::Load(const char* full_path,
231 bool no_map_exec_support_fallback_enabled,
233 // First, record the path.
234 LOG("%s: full path '%s'\n", __FUNCTION__, full_path);
236 size_t full_path_len = strlen(full_path);
237 if (full_path_len >= sizeof(full_path_)) {
238 error->Format("Path too long: %s", full_path);
242 strlcpy(full_path_, full_path, sizeof(full_path_));
243 base_name_ = GetBaseNamePtr(full_path_);
245 // Load the ELF binary in memory.
246 LOG("%s: Loading ELF segments for %s\n", __FUNCTION__, base_name_);
249 ElfLoader loader(no_map_exec_support_fallback_enabled);
250 if (!loader.LoadAt(full_path_, file_offset, load_address, error)) {
254 if (!view_.InitUnmapped(loader.load_start(),
255 loader.loaded_phdr(),
261 if (!symbols_.Init(&view_)) {
262 *error = "Missing or malformed symbol table";
267 if (phdr_table_get_relro_info(view_.phdr(),
277 LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_);
278 (void)phdr_table_get_arm_exidx(
279 phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_);
282 #if defined(__arm__) || defined(__aarch64__)
283 off_t packed_relocations_offset = 0;
284 size_t packed_relocations_size = 0;
287 LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_);
288 ElfView::DynamicIterator dyn(&view_);
289 for (; dyn.HasNext(); dyn.GetNext()) {
290 ELF::Addr dyn_value = dyn.GetValue();
291 uintptr_t dyn_addr = dyn.GetAddress(load_bias());
292 switch (dyn.GetTag()) {
294 if (view_.dynamic_flags() & PF_W) {
295 *dyn.GetValuePointer() =
296 reinterpret_cast<uintptr_t>(Globals::GetRDebug()->GetAddress());
300 LOG(" DT_INIT addr=%p\n", dyn_addr);
301 init_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
304 LOG(" DT_FINI addr=%p\n", dyn_addr);
305 fini_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
308 LOG(" DT_INIT_ARRAY addr=%p\n", dyn_addr);
309 init_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
311 case DT_INIT_ARRAYSZ:
312 init_array_count_ = dyn_value / sizeof(ELF::Addr);
313 LOG(" DT_INIT_ARRAYSZ value=%p count=%p\n",
318 LOG(" DT_FINI_ARRAY addr=%p\n", dyn_addr);
319 fini_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
321 case DT_FINI_ARRAYSZ:
322 fini_array_count_ = dyn_value / sizeof(ELF::Addr);
323 LOG(" DT_FINI_ARRAYSZ value=%p count=%p\n",
327 case DT_PREINIT_ARRAY:
328 LOG(" DT_PREINIT_ARRAY addr=%p\n", dyn_addr);
329 preinit_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
331 case DT_PREINIT_ARRAYSZ:
332 preinit_array_count_ = dyn_value / sizeof(ELF::Addr);
333 LOG(" DT_PREINIT_ARRAYSZ value=%p count=%p\n",
335 preinit_array_count_);
338 LOG(" DT_SYMBOLIC\n");
339 has_DT_SYMBOLIC_ = true;
342 if (dyn_value & DF_SYMBOLIC)
343 has_DT_SYMBOLIC_ = true;
345 #if defined(__arm__) || defined(__aarch64__)
346 case DT_ANDROID_REL_OFFSET:
347 packed_relocations_offset = dyn.GetOffset();
348 LOG(" DT_ANDROID_REL_OFFSET addr=%p\n", packed_relocations_offset);
350 case DT_ANDROID_REL_SIZE:
351 packed_relocations_size = dyn.GetValue();
352 LOG(" DT_ANDROID_REL_SIZE=%d\n", packed_relocations_size);
355 #if defined(__mips__)
356 case DT_MIPS_RLD_MAP:
357 *dyn.GetValuePointer() =
358 reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress());
366 #if defined(__arm__) || defined(__aarch64__)
367 // If packed relocations are present in the target library, read the
368 // section data and save it in packed_relocations_.
369 if (packed_relocations_offset && packed_relocations_size) {
370 LOG("%s: Packed relocations found at offset %d, %d bytes\n",
372 packed_relocations_offset,
373 packed_relocations_size);
375 packed_relocations_ =
376 ReadPackedRelocations(full_path,
377 packed_relocations_offset + file_offset,
378 packed_relocations_size,
380 if (!packed_relocations_)
383 LOG("%s: Packed relocations stored at %p\n",
385 packed_relocations_);
389 LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_);
393 bool SharedLibrary::Relocate(LibraryList* lib_list,
394 Vector<LibraryView*>* dependencies,
396 // Apply relocations.
397 LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_);
399 ElfRelocations relocations;
401 if (!relocations.Init(&view_, error))
404 #if defined(__arm__) || defined(__aarch64__)
405 relocations.RegisterPackedRelocations(packed_relocations_);
408 SharedLibraryResolver resolver(this, lib_list, dependencies);
409 if (!relocations.ApplyAll(&symbols_, &resolver, error))
412 LOG("%s: Relocations applied for %s\n", __FUNCTION__, base_name_);
416 const ELF::Sym* SharedLibrary::LookupSymbolEntry(const char* symbol_name) {
417 return symbols_.LookupByName(symbol_name);
420 void* SharedLibrary::FindAddressForSymbol(const char* symbol_name) {
421 return symbols_.LookupAddressByName(symbol_name, view_.load_bias());
424 bool SharedLibrary::CreateSharedRelro(size_t load_address,
431 if (!relro.Allocate(relro_size_, base_name_, error))
434 if (load_address != 0 && load_address != this->load_address()) {
435 // Need to relocate the content of the ashmem region first to accomodate
436 // for the new load address.
437 if (!relro.CopyFromRelocated(
438 &view_, load_address, relro_start_, relro_size_, error))
441 // Simply copy, no relocations.
442 if (!relro.CopyFrom(relro_start_, relro_size_, error))
446 // Enforce read-only mode for the region's content.
447 if (!relro.ForceReadOnly(error))
451 *relro_start = relro.start();
452 *relro_size = relro.size();
453 *relro_fd = relro.DetachFd();
457 bool SharedLibrary::UseSharedRelro(size_t relro_start,
461 LOG("%s: relro_start=%p relro_size=%p relro_fd=%d\n",
467 if (relro_fd < 0 || relro_size == 0) {
468 // Nothing to do here.
472 // Sanity check: A shared RELRO is not already used.
474 *error = "Library already using shared RELRO section";
478 // Sanity check: RELRO addresses must match.
479 if (relro_start_ != relro_start || relro_size_ != relro_size) {
480 error->Format("RELRO mismatch addr=%p size=%p (wanted addr=%p size=%p)",
488 // Everything's good, swap pages in this process's address space.
490 if (!relro.InitFrom(relro_start, relro_size, relro_fd, error))
497 void SharedLibrary::CallConstructors() {
498 CallFunction(init_func_, "DT_INIT");
499 for (size_t n = 0; n < init_array_count_; ++n)
500 CallFunction(init_array_[n], "DT_INIT_ARRAY");
503 void SharedLibrary::CallDestructors() {
504 for (size_t n = fini_array_count_; n > 0; --n) {
505 CallFunction(fini_array_[n - 1], "DT_FINI_ARRAY");
507 CallFunction(fini_func_, "DT_FINI");
510 bool SharedLibrary::SetJavaVM(void* java_vm,
511 int minimum_jni_version,
516 // Lookup for JNI_OnLoad, exit if it doesn't exist.
517 JNI_OnLoadFunctionPtr jni_onload = reinterpret_cast<JNI_OnLoadFunctionPtr>(
518 FindAddressForSymbol("JNI_OnLoad"));
522 int jni_version = (*jni_onload)(java_vm, NULL);
523 if (jni_version < minimum_jni_version) {
524 error->Format("JNI_OnLoad() in %s returned %d, expected at least %d",
527 minimum_jni_version);
531 // Save the JavaVM handle for unload time.
536 void SharedLibrary::CallJniOnUnload() {
540 JNI_OnUnloadFunctionPtr jni_on_unload =
541 reinterpret_cast<JNI_OnUnloadFunctionPtr>(
542 this->FindAddressForSymbol("JNI_OnUnload"));
545 (*jni_on_unload)(java_vm_, NULL);
548 bool SharedLibrary::DependencyIterator::GetNext() {
550 for (; iter_.HasNext(); iter_.GetNext()) {
551 if (iter_.GetTag() == DT_NEEDED) {
552 dep_name_ = symbols_->GetStringById(iter_.GetValue());