• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
soinfo(android_namespace_t * ns,const char * realpath,const struct stat * file_stat,off64_t file_offset,int rtld_flags)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 
~soinfo()71 soinfo::~soinfo() {
72   g_soinfo_handles_map.erase(handle_);
73 }
74 
set_dt_runpath(const char * path)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 
ElfW(Versym)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 
ElfW(Addr)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 
get_verneed_cnt() const117 size_t soinfo::get_verneed_cnt() const {
118   if (has_min_version(2)) {
119     return verneed_cnt_;
120   }
121 
122   return 0;
123 }
124 
ElfW(Addr)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 
get_verdef_cnt() const133 size_t soinfo::get_verdef_cnt() const {
134   if (has_min_version(2)) {
135     return verdef_cnt_;
136   }
137 
138   return 0;
139 }
140 
find_symbol_by_name(SymbolName & symbol_name,const version_info * vi,const ElfW (Sym)** symbol) const141 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 
is_symbol_global_and_defined(const soinfo * si,const ElfW (Sym)* s)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 
is_versym_hidden(const ElfW (Versym)* versym)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 
check_symbol_version(const ElfW (Versym)verneed,const ElfW (Versym)* verdef)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 
gnu_lookup(SymbolName & symbol_name,const version_info * vi,uint32_t * symbol_index) const183 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 
elf_lookup(SymbolName & symbol_name,const version_info * vi,uint32_t * symbol_index) const252 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 
ElfW(Sym)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 
symbol_matches_soaddr(const ElfW (Sym)* sym,ElfW (Addr)soaddr)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 
ElfW(Sym)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 
ElfW(Sym)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 
call_function(const char * function_name __unused,linker_ctor_function_t function,const char * realpath __unused)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 
call_function(const char * function_name __unused,linker_dtor_function_t function,const char * realpath __unused)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>
call_array(const char * array_name __unused,F * functions,size_t count,bool reverse,const char * realpath)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 
call_pre_init_constructors()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 
call_constructors()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 
call_destructors()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 
add_child(soinfo * child)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 
remove_all_links()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 
get_st_dev() const493 dev_t soinfo::get_st_dev() const {
494   if (has_min_version(0)) {
495     return st_dev_;
496   }
497 
498   return 0;
499 };
500 
get_st_ino() const501 ino_t soinfo::get_st_ino() const {
502   if (has_min_version(0)) {
503     return st_ino_;
504   }
505 
506   return 0;
507 }
508 
get_file_offset() const509 off64_t soinfo::get_file_offset() const {
510   if (has_min_version(1)) {
511     return file_offset_;
512   }
513 
514   return 0;
515 }
516 
get_rtld_flags() const517 uint32_t soinfo::get_rtld_flags() const {
518   if (has_min_version(1)) {
519     return rtld_flags_;
520   }
521 
522   return 0;
523 }
524 
get_dt_flags_1() const525 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 
set_dt_flags_1(uint32_t dt_flags_1)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 
set_nodelete()547 void soinfo::set_nodelete() {
548   rtld_flags_ |= RTLD_NODELETE;
549 }
550 
get_realpath() const551 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 
set_soname(const char * soname)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 
get_soname() const574 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 
get_children()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 
get_children() const598 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 
get_parents()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 
get_dt_runpath() const616 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 
get_primary_namespace()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 
add_secondary_namespace(android_namespace_t * secondary_ns)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 
get_secondary_namespaces()637 android_namespace_list_t& soinfo::get_secondary_namespaces() {
638   CHECK(has_min_version(3));
639   return secondary_namespaces_;
640 }
641 
get_tls() const642 soinfo_tls* soinfo::get_tls() const {
643   return has_min_version(5) ? tls_.get() : nullptr;
644 }
645 
ElfW(Addr)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 
get_string(ElfW (Word)index) const654 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 
is_gnu_hash() const663 bool soinfo::is_gnu_hash() const {
664   return (flags_ & FLAG_GNU_HASH) != 0;
665 }
666 
can_unload() const667 bool soinfo::can_unload() const {
668   return !is_linked() ||
669          (
670              (get_rtld_flags() & (RTLD_NODELETE | RTLD_GLOBAL)) == 0
671          );
672 }
673 
is_linked() const674 bool soinfo::is_linked() const {
675   return (flags_ & FLAG_LINKED) != 0;
676 }
677 
is_image_linked() const678 bool soinfo::is_image_linked() const {
679   return (flags_ & FLAG_IMAGE_LINKED) != 0;
680 }
681 
is_main_executable() const682 bool soinfo::is_main_executable() const {
683   return (flags_ & FLAG_EXE) != 0;
684 }
685 
is_linker() const686 bool soinfo::is_linker() const {
687   return (flags_ & FLAG_LINKER) != 0;
688 }
689 
set_linked()690 void soinfo::set_linked() {
691   flags_ |= FLAG_LINKED;
692 }
693 
set_image_linked()694 void soinfo::set_image_linked() {
695   flags_ |= FLAG_IMAGE_LINKED;
696 }
697 
set_linker_flag()698 void soinfo::set_linker_flag() {
699   flags_ |= FLAG_LINKER;
700 }
701 
set_main_executable()702 void soinfo::set_main_executable() {
703   flags_ |= FLAG_EXE;
704 }
705 
increment_ref_count()706 size_t soinfo::increment_ref_count() {
707   return ++local_group_root_->ref_count_;
708 }
709 
decrement_ref_count()710 size_t soinfo::decrement_ref_count() {
711   return --local_group_root_->ref_count_;
712 }
713 
get_ref_count() const714 size_t soinfo::get_ref_count() const {
715   return local_group_root_->ref_count_;
716 }
717 
get_local_group_root() const718 soinfo* soinfo::get_local_group_root() const {
719   return local_group_root_;
720 }
721 
set_mapped_by_caller(bool mapped_by_caller)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 
is_mapped_by_caller() const730 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.
get_target_sdk_version() const737 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 
get_handle() const745 uintptr_t soinfo::get_handle() const {
746   CHECK(has_min_version(3));
747   CHECK(handle_ != 0);
748   return handle_;
749 }
750 
to_handle()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 
generate_handle()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 
calculate_elf_hash(const char * name)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 
elf_hash()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 
gnu_hash()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