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