Home | History | Annotate | Download | only in linker
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include "linker_soinfo.h"
     30 
     31 #include <dlfcn.h>
     32 #include <elf.h>
     33 #include <string.h>
     34 #include <sys/stat.h>
     35 #include <unistd.h>
     36 
     37 #include "linker_debug.h"
     38 #include "linker_globals.h"
     39 #include "linker_logger.h"
     40 #include "linker_utils.h"
     41 
     42 // TODO(dimitry): These functions are currently located in linker.cpp - find a better place for it
     43 bool find_verdef_version_index(const soinfo* si, const version_info* vi, ElfW(Versym)* versym);
     44 ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr);
     45 uint32_t get_application_target_sdk_version();
     46 
     47 soinfo::soinfo(android_namespace_t* ns, const char* realpath,
     48                const struct stat* file_stat, off64_t file_offset,
     49                int rtld_flags) {
     50   memset(this, 0, sizeof(*this));
     51 
     52   if (realpath != nullptr) {
     53     realpath_ = realpath;
     54   }
     55 
     56   flags_ = FLAG_NEW_SOINFO;
     57   version_ = SOINFO_VERSION;
     58 
     59   if (file_stat != nullptr) {
     60     this->st_dev_ = file_stat->st_dev;
     61     this->st_ino_ = file_stat->st_ino;
     62     this->file_offset_ = file_offset;
     63   }
     64 
     65   this->rtld_flags_ = rtld_flags;
     66   this->primary_namespace_ = ns;
     67 }
     68 
     69 soinfo::~soinfo() {
     70   g_soinfo_handles_map.erase(handle_);
     71 }
     72 
     73 void soinfo::set_dt_runpath(const char* path) {
     74   if (!has_min_version(3)) {
     75     return;
     76   }
     77 
     78   std::vector<std::string> runpaths;
     79 
     80   split_path(path, ":", &runpaths);
     81 
     82   std::string origin = dirname(get_realpath());
     83   // FIXME: add $LIB and $PLATFORM.
     84   std::vector<std::pair<std::string, std::string>> params = {{"ORIGIN", origin}};
     85   for (auto&& s : runpaths) {
     86     format_string(&s, params);
     87   }
     88 
     89   resolve_paths(runpaths, &dt_runpath_);
     90 }
     91 
     92 const ElfW(Versym)* soinfo::get_versym(size_t n) const {
     93   if (has_min_version(2) && versym_ != nullptr) {
     94     return versym_ + n;
     95   }
     96 
     97   return nullptr;
     98 }
     99 
    100 ElfW(Addr) soinfo::get_verneed_ptr() const {
    101   if (has_min_version(2)) {
    102     return verneed_ptr_;
    103   }
    104 
    105   return 0;
    106 }
    107 
    108 size_t soinfo::get_verneed_cnt() const {
    109   if (has_min_version(2)) {
    110     return verneed_cnt_;
    111   }
    112 
    113   return 0;
    114 }
    115 
    116 ElfW(Addr) soinfo::get_verdef_ptr() const {
    117   if (has_min_version(2)) {
    118     return verdef_ptr_;
    119   }
    120 
    121   return 0;
    122 }
    123 
    124 size_t soinfo::get_verdef_cnt() const {
    125   if (has_min_version(2)) {
    126     return verdef_cnt_;
    127   }
    128 
    129   return 0;
    130 }
    131 
    132 bool soinfo::find_symbol_by_name(SymbolName& symbol_name,
    133                                  const version_info* vi,
    134                                  const ElfW(Sym)** symbol) const {
    135   uint32_t symbol_index;
    136   bool success =
    137       is_gnu_hash() ?
    138       gnu_lookup(symbol_name, vi, &symbol_index) :
    139       elf_lookup(symbol_name, vi, &symbol_index);
    140 
    141   if (success) {
    142     *symbol = symbol_index == 0 ? nullptr : symtab_ + symbol_index;
    143   }
    144 
    145   return success;
    146 }
    147 
    148 static bool is_symbol_global_and_defined(const soinfo* si, const ElfW(Sym)* s) {
    149   if (ELF_ST_BIND(s->st_info) == STB_GLOBAL ||
    150       ELF_ST_BIND(s->st_info) == STB_WEAK) {
    151     return s->st_shndx != SHN_UNDEF;
    152   } else if (ELF_ST_BIND(s->st_info) != STB_LOCAL) {
    153     DL_WARN("unexpected ST_BIND value: %d for \"%s\" in \"%s\"",
    154             ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_realpath());
    155   }
    156 
    157   return false;
    158 }
    159 
    160 static const ElfW(Versym) kVersymHiddenBit = 0x8000;
    161 
    162 static inline bool is_versym_hidden(const ElfW(Versym)* versym) {
    163   // the symbol is hidden if bit 15 of versym is set.
    164   return versym != nullptr && (*versym & kVersymHiddenBit) != 0;
    165 }
    166 
    167 static inline bool check_symbol_version(const ElfW(Versym) verneed,
    168                                         const ElfW(Versym)* verdef) {
    169   return verneed == kVersymNotNeeded ||
    170       verdef == nullptr ||
    171       verneed == (*verdef & ~kVersymHiddenBit);
    172 }
    173 
    174 bool soinfo::gnu_lookup(SymbolName& symbol_name,
    175                         const version_info* vi,
    176                         uint32_t* symbol_index) const {
    177   uint32_t hash = symbol_name.gnu_hash();
    178   uint32_t h2 = hash >> gnu_shift2_;
    179 
    180   uint32_t bloom_mask_bits = sizeof(ElfW(Addr))*8;
    181   uint32_t word_num = (hash / bloom_mask_bits) & gnu_maskwords_;
    182   ElfW(Addr) bloom_word = gnu_bloom_filter_[word_num];
    183 
    184   *symbol_index = 0;
    185 
    186   TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p (gnu)",
    187       symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
    188 
    189   // test against bloom filter
    190   if ((1 & (bloom_word >> (hash % bloom_mask_bits)) & (bloom_word >> (h2 % bloom_mask_bits))) == 0) {
    191     TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
    192         symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
    193 
    194     return true;
    195   }
    196 
    197   // bloom test says "probably yes"...
    198   uint32_t n = gnu_bucket_[hash % gnu_nbucket_];
    199 
    200   if (n == 0) {
    201     TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
    202         symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
    203 
    204     return true;
    205   }
    206 
    207   // lookup versym for the version definition in this library
    208   // note the difference between "version is not requested" (vi == nullptr)
    209   // and "version not found". In the first case verneed is kVersymNotNeeded
    210   // which implies that the default version can be accepted; the second case results in
    211   // verneed = 1 (kVersymGlobal) and implies that we should ignore versioned symbols
    212   // for this library and consider only *global* ones.
    213   ElfW(Versym) verneed = 0;
    214   if (!find_verdef_version_index(this, vi, &verneed)) {
    215     return false;
    216   }
    217 
    218   do {
    219     ElfW(Sym)* s = symtab_ + n;
    220     const ElfW(Versym)* verdef = get_versym(n);
    221     // skip hidden versions when verneed == kVersymNotNeeded (0)
    222     if (verneed == kVersymNotNeeded && is_versym_hidden(verdef)) {
    223         continue;
    224     }
    225     if (((gnu_chain_[n] ^ hash) >> 1) == 0 &&
    226         check_symbol_version(verneed, verdef) &&
    227         strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
    228         is_symbol_global_and_defined(this, s)) {
    229       TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
    230           symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(s->st_value),
    231           static_cast<size_t>(s->st_size));
    232       *symbol_index = n;
    233       return true;
    234     }
    235   } while ((gnu_chain_[n++] & 1) == 0);
    236 
    237   TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
    238              symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
    239 
    240   return true;
    241 }
    242 
    243 bool soinfo::elf_lookup(SymbolName& symbol_name,
    244                         const version_info* vi,
    245                         uint32_t* symbol_index) const {
    246   uint32_t hash = symbol_name.elf_hash();
    247 
    248   TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p h=%x(elf) %zd",
    249              symbol_name.get_name(), get_realpath(),
    250              reinterpret_cast<void*>(base), hash, hash % nbucket_);
    251 
    252   ElfW(Versym) verneed = 0;
    253   if (!find_verdef_version_index(this, vi, &verneed)) {
    254     return false;
    255   }
    256 
    257   for (uint32_t n = bucket_[hash % nbucket_]; n != 0; n = chain_[n]) {
    258     ElfW(Sym)* s = symtab_ + n;
    259     const ElfW(Versym)* verdef = get_versym(n);
    260 
    261     // skip hidden versions when verneed == 0
    262     if (verneed == kVersymNotNeeded && is_versym_hidden(verdef)) {
    263         continue;
    264     }
    265 
    266     if (check_symbol_version(verneed, verdef) &&
    267         strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
    268         is_symbol_global_and_defined(this, s)) {
    269       TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
    270                  symbol_name.get_name(), get_realpath(),
    271                  reinterpret_cast<void*>(s->st_value),
    272                  static_cast<size_t>(s->st_size));
    273       *symbol_index = n;
    274       return true;
    275     }
    276   }
    277 
    278   TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
    279              symbol_name.get_name(), get_realpath(),
    280              reinterpret_cast<void*>(base), hash, hash % nbucket_);
    281 
    282   *symbol_index = 0;
    283   return true;
    284 }
    285 
    286 ElfW(Sym)* soinfo::find_symbol_by_address(const void* addr) {
    287   return is_gnu_hash() ? gnu_addr_lookup(addr) : elf_addr_lookup(addr);
    288 }
    289 
    290 static bool symbol_matches_soaddr(const ElfW(Sym)* sym, ElfW(Addr) soaddr) {
    291   return sym->st_shndx != SHN_UNDEF &&
    292       soaddr >= sym->st_value &&
    293       soaddr < sym->st_value + sym->st_size;
    294 }
    295 
    296 ElfW(Sym)* soinfo::gnu_addr_lookup(const void* addr) {
    297   ElfW(Addr) soaddr = reinterpret_cast<ElfW(Addr)>(addr) - load_bias;
    298 
    299   for (size_t i = 0; i < gnu_nbucket_; ++i) {
    300     uint32_t n = gnu_bucket_[i];
    301 
    302     if (n == 0) {
    303       continue;
    304     }
    305 
    306     do {
    307       ElfW(Sym)* sym = symtab_ + n;
    308       if (symbol_matches_soaddr(sym, soaddr)) {
    309         return sym;
    310       }
    311     } while ((gnu_chain_[n++] & 1) == 0);
    312   }
    313 
    314   return nullptr;
    315 }
    316 
    317 ElfW(Sym)* soinfo::elf_addr_lookup(const void* addr) {
    318   ElfW(Addr) soaddr = reinterpret_cast<ElfW(Addr)>(addr) - load_bias;
    319 
    320   // Search the library's symbol table for any defined symbol which
    321   // contains this address.
    322   for (size_t i = 0; i < nchain_; ++i) {
    323     ElfW(Sym)* sym = symtab_ + i;
    324     if (symbol_matches_soaddr(sym, soaddr)) {
    325       return sym;
    326     }
    327   }
    328 
    329   return nullptr;
    330 }
    331 
    332 static void call_function(const char* function_name __unused,
    333                           linker_ctor_function_t function,
    334                           const char* realpath __unused) {
    335   if (function == nullptr || reinterpret_cast<uintptr_t>(function) == static_cast<uintptr_t>(-1)) {
    336     return;
    337   }
    338 
    339   TRACE("[ Calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
    340   function(g_argc, g_argv, g_envp);
    341   TRACE("[ Done calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
    342 }
    343 
    344 static void call_function(const char* function_name __unused,
    345                           linker_dtor_function_t function,
    346                           const char* realpath __unused) {
    347   if (function == nullptr || reinterpret_cast<uintptr_t>(function) == static_cast<uintptr_t>(-1)) {
    348     return;
    349   }
    350 
    351   TRACE("[ Calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
    352   function();
    353   TRACE("[ Done calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
    354 }
    355 
    356 template <typename F>
    357 static void call_array(const char* array_name __unused,
    358                        F* functions,
    359                        size_t count,
    360                        bool reverse,
    361                        const char* realpath) {
    362   if (functions == nullptr) {
    363     return;
    364   }
    365 
    366   TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, realpath);
    367 
    368   int begin = reverse ? (count - 1) : 0;
    369   int end = reverse ? -1 : count;
    370   int step = reverse ? -1 : 1;
    371 
    372   for (int i = begin; i != end; i += step) {
    373     TRACE("[ %s[%d] == %p ]", array_name, i, functions[i]);
    374     call_function("function", functions[i], realpath);
    375   }
    376 
    377   TRACE("[ Done calling %s for '%s' ]", array_name, realpath);
    378 }
    379 
    380 void soinfo::call_pre_init_constructors() {
    381   // DT_PREINIT_ARRAY functions are called before any other constructors for executables,
    382   // but ignored in a shared library.
    383   call_array("DT_PREINIT_ARRAY", preinit_array_, preinit_array_count_, false, get_realpath());
    384 }
    385 
    386 void soinfo::call_constructors() {
    387   if (constructors_called) {
    388     return;
    389   }
    390 
    391   // We set constructors_called before actually calling the constructors, otherwise it doesn't
    392   // protect against recursive constructor calls. One simple example of constructor recursion
    393   // is the libc debug malloc, which is implemented in libc_malloc_debug_leak.so:
    394   // 1. The program depends on libc, so libc's constructor is called here.
    395   // 2. The libc constructor calls dlopen() to load libc_malloc_debug_leak.so.
    396   // 3. dlopen() calls the constructors on the newly created
    397   //    soinfo for libc_malloc_debug_leak.so.
    398   // 4. The debug .so depends on libc, so CallConstructors is
    399   //    called again with the libc soinfo. If it doesn't trigger the early-
    400   //    out above, the libc constructor will be called again (recursively!).
    401   constructors_called = true;
    402 
    403   if (!is_main_executable() && preinit_array_ != nullptr) {
    404     // The GNU dynamic linker silently ignores these, but we warn the developer.
    405     PRINT("\"%s\": ignoring DT_PREINIT_ARRAY in shared library!", get_realpath());
    406   }
    407 
    408   get_children().for_each([] (soinfo* si) {
    409     si->call_constructors();
    410   });
    411 
    412   if (!is_linker()) {
    413     bionic_trace_begin((std::string("calling constructors: ") + get_realpath()).c_str());
    414   }
    415 
    416   // DT_INIT should be called before DT_INIT_ARRAY if both are present.
    417   call_function("DT_INIT", init_func_, get_realpath());
    418   call_array("DT_INIT_ARRAY", init_array_, init_array_count_, false, get_realpath());
    419 
    420   if (!is_linker()) {
    421     bionic_trace_end();
    422   }
    423 }
    424 
    425 void soinfo::call_destructors() {
    426   if (!constructors_called) {
    427     return;
    428   }
    429 
    430   ScopedTrace trace((std::string("calling destructors: ") + get_realpath()).c_str());
    431 
    432   // DT_FINI_ARRAY must be parsed in reverse order.
    433   call_array("DT_FINI_ARRAY", fini_array_, fini_array_count_, true, get_realpath());
    434 
    435   // DT_FINI should be called after DT_FINI_ARRAY if both are present.
    436   call_function("DT_FINI", fini_func_, get_realpath());
    437 }
    438 
    439 void soinfo::add_child(soinfo* child) {
    440   if (has_min_version(0)) {
    441     child->parents_.push_back(this);
    442     this->children_.push_back(child);
    443   }
    444 }
    445 
    446 void soinfo::remove_all_links() {
    447   if (!has_min_version(0)) {
    448     return;
    449   }
    450 
    451   // 1. Untie connected soinfos from 'this'.
    452   children_.for_each([&] (soinfo* child) {
    453     child->parents_.remove_if([&] (const soinfo* parent) {
    454       return parent == this;
    455     });
    456   });
    457 
    458   parents_.for_each([&] (soinfo* parent) {
    459     parent->children_.remove_if([&] (const soinfo* child) {
    460       return child == this;
    461     });
    462   });
    463 
    464   // 2. Remove from the primary namespace
    465   primary_namespace_->remove_soinfo(this);
    466   primary_namespace_ = nullptr;
    467 
    468   // 3. Remove from secondary namespaces
    469   secondary_namespaces_.for_each([&](android_namespace_t* ns) {
    470     ns->remove_soinfo(this);
    471   });
    472 
    473 
    474   // 4. Once everything untied - clear local lists.
    475   parents_.clear();
    476   children_.clear();
    477   secondary_namespaces_.clear();
    478 }
    479 
    480 dev_t soinfo::get_st_dev() const {
    481   if (has_min_version(0)) {
    482     return st_dev_;
    483   }
    484 
    485   return 0;
    486 };
    487 
    488 ino_t soinfo::get_st_ino() const {
    489   if (has_min_version(0)) {
    490     return st_ino_;
    491   }
    492 
    493   return 0;
    494 }
    495 
    496 off64_t soinfo::get_file_offset() const {
    497   if (has_min_version(1)) {
    498     return file_offset_;
    499   }
    500 
    501   return 0;
    502 }
    503 
    504 uint32_t soinfo::get_rtld_flags() const {
    505   if (has_min_version(1)) {
    506     return rtld_flags_;
    507   }
    508 
    509   return 0;
    510 }
    511 
    512 uint32_t soinfo::get_dt_flags_1() const {
    513   if (has_min_version(1)) {
    514     return dt_flags_1_;
    515   }
    516 
    517   return 0;
    518 }
    519 
    520 void soinfo::set_dt_flags_1(uint32_t dt_flags_1) {
    521   if (has_min_version(1)) {
    522     if ((dt_flags_1 & DF_1_GLOBAL) != 0) {
    523       rtld_flags_ |= RTLD_GLOBAL;
    524     }
    525 
    526     if ((dt_flags_1 & DF_1_NODELETE) != 0) {
    527       rtld_flags_ |= RTLD_NODELETE;
    528     }
    529 
    530     dt_flags_1_ = dt_flags_1;
    531   }
    532 }
    533 
    534 void soinfo::set_nodelete() {
    535   rtld_flags_ |= RTLD_NODELETE;
    536 }
    537 
    538 const char* soinfo::get_realpath() const {
    539 #if defined(__work_around_b_24465209__)
    540   if (has_min_version(2)) {
    541     return realpath_.c_str();
    542   } else {
    543     return old_name_;
    544   }
    545 #else
    546   return realpath_.c_str();
    547 #endif
    548 }
    549 
    550 void soinfo::set_soname(const char* soname) {
    551 #if defined(__work_around_b_24465209__)
    552   if (has_min_version(2)) {
    553     soname_ = soname;
    554   }
    555   strlcpy(old_name_, soname_, sizeof(old_name_));
    556 #else
    557   soname_ = soname;
    558 #endif
    559 }
    560 
    561 const char* soinfo::get_soname() const {
    562 #if defined(__work_around_b_24465209__)
    563   if (has_min_version(2)) {
    564     return soname_;
    565   } else {
    566     return old_name_;
    567   }
    568 #else
    569   return soname_;
    570 #endif
    571 }
    572 
    573 // This is a return on get_children()/get_parents() if
    574 // 'this->flags' does not have FLAG_NEW_SOINFO set.
    575 static soinfo_list_t g_empty_list;
    576 
    577 soinfo_list_t& soinfo::get_children() {
    578   if (has_min_version(0)) {
    579     return children_;
    580   }
    581 
    582   return g_empty_list;
    583 }
    584 
    585 const soinfo_list_t& soinfo::get_children() const {
    586   if (has_min_version(0)) {
    587     return children_;
    588   }
    589 
    590   return g_empty_list;
    591 }
    592 
    593 soinfo_list_t& soinfo::get_parents() {
    594   if (has_min_version(0)) {
    595     return parents_;
    596   }
    597 
    598   return g_empty_list;
    599 }
    600 
    601 static std::vector<std::string> g_empty_runpath;
    602 
    603 const std::vector<std::string>& soinfo::get_dt_runpath() const {
    604   if (has_min_version(3)) {
    605     return dt_runpath_;
    606   }
    607 
    608   return g_empty_runpath;
    609 }
    610 
    611 android_namespace_t* soinfo::get_primary_namespace() {
    612   if (has_min_version(3)) {
    613     return primary_namespace_;
    614   }
    615 
    616   return &g_default_namespace;
    617 }
    618 
    619 void soinfo::add_secondary_namespace(android_namespace_t* secondary_ns) {
    620   CHECK(has_min_version(3));
    621   secondary_namespaces_.push_back(secondary_ns);
    622 }
    623 
    624 android_namespace_list_t& soinfo::get_secondary_namespaces() {
    625   CHECK(has_min_version(3));
    626   return secondary_namespaces_;
    627 }
    628 
    629 ElfW(Addr) soinfo::resolve_symbol_address(const ElfW(Sym)* s) const {
    630   if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
    631     return call_ifunc_resolver(s->st_value + load_bias);
    632   }
    633 
    634   return static_cast<ElfW(Addr)>(s->st_value + load_bias);
    635 }
    636 
    637 const char* soinfo::get_string(ElfW(Word) index) const {
    638   if (has_min_version(1) && (index >= strtab_size_)) {
    639     __libc_fatal("%s: strtab out of bounds error; STRSZ=%zd, name=%d",
    640         get_realpath(), strtab_size_, index);
    641   }
    642 
    643   return strtab_ + index;
    644 }
    645 
    646 bool soinfo::is_gnu_hash() const {
    647   return (flags_ & FLAG_GNU_HASH) != 0;
    648 }
    649 
    650 bool soinfo::can_unload() const {
    651   return !is_linked() || ((get_rtld_flags() & (RTLD_NODELETE | RTLD_GLOBAL)) == 0);
    652 }
    653 
    654 bool soinfo::is_linked() const {
    655   return (flags_ & FLAG_LINKED) != 0;
    656 }
    657 
    658 bool soinfo::is_main_executable() const {
    659   return (flags_ & FLAG_EXE) != 0;
    660 }
    661 
    662 bool soinfo::is_linker() const {
    663   return (flags_ & FLAG_LINKER) != 0;
    664 }
    665 
    666 void soinfo::set_linked() {
    667   flags_ |= FLAG_LINKED;
    668 }
    669 
    670 void soinfo::set_linker_flag() {
    671   flags_ |= FLAG_LINKER;
    672 }
    673 
    674 void soinfo::set_main_executable() {
    675   flags_ |= FLAG_EXE;
    676 }
    677 
    678 void soinfo::increment_ref_count() {
    679   local_group_root_->ref_count_++;
    680 }
    681 
    682 size_t soinfo::decrement_ref_count() {
    683   return --local_group_root_->ref_count_;
    684 }
    685 
    686 soinfo* soinfo::get_local_group_root() const {
    687   return local_group_root_;
    688 }
    689 
    690 void soinfo::set_mapped_by_caller(bool mapped_by_caller) {
    691   if (mapped_by_caller) {
    692     flags_ |= FLAG_MAPPED_BY_CALLER;
    693   } else {
    694     flags_ &= ~FLAG_MAPPED_BY_CALLER;
    695   }
    696 }
    697 
    698 bool soinfo::is_mapped_by_caller() const {
    699   return (flags_ & FLAG_MAPPED_BY_CALLER) != 0;
    700 }
    701 
    702 // This function returns api-level at the time of
    703 // dlopen/load. Note that libraries opened by system
    704 // will always have 'current' api level.
    705 uint32_t soinfo::get_target_sdk_version() const {
    706   if (!has_min_version(2)) {
    707     return __ANDROID_API__;
    708   }
    709 
    710   return local_group_root_->target_sdk_version_;
    711 }
    712 
    713 uintptr_t soinfo::get_handle() const {
    714   CHECK(has_min_version(3));
    715   CHECK(handle_ != 0);
    716   return handle_;
    717 }
    718 
    719 void* soinfo::to_handle() {
    720   if (get_application_target_sdk_version() < __ANDROID_API_N__ || !has_min_version(3)) {
    721     return this;
    722   }
    723 
    724   return reinterpret_cast<void*>(get_handle());
    725 }
    726 
    727 void soinfo::generate_handle() {
    728   CHECK(has_min_version(3));
    729   CHECK(handle_ == 0); // Make sure this is the first call
    730 
    731   // Make sure the handle is unique and does not collide
    732   // with special values which are RTLD_DEFAULT and RTLD_NEXT.
    733   do {
    734     arc4random_buf(&handle_, sizeof(handle_));
    735     // the least significant bit for the handle is always 1
    736     // making it easy to test the type of handle passed to
    737     // dl* functions.
    738     handle_ = handle_ | 1;
    739   } while (handle_ == reinterpret_cast<uintptr_t>(RTLD_DEFAULT) ||
    740            handle_ == reinterpret_cast<uintptr_t>(RTLD_NEXT) ||
    741            g_soinfo_handles_map.find(handle_) != g_soinfo_handles_map.end());
    742 
    743   g_soinfo_handles_map[handle_] = this;
    744 }
    745 
    746 // TODO(dimitry): Move SymbolName methods to a separate file.
    747 
    748 uint32_t calculate_elf_hash(const char* name) {
    749   const uint8_t* name_bytes = reinterpret_cast<const uint8_t*>(name);
    750   uint32_t h = 0, g;
    751 
    752   while (*name_bytes) {
    753     h = (h << 4) + *name_bytes++;
    754     g = h & 0xf0000000;
    755     h ^= g;
    756     h ^= g >> 24;
    757   }
    758 
    759   return h;
    760 }
    761 
    762 uint32_t SymbolName::elf_hash() {
    763   if (!has_elf_hash_) {
    764     elf_hash_ = calculate_elf_hash(name_);
    765     has_elf_hash_ = true;
    766   }
    767 
    768   return elf_hash_;
    769 }
    770 
    771 uint32_t SymbolName::gnu_hash() {
    772   if (!has_gnu_hash_) {
    773     uint32_t h = 5381;
    774     const uint8_t* name = reinterpret_cast<const uint8_t*>(name_);
    775     while (*name != 0) {
    776       h += (h << 5) + *name++; // h*33 + c = h + h * 32 + c = h + h << 5 + c
    777     }
    778 
    779     gnu_hash_ =  h;
    780     has_gnu_hash_ = true;
    781   }
    782 
    783   return gnu_hash_;
    784 }
    785