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