android so载入过程

news/2024/4/21 13:58:56/文章来源:https://blog.csdn.net/god_wen/article/details/136527072

源自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.so101// 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 present104soinfo* solist_get_somain() {
105  return somain;
106}

通过注释好像标识main process ,不过上面有一个remove somain 是不是表示后面要移除的。不过这个不是我们研究的重点

/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}
14931322static 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}
14091188static 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}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_998468.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Web前端】Vue核心基础

文章目录 1. Vue简介2. Vue官网使用指南3. 初识Vue3.1 搭建Vue开发环境3.2 HelloWorld案例3.3 el与data的两种写法3.4 MVVM模型3.5 模板语法 4. 数据绑定4.1 v-bind单向数据绑定4.2 v-model双向数据绑定 5. 事件处理5.1 v-on绑定事件5.2 事件修饰符5.3 键盘事件 6. 计算属性6.1…

关于出国留学和考研比较----以本人双非跨考计算机为例

文章目录 中心论点国内就业现状勿让旧认知害了自己那出国留学真的一无是处了吗?1. 藤校仍旧是具有极高价值2. 时间成本低3. 研究生一定比单纯的本科找工作强!4. 很多人说出国读博好,可以无脑入,真是这样吗? 中心论点 如果在选择出国留学还是国内考研的最终核心诉求都是有更好…

【kubernetes】关于k8s集群的污点和容忍,以及k8s集群的故障排查思路

目录 一、污点 关于污点的增删改查 验证污点的作用——NoExecute ​编辑 验证污点的作用——NoSchedule 验证污点的作用——PreferNoSchedule 二、容忍 三、关于cordon 和 drain 四、Pod启动阶段 五、关于pod的五种状态 六、k8s常见的排障手段 针对组件故障 针对pod…

04 Python的面向对象编程

self是一个指针&#xff0c;指向对象xiaoming,可以调用对象里面的属性和方法。 name 和 age是实例变量。 desplay_msg是类变量 xiaoming就是具体的对象&#xff0c;是类的实例化

如何使用apk2url从APK中快速提取IP地址和URL节点

关于apk2url apk2url是一款功能强大的公开资源情报OSINT工具&#xff0c;该工具可以通过对APK文件执行反汇编和反编译&#xff0c;以从中快速提取出IP地址和URL节点&#xff0c;然后将结果过滤并存储到一个.txt输出文件中。 该工具本质上是一个Shell脚本&#xff0c;专为红队…

字节跳动发布SDXL-Lightning模型,支持WebUI与ComfyUI双平台,只需一步生成1024高清大图!

字节跳动发布SDXL-Lightning模型,WebUI与ComfyUI平台,只需一步生成1024高清大图,需要的步数比 LCM 更低了! 什么是SDXL-Lightning: SDXL-Lightning 是一种快速的文本到图像生成模型。SDXL-Lightning模型的核心优势在于其创新的蒸馏策略,它可以通过几个步骤生成高质量的 1…

Unity使用UnityWebRequest读取音频长度不对的解决方法

在开发的过程中碰到这样一个问题&#xff0c;有的音频文件通过UnityWebRequest读取出来后&#xff0c;AudioClip的Length会不对&#xff0c;比如本身有7秒&#xff0c;读出来只有3秒。代码如下&#xff1a; IEnumerator TestEnumerator() {UnityWebRequest www UnityWebReque…

利用“定时执行专家”循环执行BAT、VBS、Python脚本——含参数指定功能

目录 一、软件概述 二、VBS脚本执行设置 三、触发器设置 四、功能亮点 五、总结 在自动化办公和日常计算机任务管理中&#xff0c;定时执行脚本是一项非常重要的功能。今天&#xff0c;我将为大家带来一款名为“定时执行专家”的软件的评测&#xff0c;特别是其定时执行VB…

IPSEC VPN安全介绍以及相关实验

目录 一、IPSEC相关的安全服务 二、IPSEC的安全协议 三、实验 IPSEC一组协议集合&#xff0c;用于确保在IP网络上进行通信时的安全性和保密性。它提供了一种标准化的方法&#xff0c;用于对IP数据包进行加密、身份验证和完整性保护。IPSEC通常用于建立虚拟私人网络VPN连接&am…

托管服务器常见的问题有哪些(常见托管问题解决)

