android so载入过程

源自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迭代而增加的。本来不想粘怎么多代码的。但是看它写了这个函数的具体的操作的步骤,我就简单写一下把

  1. 全部代码都是围绕着LoadTask列表操作。第一步就是把所有依赖的so都找出来初始化load_tasks 列表。这个列表是 std::vector<LoadTask*>,猜测所有载入操作实际就是在LoadTask类中进行的。
  2. 调用LoadTask的load 方法载入so
  3. 后面就是处理载入的so,然后进行linking。至于什么namespace,local group和global group是啥,我也不明白,就先不写了
  4. 最后做一些首尾的清理工作。这一套走完。我们的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}

相关推荐

  1. android so载入过程

    2024-03-13 01:00:08       20 阅读
  2. C# WinForm listView 按列排序、listView 数据快速载入

    2024-03-13 01:00:08       24 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-13 01:00:08       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-13 01:00:08       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-13 01:00:08       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-13 01:00:08       20 阅读

热门阅读

  1. Vue3:ref和reactive实现响应式数据

    2024-03-13 01:00:08       24 阅读
  2. LeetCode--代码详解 146.LRU缓存

    2024-03-13 01:00:08       24 阅读
  3. Lwip之TCP服务端示例记录(1对1)

    2024-03-13 01:00:08       20 阅读
  4. swagger-ui页面设置接口请求头head参数

    2024-03-13 01:00:08       19 阅读
  5. .NET Core 日志记录功能详解

    2024-03-13 01:00:08       17 阅读
  6. LeetCode每日一题[C++]-2129.将标题首字母大写

    2024-03-13 01:00:08       22 阅读
  7. 【LeetCode】 删除链表的倒数第 N 个结点

    2024-03-13 01:00:08       21 阅读
  8. css---定位

    2024-03-13 01:00:08       21 阅读
  9. 高防IP有哪些防御方法?

    2024-03-13 01:00:08       24 阅读
  10. C++ struct 结构体类型

    2024-03-13 01:00:08       17 阅读