源自android 9
/bionic/libdl/libdl_static.c 好像没用。都是空的
/bionic/libdl/libdl.cpp 主角
22// These functions are exported by the loader
23// TODO(dimitry): replace these with reference to libc.so
101// Proxy calls to bionic loader
102__attribute__((__weak__))
103void* dlopen(const char* filename, int flag) {
104 const void* caller_addr = __builtin_return_address(0);
105 return __loader_dlopen(filename, flag, caller_addr);
106}
/bionic/linker/dlfcn.cpp
152void* __loader_dlopen(const char* filename, int flags, const void* caller_addr) {
153 return dlopen_ext(filename, flags, nullptr, caller_addr);
154}
131static void* dlopen_ext(const char* filename,
132 int flags,
133 const android_dlextinfo* extinfo,
134 const void* caller_addr) {
135 ScopedPthreadMutexLocker locker(&g_dl_mutex);
136 g_linker_logger.ResetState();
137 void* result = do_dlopen(filename, flags, extinfo, caller_addr);
138 if (result == nullptr) {
139 __bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
140 return nullptr;
141 }
142 return result;
143}
do_dlopen
/bionic/linker/linker.cpp
49void* do_dlopen(const char* name, int flags,
2050 const android_dlextinfo* extinfo,
2051 const void* caller_addr) {
2052 std::string trace_prefix = std::string("dlopen: ") + (name == nullptr ? "(nullptr)" : name);
2053 ScopedTrace trace(trace_prefix.c_str());
2054 ScopedTrace loading_trace((trace_prefix + " - loading and linking").c_str());
2055 soinfo* const caller = find_containing_library(caller_addr);
2056 android_namespace_t* ns = get_caller_namespace(caller);
2057
2058 LD_LOG(kLogDlopen,
2059 "dlopen(name=\"%s\", flags=0x%x, extinfo=%s, caller=\"%s\", caller_ns=%s@%p) ...",
2060 name,
2061 flags,
2062 android_dlextinfo_to_string(extinfo).c_str(),
2063 caller == nullptr ? "(null)" : caller->get_realpath(),
2064 ns == nullptr ? "(null)" : ns->get_name(),
2065 ns);
2066
2067 auto failure_guard = android::base::make_scope_guard(
2068 [&]() { LD_LOG(kLogDlopen, "... dlopen failed: %s", linker_get_error_buffer()); });
2069
2070 if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) {
2071 DL_ERR("invalid flags to dlopen: %x", flags);
2072 return nullptr;
2073 }
2074
2075 if (extinfo != nullptr) {
2076 if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {
2077 DL_ERR("invalid extended flags to android_dlopen_ext: 0x%" PRIx64, extinfo->flags);
2078 return nullptr;
2079 }
2080
2081 if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 &&
2082 (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
2083 DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without "
2084 "ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags);
2085 return nullptr;
2086 }
2087
2088 if ((extinfo->flags & ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS) != 0 &&
2089 (extinfo->flags & (ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_HINT)) != 0) {
2090 DL_ERR("invalid extended flag combination: ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS is not "
2091 "compatible with ANDROID_DLEXT_RESERVED_ADDRESS/ANDROID_DLEXT_RESERVED_ADDRESS_HINT");
2092 return nullptr;
2093 }
2094
2095 if ((extinfo->flags & ANDROID_DLEXT_USE_NAMESPACE) != 0) {
2096 if (extinfo->library_namespace == nullptr) {
2097 DL_ERR("ANDROID_DLEXT_USE_NAMESPACE is set but extinfo->library_namespace is null");
2098 return nullptr;
2099 }
2100 ns = extinfo->library_namespace;
2101 }
2102 }
2103
2104 std::string asan_name_holder;
2105
2106 const char* translated_name = name;
2107 if (g_is_asan && translated_name != nullptr && translated_name[0] == '/') {
2108 char original_path[PATH_MAX];
2109 if (realpath(name, original_path) != nullptr) {
2110 asan_name_holder = std::string(kAsanLibDirPrefix) + original_path;
2111 if (file_exists(asan_name_holder.c_str())) {
2112 soinfo* si = nullptr;
2113 if (find_loaded_library_by_realpath(ns, original_path, true, &si)) {
2114 PRINT("linker_asan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
2115 asan_name_holder.c_str());
2116 } else {
2117 PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
2118 translated_name = asan_name_holder.c_str();
2119 }
2120 }
2121 }
2122 }
2123
2124 ProtectedDataGuard guard;
2125 soinfo* si = find_library(ns, translated_name, flags, extinfo, caller);
2126 loading_trace.End();
2127
2128 if (si != nullptr) {
2129 void* handle = si->to_handle();
2130 LD_LOG(kLogDlopen,
2131 "... dlopen calling constructors: realpath=\"%s\", soname=\"%s\", handle=%p",
2132 si->get_realpath(), si->get_soname(), handle);
2133 si->call_constructors();
2134 failure_guard.Disable();
2135 LD_LOG(kLogDlopen,
2136 "... dlopen successful: realpath=\"%s\", soname=\"%s\", handle=%p",
2137 si->get_realpath(), si->get_soname(), handle);
2138 return handle;
2139 }
2140
2141 return nullptr;
2142}
排除一大堆分支。可以很清楚的发现 核心代码就是调用find_library 来构造一个soinfo 结构体,然后调用soinfo 的to_handle和call_constructors最后把to_handle函数的返回值返回。
soinfo
/bionic/linker/linker_soinfo.h
soinfo 代码太长了就不贴了。看样子内容和elf 的差不多。所以find_library 的任务应该就是把elf 文件的动态链接库文件加工一下放到soinfo结构体中。然后android 通过管理soinfo 来管理所有动态链接库
find_library
/bionic/linker/linker.cpp
1759static soinfo* find_library(android_namespace_t* ns,
1760 const char* name, int rtld_flags,
1761 const android_dlextinfo* extinfo,
1762 soinfo* needed_by) {
1763 soinfo* si = nullptr;
1764
1765 if (name == nullptr) {
1766 si = solist_get_somain();
1767 } else if (!find_libraries(ns,
1768 needed_by,
1769 &name,
1770 1,
1771 &si,
1772 nullptr,
1773 0,
1774 rtld_flags,
1775 extinfo,
1776 false /* add_as_children */,
1777 true /* search_linked_namespaces */)) {
1778 if (si != nullptr) {
1779 soinfo_unload(si);
1780 }
1781 return nullptr;
1782 }
1783
1784 si->increment_ref_count();
1785
1786 return si;
1787}
这个name 就do_dlopen前面一大串代码找到的so路径。 所以一般情况下solist_get_somain 是不会运行的。不过我好奇看了一下这个默认行为是做什么的。
/bionic/linker/linker_main.cpp
59// These should be preserved static to avoid emitting
60// RELATIVE relocations for the part of the code running
61// before linker links itself.
62
63// TODO (dimtiry): remove somain, rename solist to solist_head
64static soinfo* solist;
65static soinfo* sonext;
66static soinfo* somain; // main process, always the one after libdl_info
67static soinfo* vdso; // vdso if present
104soinfo* solist_get_somain() {
105 return somain;
106}
通过注释好像标识main process ,不过上面有一个remove somain 是不是表示后面要移除的。不过这个不是我们研究的重点
find_libraries 核心装在步骤
/bionic/linker/linker_main.cpp
1504// add_as_children - add first-level loaded libraries (i.e. library_names[], but
1505// not their transitive dependencies) as children of the start_with library.
1506// This is false when find_libraries is called for dlopen(), when newly loaded
1507// libraries must form a disjoint tree.
1508bool find_libraries(android_namespace_t* ns,
1509 soinfo* start_with,
1510 const char* const library_names[],
1511 size_t library_names_count,
1512 soinfo* soinfos[],
1513 std::vector<soinfo*>* ld_preloads,
1514 size_t ld_preloads_count,
1515 int rtld_flags,
1516 const android_dlextinfo* extinfo,
1517 bool add_as_children,
1518 bool search_linked_namespaces,
1519 std::vector<android_namespace_t*>* namespaces) {
1520 // Step 0: prepare.
1521 std::unordered_map<const soinfo*, ElfReader> readers_map;
1522 LoadTaskList load_tasks;
1523
1524 for (size_t i = 0; i < library_names_count; ++i) {
1525 const char* name = library_names[i];
1526 load_tasks.push_back(LoadTask::create(name, start_with, ns, &readers_map));
1527 }
1528
1529 // If soinfos array is null allocate one on stack.
1530 // The array is needed in case of failure; for example
1531 // when library_names[] = {libone.so, libtwo.so} and libone.so
1532 // is loaded correctly but libtwo.so failed for some reason.
1533 // In this case libone.so should be unloaded on return.
1534 // See also implementation of failure_guard below.
1535
1536 if (soinfos == nullptr) {
1537 size_t soinfos_size = sizeof(soinfo*)*library_names_count;
1538 soinfos = reinterpret_cast<soinfo**>(alloca(soinfos_size));
1539 memset(soinfos, 0, soinfos_size);
1540 }
1541
1542 // list of libraries to link - see step 2.
1543 size_t soinfos_count = 0;
1544
1545 auto scope_guard = android::base::make_scope_guard([&]() {
1546 for (LoadTask* t : load_tasks) {
1547 LoadTask::deleter(t);
1548 }
1549 });
1550
1551 ZipArchiveCache zip_archive_cache;
1552
1553 // Step 1: expand the list of load_tasks to include
1554 // all DT_NEEDED libraries (do not load them just yet)
1555 for (size_t i = 0; i<load_tasks.size(); ++i) {
1556 LoadTask* task = load_tasks[i];
1557 soinfo* needed_by = task->get_needed_by();
1558
1559 bool is_dt_needed = needed_by != nullptr && (needed_by != start_with || add_as_children);
1560 task->set_extinfo(is_dt_needed ? nullptr : extinfo);
1561 task->set_dt_needed(is_dt_needed);
1562
1563 // Note: start from the namespace that is stored in the LoadTask. This namespace
1564 // is different from the current namespace when the LoadTask is for a transitive
1565 // dependency and the lib that created the LoadTask is not found in the
1566 // current namespace but in one of the linked namespace.
1567 if (!find_library_internal(const_cast<android_namespace_t*>(task->get_start_from()),
1568 task,
1569 &zip_archive_cache,
1570 &load_tasks,
1571 rtld_flags,
1572 search_linked_namespaces || is_dt_needed)) {
1573 return false;
1574 }
1575
1576 soinfo* si = task->get_soinfo();
1577
1578 if (is_dt_needed) {
1579 needed_by->add_child(si);
1580 }
1581
1582 // When ld_preloads is not null, the first
1583 // ld_preloads_count libs are in fact ld_preloads.
1584 if (ld_preloads != nullptr && soinfos_count < ld_preloads_count) {
1585 ld_preloads->push_back(si);
1586 }
1587
1588 if (soinfos_count < library_names_count) {
1589 soinfos[soinfos_count++] = si;
1590 }
1591 }
1592
1593 // Step 2: Load libraries in random order (see b/24047022)
1594 LoadTaskList load_list;
1595 for (auto&& task : load_tasks) {
1596 soinfo* si = task->get_soinfo();
1597 auto pred = [&](const LoadTask* t) {
1598 return t->get_soinfo() == si;
1599 };
1600
1601 if (!si->is_linked() &&
1602 std::find_if(load_list.begin(), load_list.end(), pred) == load_list.end() ) {
1603 load_list.push_back(task);
1604 }
1605 }
1606 shuffle(&load_list);
1607
1608 for (auto&& task : load_list) {
1609 if (!task->load()) {
1610 return false;
1611 }
1612 }
1613
1614 // Step 3: pre-link all DT_NEEDED libraries in breadth first order.
1615 for (auto&& task : load_tasks) {
1616 soinfo* si = task->get_soinfo();
1617 if (!si->is_linked() && !si->prelink_image()) {
1618 return false;
1619 }
1620 }
1621
1622 // Step 4: Construct the global group. Note: DF_1_GLOBAL bit of a library is
1623 // determined at step 3.
1624
1625 // Step 4-1: DF_1_GLOBAL bit is force set for LD_PRELOADed libs because they
1626 // must be added to the global group
1627 if (ld_preloads != nullptr) {
1628 for (auto&& si : *ld_preloads) {
1629 si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
1630 }
1631 }
1632
1633 // Step 4-2: Gather all DF_1_GLOBAL libs which were newly loaded during this
1634 // run. These will be the new member of the global group
1635 soinfo_list_t new_global_group_members;
1636 for (auto&& task : load_tasks) {
1637 soinfo* si = task->get_soinfo();
1638 if (!si->is_linked() && (si->get_dt_flags_1() & DF_1_GLOBAL) != 0) {
1639 new_global_group_members.push_back(si);
1640 }
1641 }
1642
1643 // Step 4-3: Add the new global group members to all the linked namespaces
1644 if (namespaces != nullptr) {
1645 for (auto linked_ns : *namespaces) {
1646 for (auto si : new_global_group_members) {
1647 if (si->get_primary_namespace() != linked_ns) {
1648 linked_ns->add_soinfo(si);
1649 si->add_secondary_namespace(linked_ns);
1650 }
1651 }
1652 }
1653 }
1654
1655 // Step 5: Collect roots of local_groups.
1656 // Whenever needed_by->si link crosses a namespace boundary it forms its own local_group.
1657 // Here we collect new roots to link them separately later on. Note that we need to avoid
1658 // collecting duplicates. Also the order is important. They need to be linked in the same
1659 // BFS order we link individual libraries.
1660 std::vector<soinfo*> local_group_roots;
1661 if (start_with != nullptr && add_as_children) {
1662 local_group_roots.push_back(start_with);
1663 } else {
1664 CHECK(soinfos_count == 1);
1665 local_group_roots.push_back(soinfos[0]);
1666 }
1667
1668 for (auto&& task : load_tasks) {
1669 soinfo* si = task->get_soinfo();
1670 soinfo* needed_by = task->get_needed_by();
1671 bool is_dt_needed = needed_by != nullptr && (needed_by != start_with || add_as_children);
1672 android_namespace_t* needed_by_ns =
1673 is_dt_needed ? needed_by->get_primary_namespace() : ns;
1674
1675 if (!si->is_linked() && si->get_primary_namespace() != needed_by_ns) {
1676 auto it = std::find(local_group_roots.begin(), local_group_roots.end(), si);
1677 LD_LOG(kLogDlopen,
1678 "Crossing namespace boundary (si=%s@%p, si_ns=%s@%p, needed_by=%s@%p, ns=%s@%p, needed_by_ns=%s@%p) adding to local_group_roots: %s",
1679 si->get_realpath(),
1680 si,
1681 si->get_primary_namespace()->get_name(),
1682 si->get_primary_namespace(),
1683 needed_by == nullptr ? "(nullptr)" : needed_by->get_realpath(),
1684 needed_by,
1685 ns->get_name(),
1686 ns,
1687 needed_by_ns->get_name(),
1688 needed_by_ns,
1689 it == local_group_roots.end() ? "yes" : "no");
1690
1691 if (it == local_group_roots.end()) {
1692 local_group_roots.push_back(si);
1693 }
1694 }
1695 }
1696
1697 // Step 6: Link all local groups
1698 for (auto root : local_group_roots) {
1699 soinfo_list_t local_group;
1700 android_namespace_t* local_group_ns = root->get_primary_namespace();
1701
1702 walk_dependencies_tree(root,
1703 [&] (soinfo* si) {
1704 if (local_group_ns->is_accessible(si)) {
1705 local_group.push_back(si);
1706 return kWalkContinue;
1707 } else {
1708 return kWalkSkip;
1709 }
1710 });
1711
1712 soinfo_list_t global_group = local_group_ns->get_global_group();
1713 bool linked = local_group.visit([&](soinfo* si) {
1714 // Even though local group may contain accessible soinfos from other namesapces
1715 // we should avoid linking them (because if they are not linked -> they
1716 // are in the local_group_roots and will be linked later).
1717 if (!si->is_linked() && si->get_primary_namespace() == local_group_ns) {
1718 if (!si->link_image(global_group, local_group, extinfo) ||
1719 !get_cfi_shadow()->AfterLoad(si, solist_get_head())) {
1720 return false;
1721 }
1722 }
1723
1724 return true;
1725 });
1726
1727 if (!linked) {
1728 return false;
1729 }
1730 }
1731
1732 // Step 7: Mark all load_tasks as linked and increment refcounts
1733 // for references between load_groups (at this point it does not matter if
1734 // referenced load_groups were loaded by previous dlopen or as part of this
1735 // one on step 6)
1736 if (start_with != nullptr && add_as_children) {
1737 start_with->set_linked();
1738 }
1739
1740 for (auto&& task : load_tasks) {
1741 soinfo* si = task->get_soinfo();
1742 si->set_linked();
1743 }
1744
1745 for (auto&& task : load_tasks) {
1746 soinfo* si = task->get_soinfo();
1747 soinfo* needed_by = task->get_needed_by();
1748 if (needed_by != nullptr &&
1749 needed_by != start_with &&
1750 needed_by->get_local_group_root() != si->get_local_group_root()) {
1751 si->increment_ref_count();
1752 }
1753 }
1754
1755
1756 return true;
1757}
看到这我第一时间感觉这块代码是不是大改过。应该是随着android迭代而增加的。本来不想粘怎么多代码的。但是看它写了这个函数的具体的操作的步骤,我就简单写一下把
- 全部代码都是围绕着LoadTask列表操作。第一步就是把所有依赖的so都找出来初始化load_tasks 列表。这个列表是 std::vector<LoadTask*>,猜测所有载入操作实际就是在LoadTask类中进行的。
- 调用LoadTask的load 方法载入so
- 后面就是处理载入的so,然后进行linking。至于什么namespace,local group和global group是啥,我也不明白,就先不写了
- 最后做一些首尾的清理工作。这一套走完。我们的soinfos就初始化玩了。
最后我们看一下find_library_internal,其实也没啥可看的,都是比较底层的工作,一层层调用之后。最后就是读so的磁盘文件。之后他们负责初始化传进来的LoadTask的类。初始化好了之后,以后LoadTask调用load方法就就完成载入了。
/bionic/linker/linker.cpp
1442static bool find_library_internal(android_namespace_t* ns,
1443 LoadTask* task,
1444 ZipArchiveCache* zip_archive_cache,
1445 LoadTaskList* load_tasks,
1446 int rtld_flags,
1447 bool search_linked_namespaces) {
1448 soinfo* candidate;
1449
1450 if (find_loaded_library_by_soname(ns, task->get_name(), search_linked_namespaces, &candidate)) {
1451 task->set_soinfo(candidate);
1452 return true;
1453 }
1454
1455 // Library might still be loaded, the accurate detection
1456 // of this fact is done by load_library.
1457 TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder...]",
1458 task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
1459
1460 if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags, search_linked_namespaces)) {
1461 return true;
1462 }
1463
1464 if (search_linked_namespaces) {
1465 // if a library was not found - look into linked namespaces
1466 // preserve current dlerror in the case it fails.
1467 DlErrorRestorer dlerror_restorer;
1468 for (auto& linked_namespace : ns->linked_namespaces()) {
1469 if (find_library_in_linked_namespace(linked_namespace,
1470 task)) {
1471 if (task->get_soinfo() == nullptr) {
1472 // try to load the library - once namespace boundary is crossed
1473 // we need to load a library within separate load_group
1474 // to avoid using symbols from foreign namespace while.
1475 //
1476 // However, actual linking is deferred until when the global group
1477 // is fully identified and is applied to all namespaces.
1478 // Otherwise, the libs in the linked namespace won't get symbols from
1479 // the global group.
1480 if (load_library(linked_namespace.linked_namespace(), task, zip_archive_cache, load_tasks, rtld_flags, false)) {
1481 return true;
1482 }
1483 } else {
1484 // lib is already loaded
1485 return true;
1486 }
1487 }
1488 }
1489 }
1490
1491 return false;
1492}
1493
1322static bool load_library(android_namespace_t* ns,
1323 LoadTask* task,
1324 ZipArchiveCache* zip_archive_cache,
1325 LoadTaskList* load_tasks,
1326 int rtld_flags,
1327 bool search_linked_namespaces) {
1328 const char* name = task->get_name();
1329 soinfo* needed_by = task->get_needed_by();
1330 const android_dlextinfo* extinfo = task->get_extinfo();
1331
1332 off64_t file_offset;
1333 std::string realpath;
1334 if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
1335 file_offset = 0;
1336 if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
1337 file_offset = extinfo->library_fd_offset;
1338 }
1339
1340 if (!realpath_fd(extinfo->library_fd, &realpath)) {
1341 PRINT("warning: unable to get realpath for the library \"%s\" by extinfo->library_fd. "
1342 "Will use given name.", name);
1343 realpath = name;
1344 }
1345
1346 task->set_fd(extinfo->library_fd, false);
1347 task->set_file_offset(file_offset);
1348 return load_library(ns, task, load_tasks, rtld_flags, realpath, search_linked_namespaces);
1349 }
1350
1351 // Open the file.
1352 int fd = open_library(ns, zip_archive_cache, name, needed_by, &file_offset, &realpath);
1353 if (fd == -1) {
1354 DL_ERR("library \"%s\" not found", name);
1355 return false;
1356 }
1357
1358 task->set_fd(fd, true);
1359 task->set_file_offset(file_offset);
1360
1361 return load_library(ns, task, load_tasks, rtld_flags, realpath, search_linked_namespaces);
1362}
1363
1364static bool find_loaded_library_by_soname(android_namespace_t* ns,
1365 const char* name,
1366 soinfo** candidate) {
1367 return !ns->soinfo_list().visit([&](soinfo* si) {
1368 const char* soname = si->get_soname();
1369 if (soname != nullptr && (strcmp(name, soname) == 0)) {
1370 *candidate = si;
1371 return false;
1372 }
1373
1374 return true;
1375 });
1376}
1377
1378// Returns true if library was found and false otherwise
1379static bool find_loaded_library_by_soname(android_namespace_t* ns,
1380 const char* name,
1381 bool search_linked_namespaces,
1382 soinfo** candidate) {
1383 *candidate = nullptr;
1384
1385 // Ignore filename with path.
1386 if (strchr(name, '/') != nullptr) {
1387 return false;
1388 }
1389
1390 bool found = find_loaded_library_by_soname(ns, name, candidate);
1391
1392 if (!found && search_linked_namespaces) {
1393 // if a library was not found - look into linked namespaces
1394 for (auto& link : ns->linked_namespaces()) {
1395 if (!link.is_accessible(name)) {
1396 continue;
1397 }
1398
1399 android_namespace_t* linked_ns = link.linked_namespace();
1400
1401 if (find_loaded_library_by_soname(linked_ns, name, candidate)) {
1402 return true;
1403 }
1404 }
1405 }
1406
1407 return found;
1408}
1409
1188static bool load_library(android_namespace_t* ns,
1189 LoadTask* task,
1190 LoadTaskList* load_tasks,
1191 int rtld_flags,
1192 const std::string& realpath,
1193 bool search_linked_namespaces) {
1194 off64_t file_offset = task->get_file_offset();
1195 const char* name = task->get_name();
1196 const android_dlextinfo* extinfo = task->get_extinfo();
1197
1198 if ((file_offset % PAGE_SIZE) != 0) {
1199 DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset);
1200 return false;
1201 }
1202 if (file_offset < 0) {
1203 DL_ERR("file offset for the library \"%s\" is negative: %" PRId64, name, file_offset);
1204 return false;
1205 }
1206
1207 struct stat file_stat;
1208 if (TEMP_FAILURE_RETRY(fstat(task->get_fd(), &file_stat)) != 0) {
1209 DL_ERR("unable to stat file for the library \"%s\": %s", name, strerror(errno));
1210 return false;
1211 }
1212 if (file_offset >= file_stat.st_size) {
1213 DL_ERR("file offset for the library \"%s\" >= file size: %" PRId64 " >= %" PRId64,
1214 name, file_offset, file_stat.st_size);
1215 return false;
1216 }
1217
1218 // Check for symlink and other situations where
1219 // file can have different names, unless ANDROID_DLEXT_FORCE_LOAD is set
1220 if (extinfo == nullptr || (extinfo->flags & ANDROID_DLEXT_FORCE_LOAD) == 0) {
1221 soinfo* si = nullptr;
1222 if (find_loaded_library_by_inode(ns, file_stat, file_offset, search_linked_namespaces, &si)) {
1223 TRACE("library \"%s\" is already loaded under different name/path \"%s\" - "
1224 "will return existing soinfo", name, si->get_realpath());
1225 task->set_soinfo(si);
1226 return true;
1227 }
1228 }
1229
1230 if ((rtld_flags & RTLD_NOLOAD) != 0) {
1231 DL_ERR("library \"%s\" wasn't loaded and RTLD_NOLOAD prevented it", name);
1232 return false;
1233 }
1234
1235 struct statfs fs_stat;
1236 if (TEMP_FAILURE_RETRY(fstatfs(task->get_fd(), &fs_stat)) != 0) {
1237 DL_ERR("unable to fstatfs file for the library \"%s\": %s", name, strerror(errno));
1238 return false;
1239 }
1240
1241 // do not check accessibility using realpath if fd is located on tmpfs
1242 // this enables use of memfd_create() for apps
1243 if ((fs_stat.f_type != TMPFS_MAGIC) && (!ns->is_accessible(realpath))) {
1244 // TODO(dimitry): workaround for http://b/26394120 - the grey-list
1245
1246 // TODO(dimitry) before O release: add a namespace attribute to have this enabled
1247 // only for classloader-namespaces
1248 const soinfo* needed_by = task->is_dt_needed() ? task->get_needed_by() : nullptr;
1249 if (is_greylisted(ns, name, needed_by)) {
1250 // print warning only if needed by non-system library
1251 if (needed_by == nullptr || !is_system_library(needed_by->get_realpath())) {
1252 const soinfo* needed_or_dlopened_by = task->get_needed_by();
1253 const char* sopath = needed_or_dlopened_by == nullptr ? "(unknown)" :
1254 needed_or_dlopened_by->get_realpath();
1255 DL_WARN_documented_change(__ANDROID_API_N__,
1256 "private-api-enforced-for-api-level-24",
1257 "library \"%s\" (\"%s\") needed or dlopened by \"%s\" "
1258 "is not accessible by namespace \"%s\"",
1259 name, realpath.c_str(), sopath, ns->get_name());
1260 add_dlwarning(sopath, "unauthorized access to", name);
1261 }
1262 } else {
1263 // do not load libraries if they are not accessible for the specified namespace.
1264 const char* needed_or_dlopened_by = task->get_needed_by() == nullptr ?
1265 "(unknown)" :
1266 task->get_needed_by()->get_realpath();
1267
1268 DL_ERR("library \"%s\" needed or dlopened by \"%s\" is not accessible for the namespace \"%s\"",
1269 name, needed_or_dlopened_by, ns->get_name());
1270
1271 // do not print this if a library is in the list of shared libraries for linked namespaces
1272 if (!maybe_accessible_via_namespace_links(ns, name)) {
1273 PRINT("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
1274 " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
1275 " permitted_paths=\"%s\"]",
1276 name, realpath.c_str(),
1277 needed_or_dlopened_by,
1278 ns->get_name(),
1279 android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
1280 android::base::Join(ns->get_default_library_paths(), ':').c_str(),
1281 android::base::Join(ns->get_permitted_paths(), ':').c_str());
1282 }
1283 return false;
1284 }
1285 }
1286
1287 soinfo* si = soinfo_alloc(ns, realpath.c_str(), &file_stat, file_offset, rtld_flags);
1288 if (si == nullptr) {
1289 return false;
1290 }
1291
1292 task->set_soinfo(si);
1293
1294 // Read the ELF header and some of the segments.
1295 if (!task->read(realpath.c_str(), file_stat.st_size)) {
1296 soinfo_free(si);
1297 task->set_soinfo(nullptr);
1298 return false;
1299 }
1300
1301 // find and set DT_RUNPATH and dt_soname
1302 // Note that these field values are temporary and are
1303 // going to be overwritten on soinfo::prelink_image
1304 // with values from PT_LOAD segments.
1305 const ElfReader& elf_reader = task->get_elf_reader();
1306 for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) {
1307 if (d->d_tag == DT_RUNPATH) {
1308 si->set_dt_runpath(elf_reader.get_string(d->d_un.d_val));
1309 }
1310 if (d->d_tag == DT_SONAME) {
1311 si->set_soname(elf_reader.get_string(d->d_un.d_val));
1312 }
1313 }
1314
1315 for_each_dt_needed(task->get_elf_reader(), [&](const char* name) {
1316 load_tasks->push_back(LoadTask::create(name, si, ns, task->get_readers_map()));
1317 });
1318
1319 return true;
1320}