​  对于我们来说&#xff0c;选择一个合适的服务器托管提供商只是建立和管理自己所属网站的第一步。相对来说&#xff0c;真正的挑战在于解决管理网站运行时可能出现的各种问题。就像有时&#xff0c;有些常见的服务器托管问题是不可避免的&#xff0c;但通过主动监控、定期…

Springboot教程(六)——异常处理

拦截异常 在Spring Boot中&#xff0c;我们可以将异常统一放在全局处理类来处理&#xff0c;创建一个全局异常处理类需要用到ControllerAdvice和ExceptionHandler注解。 ControllerAdvice类似一个增强版的Controller&#xff0c;用于标注类&#xff0c;表示该类声明了整个项目…

消息队列-Kafka-基础架构

基础架构 官网地址 上面这张图类比RocketMQ 相当于对一个主题进行了分区&#xff08;类似于RockeMQ 消息队列&#xff09;&#xff0c;每个分区存储到不同的Broker。在发送消息的时候都是发送到主分区。如果一台Broker由于其它节点备份了挂掉节点的数据&#xff0c;所以可以…

java-抢红包一些简单概念

抢红包&#xff0c;比如微信中抢红包&#xff0c;红包金额分配使用的是二倍均值算法。 二倍均值拆包&#xff1a; 拆包要求:所有人抢到的金额之和等于红包总额&#xff0c;每个人最少抢到 0.01 元&#xff0c;每个人抢到的红包金额不要相差太大二倍均值法:假设红包总金额是X&…

向量数据库短板及解决方案

索引内存消耗问题 索引的选择对于向量召回的性能至关重要&#xff0c;Milvus 支持了 Annoy&#xff0c;Faiss&#xff0c;HNSW等多种不同的索引&#xff0c;大部分索引必须加载进内存. 用户可以根据对延迟、内存使用和召回率的需求进行选择。对于大数据量&#xff0c;内存不足…

今日arXiv最热大模型论文:北大发布,通过上下文提示,让大模型学习一门新的语言

在人工智能领域&#xff0c;大语言模型&#xff08;LLMs&#xff09;的发展已经取得了显著的进步&#xff0c;它们在处理高资源语言方面表现出色。然而&#xff0c;对于资源较少的语言&#xff0c;尤其是极低资源语言&#xff0c;这些模型的支持却显得力不从心。这些语言往往缺…

数据结构测试题

目录 1.闰年判断 2.志愿者选拔 3.单词接龙 4.对称二叉树 5.英雄南昌欢迎您 6.时间转换 7.矩阵乘法 8. Huffuman树 1.闰年判断 题目描述&#xff1a; 给定一个年份&#xff0c;判断这一年是不是闰年。 当以下情况之一满足时&#xff0c;这一年是闰年&#xff1a; 1. 年…

Libevent的使用及reactor模型

Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库&#xff0c;主要有以下几个亮点&#xff1a;事件驱动&#xff08; event-driven&#xff09;&#xff0c;高性能;轻量级&#xff0c;专注于网络&#xff0c;不如 ACE 那么臃肿庞大&#xff1b;源代码相当精炼、易读…

Linux/Knife

Knife Enumeration nmap 第一次扫描发现系统对外开放了22和80端口&#xff0c;端口详细信息如下 系统对外开放了2个端口&#xff0c;22的ssh和80的http&#xff0c;先访问web看看 单看该服务&#xff0c;并没有发现有趣的东西&#xff0c;wappalyzer显示php版本为8.1.0 PHP…

React报错 之 Objects are not valid as a React child

原文链接&#xff1a; 1、React报错之Objects are not valid as a React child 2、Objects are not valid as a React child error [Solved] 作者&#xff1a;Borislav Hadzhiev 以下文中涉及到的链接均来自于该作者&#xff0c;他写了很多相关的文章&#xff0c;可以多看看他的…

Type-C接口小家电使用PD诱骗芯片获取充电器的5V9V12V20V供电

随着Type-C接口的逐渐普及&#xff0c;小家电设备慢慢开始采用Type-C&#xff0c;淘汰了以往的DC接口&#xff0c;Type-C接口在小家电设备中的应用也越来越广泛。Type-C接口支持大电流宽电压范围&#xff0c;如何确保设备能够正确识别并使用各种电压&#xff08;例如5V、9V、12…