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