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