Home | History | Annotate | Download | only in src
      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 #include "crazy_linker_shared_library.h"
      6 
      7 #include <dlfcn.h>
      8 #include <stdlib.h>
      9 #include <sys/mman.h>
     10 #include <elf.h>
     11 
     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"
     24 
     25 #ifndef DF_SYMBOLIC
     26 #define DF_SYMBOLIC 2
     27 #endif
     28 
     29 #ifndef DF_TEXTREL
     30 #define DF_TEXTREL 4
     31 #endif
     32 
     33 #ifndef DT_INIT_ARRAY
     34 #define DT_INIT_ARRAY 25
     35 #endif
     36 
     37 #ifndef DT_INIT_ARRAYSZ
     38 #define DT_INIT_ARRAYSZ 27
     39 #endif
     40 
     41 #ifndef DT_FINI_ARRAY
     42 #define DT_FINI_ARRAY 26
     43 #endif
     44 
     45 #ifndef DT_FINI_ARRAYSZ
     46 #define DT_FINI_ARRAYSZ 28
     47 #endif
     48 
     49 #ifndef DT_FLAGS
     50 #define DT_FLAGS 30
     51 #endif
     52 
     53 #ifndef DT_PREINIT_ARRAY
     54 #define DT_PREINIT_ARRAY 32
     55 #endif
     56 
     57 #ifndef DT_PREINIT_ARRAYSZ
     58 #define DT_PREINIT_ARRAYSZ 33
     59 #endif
     60 
     61 #ifndef DT_LOOS
     62 #define DT_LOOS 0x6000000d
     63 #endif
     64 
     65 // Extension dynamic tags for packed relocations.
     66 #if defined(__arm__) || defined(__aarch64__)
     67 
     68 #define DT_ANDROID_REL_OFFSET (DT_LOOS)
     69 #define DT_ANDROID_REL_SIZE (DT_LOOS + 1)
     70 
     71 #endif  // __arm__ || __aarch64__
     72 
     73 namespace crazy {
     74 
     75 namespace {
     76 
     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);
     80 
     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);
     88 
     89   LOG("%s: %p %s\n", __FUNCTION__, func, func_type);
     90   if (func_address != 0 && func_address != uintptr_t(-1))
     91     func();
     92 }
     93 
     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 {
     98  public:
     99   SharedLibraryResolver(SharedLibrary* lib,
    100                         LibraryList* lib_list,
    101                         Vector<LibraryView*>* dependencies)
    102       : lib_(lib), dependencies_(dependencies) {}
    103 
    104   virtual void* Lookup(const char* symbol_name) {
    105     // TODO(digit): Add the ability to lookup inside the main executable.
    106 
    107     // First, look inside the current library.
    108     const ELF::Sym* entry = lib_->LookupSymbolEntry(symbol_name);
    109     if (entry)
    110       return reinterpret_cast<void*>(lib_->load_bias() + entry->st_value);
    111 
    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);
    116     if (address)
    117       return address;
    118 
    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,
    123       // wrap->GetName());
    124       if (wrap->IsSystem()) {
    125         address = ::dlsym(wrap->GetSystem(), symbol_name);
    126 #ifdef __arm__
    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.
    132         //
    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.
    136         //
    137         // http://code.google.com/p/chromium/issues/detail?id=376828
    138         if (!address &&
    139             !strcmp(symbol_name, "isnanf") &&
    140             !strcmp(wrap->GetName(), "libm.so"))
    141           address = ::dlsym(wrap->GetSystem(), "__isnanf");
    142 #endif
    143         if (address)
    144           return address;
    145       }
    146       if (wrap->IsCrazy()) {
    147         SharedLibrary* dep = wrap->GetCrazy();
    148         entry = dep->LookupSymbolEntry(symbol_name);
    149         if (entry)
    150           return reinterpret_cast<void*>(dep->load_bias() + entry->st_value);
    151       }
    152     }
    153 
    154     // Nothing found here.
    155     return NULL;
    156   }
    157 
    158  private:
    159   SharedLibrary* lib_;
    160   Vector<LibraryView*>* dependencies_;
    161 };
    162 
    163 #if defined(__arm__) || defined(__aarch64__)
    164 
    165 // Helper class to provide a simple scoped buffer.  ScopedPtr is not
    166 // usable here because it calls delete, not delete [].
    167 class ScopedBuffer {
    168  public:
    169   explicit ScopedBuffer(size_t bytes) : buffer_(new uint8_t[bytes]) { }
    170   ~ScopedBuffer() { delete [] buffer_; }
    171 
    172   uint8_t* Get() { return buffer_; }
    173 
    174   uint8_t* Release() {
    175     uint8_t* ptr = buffer_;
    176     buffer_ = NULL;
    177     return ptr;
    178   }
    179 
    180  private:
    181   uint8_t* buffer_;
    182 };
    183 
    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,
    187                                off_t offset,
    188                                size_t bytes,
    189                                Error* error) {
    190   FileDescriptor fd;
    191   if (!fd.OpenReadOnly(full_path)) {
    192     error->Format("Error opening file '%s'", full_path);
    193     return NULL;
    194   }
    195   if (fd.SeekTo(offset) == -1) {
    196     error->Format("Error seeking to %d in file '%s'", offset, full_path);
    197     return NULL;
    198   }
    199 
    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);
    204     return NULL;
    205   }
    206   fd.Close();
    207 
    208   uint8_t* packed_data = buffer.Release();
    209   return packed_data;
    210 }
    211 
    212 #endif  // __arm__ || __aarch64__
    213 
    214 }  // namespace
    215 
    216 SharedLibrary::SharedLibrary() { ::memset(this, 0, sizeof(*this)); }
    217 
    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());
    222 
    223 #if defined(__arm__) || defined(__aarch64__)
    224   delete [] packed_relocations_;
    225 #endif
    226 }
    227 
    228 bool SharedLibrary::Load(const char* full_path,
    229                          size_t load_address,
    230                          size_t file_offset,
    231                          Error* error) {
    232   // First, record the path.
    233   LOG("%s: full path '%s'\n", __FUNCTION__, full_path);
    234 
    235   size_t full_path_len = strlen(full_path);
    236   if (full_path_len >= sizeof(full_path_)) {
    237     error->Format("Path too long: %s", full_path);
    238     return false;
    239   }
    240 
    241   strlcpy(full_path_, full_path, sizeof(full_path_));
    242   base_name_ = GetBaseNamePtr(full_path_);
    243 
    244   // Load the ELF binary in memory.
    245   LOG("%s: Loading ELF segments for %s\n", __FUNCTION__, base_name_);
    246 
    247   {
    248     ElfLoader loader;
    249     if (!loader.LoadAt(full_path_, file_offset, load_address, error)) {
    250       return false;
    251     }
    252 
    253     if (!view_.InitUnmapped(loader.load_start(),
    254                             loader.loaded_phdr(),
    255                             loader.phdr_count(),
    256                             error)) {
    257       return false;
    258     }
    259 
    260     if (!symbols_.Init(&view_)) {
    261       *error = "Missing or malformed symbol table";
    262       return false;
    263     }
    264   }
    265 
    266   if (phdr_table_get_relro_info(view_.phdr(),
    267                                 view_.phdr_count(),
    268                                 view_.load_bias(),
    269                                 &relro_start_,
    270                                 &relro_size_) < 0) {
    271     relro_start_ = 0;
    272     relro_size_ = 0;
    273   }
    274 
    275 #ifdef __arm__
    276   LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_);
    277   (void)phdr_table_get_arm_exidx(
    278       phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_);
    279 #endif
    280 
    281 #if defined(__arm__) || defined(__aarch64__)
    282   off_t packed_relocations_offset = 0;
    283   size_t packed_relocations_size = 0;
    284 #endif
    285 
    286   LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_);
    287   ElfView::DynamicIterator dyn(&view_);
    288   for (; dyn.HasNext(); dyn.GetNext()) {
    289     ELF::Addr dyn_value = dyn.GetValue();
    290     uintptr_t dyn_addr = dyn.GetAddress(load_bias());
    291     switch (dyn.GetTag()) {
    292       case DT_DEBUG:
    293         if (view_.dynamic_flags() & PF_W) {
    294           *dyn.GetValuePointer() =
    295               reinterpret_cast<uintptr_t>(Globals::GetRDebug()->GetAddress());
    296         }
    297         break;
    298       case DT_INIT:
    299         LOG("  DT_INIT addr=%p\n", dyn_addr);
    300         init_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
    301         break;
    302       case DT_FINI:
    303         LOG("  DT_FINI addr=%p\n", dyn_addr);
    304         fini_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
    305         break;
    306       case DT_INIT_ARRAY:
    307         LOG("  DT_INIT_ARRAY addr=%p\n", dyn_addr);
    308         init_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
    309         break;
    310       case DT_INIT_ARRAYSZ:
    311         init_array_count_ = dyn_value / sizeof(ELF::Addr);
    312         LOG("  DT_INIT_ARRAYSZ value=%p count=%p\n",
    313             dyn_value,
    314             init_array_count_);
    315         break;
    316       case DT_FINI_ARRAY:
    317         LOG("  DT_FINI_ARRAY addr=%p\n", dyn_addr);
    318         fini_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
    319         break;
    320       case DT_FINI_ARRAYSZ:
    321         fini_array_count_ = dyn_value / sizeof(ELF::Addr);
    322         LOG("  DT_FINI_ARRAYSZ value=%p count=%p\n",
    323             dyn_value,
    324             fini_array_count_);
    325         break;
    326       case DT_PREINIT_ARRAY:
    327         LOG("  DT_PREINIT_ARRAY addr=%p\n", dyn_addr);
    328         preinit_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
    329         break;
    330       case DT_PREINIT_ARRAYSZ:
    331         preinit_array_count_ = dyn_value / sizeof(ELF::Addr);
    332         LOG("  DT_PREINIT_ARRAYSZ value=%p count=%p\n",
    333             dyn_value,
    334             preinit_array_count_);
    335         break;
    336       case DT_SYMBOLIC:
    337         LOG("  DT_SYMBOLIC\n");
    338         has_DT_SYMBOLIC_ = true;
    339         break;
    340       case DT_FLAGS:
    341         if (dyn_value & DF_SYMBOLIC)
    342           has_DT_SYMBOLIC_ = true;
    343         break;
    344 #if defined(__arm__) || defined(__aarch64__)
    345       case DT_ANDROID_REL_OFFSET:
    346         packed_relocations_offset = dyn.GetOffset();
    347         LOG("  DT_ANDROID_REL_OFFSET addr=%p\n", packed_relocations_offset);
    348         break;
    349       case DT_ANDROID_REL_SIZE:
    350         packed_relocations_size = dyn.GetValue();
    351         LOG("  DT_ANDROID_REL_SIZE=%d\n", packed_relocations_size);
    352         break;
    353 #endif
    354 #if defined(__mips__)
    355       case DT_MIPS_RLD_MAP:
    356         *dyn.GetValuePointer() =
    357             reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress());
    358         break;
    359 #endif
    360       default:
    361         ;
    362     }
    363   }
    364 
    365 #if defined(__arm__) || defined(__aarch64__)
    366   // If packed relocations are present in the target library, read the
    367   // section data and save it in packed_relocations_.
    368   if (packed_relocations_offset && packed_relocations_size) {
    369     LOG("%s: Packed relocations found at offset %d, %d bytes\n",
    370         __FUNCTION__,
    371         packed_relocations_offset,
    372         packed_relocations_size);
    373 
    374     packed_relocations_ =
    375         ReadPackedRelocations(full_path,
    376                               packed_relocations_offset + file_offset,
    377                               packed_relocations_size,
    378                               error);
    379     if (!packed_relocations_)
    380       return false;
    381 
    382     LOG("%s: Packed relocations stored at %p\n",
    383         __FUNCTION__,
    384         packed_relocations_);
    385   }
    386 #endif
    387 
    388   LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_);
    389   return true;
    390 }
    391 
    392 bool SharedLibrary::Relocate(LibraryList* lib_list,
    393                              Vector<LibraryView*>* dependencies,
    394                              Error* error) {
    395   // Apply relocations.
    396   LOG("%s: Applying relocations to %s\n", __FUNCTION__, base_name_);
    397 
    398   ElfRelocations relocations;
    399 
    400   if (!relocations.Init(&view_, error))
    401     return false;
    402 
    403 #if defined(__arm__) || defined(__aarch64__)
    404   relocations.RegisterPackedRelocations(packed_relocations_);
    405 #endif
    406 
    407   SharedLibraryResolver resolver(this, lib_list, dependencies);
    408   if (!relocations.ApplyAll(&symbols_, &resolver, error))
    409     return false;
    410 
    411   LOG("%s: Relocations applied for %s\n", __FUNCTION__, base_name_);
    412   return true;
    413 }
    414 
    415 const ELF::Sym* SharedLibrary::LookupSymbolEntry(const char* symbol_name) {
    416   return symbols_.LookupByName(symbol_name);
    417 }
    418 
    419 void* SharedLibrary::FindAddressForSymbol(const char* symbol_name) {
    420   return symbols_.LookupAddressByName(symbol_name, view_.load_bias());
    421 }
    422 
    423 bool SharedLibrary::CreateSharedRelro(size_t load_address,
    424                                       size_t* relro_start,
    425                                       size_t* relro_size,
    426                                       int* relro_fd,
    427                                       Error* error) {
    428   SharedRelro relro;
    429 
    430   if (!relro.Allocate(relro_size_, base_name_, error))
    431     return false;
    432 
    433   if (load_address != 0 && load_address != this->load_address()) {
    434     // Need to relocate the content of the ashmem region first to accomodate
    435     // for the new load address.
    436     if (!relro.CopyFromRelocated(
    437              &view_, load_address, relro_start_, relro_size_, error))
    438       return false;
    439   } else {
    440     // Simply copy, no relocations.
    441     if (!relro.CopyFrom(relro_start_, relro_size_, error))
    442       return false;
    443   }
    444 
    445   // Enforce read-only mode for the region's content.
    446   if (!relro.ForceReadOnly(error))
    447     return false;
    448 
    449   // All good.
    450   *relro_start = relro.start();
    451   *relro_size = relro.size();
    452   *relro_fd = relro.DetachFd();
    453   return true;
    454 }
    455 
    456 bool SharedLibrary::UseSharedRelro(size_t relro_start,
    457                                    size_t relro_size,
    458                                    int relro_fd,
    459                                    Error* error) {
    460   LOG("%s: relro_start=%p relro_size=%p relro_fd=%d\n",
    461       __FUNCTION__,
    462       (void*)relro_start,
    463       (void*)relro_size,
    464       relro_fd);
    465 
    466   if (relro_fd < 0 || relro_size == 0) {
    467     // Nothing to do here.
    468     return true;
    469   }
    470 
    471   // Sanity check: A shared RELRO is not already used.
    472   if (relro_used_) {
    473     *error = "Library already using shared RELRO section";
    474     return false;
    475   }
    476 
    477   // Sanity check: RELRO addresses must match.
    478   if (relro_start_ != relro_start || relro_size_ != relro_size) {
    479     error->Format("RELRO mismatch addr=%p size=%p (wanted addr=%p size=%p)",
    480                   relro_start_,
    481                   relro_size_,
    482                   relro_start,
    483                   relro_size);
    484     return false;
    485   }
    486 
    487   // Everything's good, swap pages in this process's address space.
    488   SharedRelro relro;
    489   if (!relro.InitFrom(relro_start, relro_size, relro_fd, error))
    490     return false;
    491 
    492   relro_used_ = true;
    493   return true;
    494 }
    495 
    496 void SharedLibrary::CallConstructors() {
    497   CallFunction(init_func_, "DT_INIT");
    498   for (size_t n = 0; n < init_array_count_; ++n)
    499     CallFunction(init_array_[n], "DT_INIT_ARRAY");
    500 }
    501 
    502 void SharedLibrary::CallDestructors() {
    503   for (size_t n = fini_array_count_; n > 0; --n) {
    504     CallFunction(fini_array_[n - 1], "DT_FINI_ARRAY");
    505   }
    506   CallFunction(fini_func_, "DT_FINI");
    507 }
    508 
    509 bool SharedLibrary::SetJavaVM(void* java_vm,
    510                               int minimum_jni_version,
    511                               Error* error) {
    512   if (java_vm == NULL)
    513     return true;
    514 
    515   // Lookup for JNI_OnLoad, exit if it doesn't exist.
    516   JNI_OnLoadFunctionPtr jni_onload = reinterpret_cast<JNI_OnLoadFunctionPtr>(
    517       FindAddressForSymbol("JNI_OnLoad"));
    518   if (!jni_onload)
    519     return true;
    520 
    521   int jni_version = (*jni_onload)(java_vm, NULL);
    522   if (jni_version < minimum_jni_version) {
    523     error->Format("JNI_OnLoad() in %s returned %d, expected at least %d",
    524                   full_path_,
    525                   jni_version,
    526                   minimum_jni_version);
    527     return false;
    528   }
    529 
    530   // Save the JavaVM handle for unload time.
    531   java_vm_ = java_vm;
    532   return true;
    533 }
    534 
    535 void SharedLibrary::CallJniOnUnload() {
    536   if (!java_vm_)
    537     return;
    538 
    539   JNI_OnUnloadFunctionPtr jni_on_unload =
    540       reinterpret_cast<JNI_OnUnloadFunctionPtr>(
    541           this->FindAddressForSymbol("JNI_OnUnload"));
    542 
    543   if (jni_on_unload)
    544     (*jni_on_unload)(java_vm_, NULL);
    545 }
    546 
    547 bool SharedLibrary::DependencyIterator::GetNext() {
    548   dep_name_ = NULL;
    549   for (; iter_.HasNext(); iter_.GetNext()) {
    550     if (iter_.GetTag() == DT_NEEDED) {
    551       dep_name_ = symbols_->GetStringById(iter_.GetValue());
    552       iter_.GetNext();
    553       return true;
    554     }
    555   }
    556   return false;
    557 }
    558 
    559 }  // namespace crazy
    560