• 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}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    /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}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    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}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    排除一大堆分支。可以很清楚的发现 核心代码就是调用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}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    这个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}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    通过注释好像标识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}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254

    看到这我第一时间感觉这块代码是不是大改过。应该是随着android迭代而增加的。本来不想粘怎么多代码的。但是看它写了这个函数的具体的操作的步骤,我就简单写一下把

    1. 全部代码都是围绕着LoadTask列表操作。第一步就是把所有依赖的so都找出来初始化load_tasks 列表。这个列表是 std::vector,猜测所有载入操作实际就是在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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
  • 相关阅读:
    appium默认60秒关闭应用的问题
    树莓派4B简单使用内容(以移植QT应用为例)
    2024Node.js零基础教程(小白友好型),nodejs新手到高手,(九)NodeJS入门——http模块
    Spring基础篇:注入
    RabbitMQ
    GROMACS Tutorial 5: Protein-Ligand Complex 中文实战教程
    KdMapper扩展实现之REALiX(hwinfo64a.sys)
    操作系统简介(上)
    [附源码]java毕业设计基于ssm的电子网上商城
    使用 Apache Kafka 实现 Quarkus 的反应式消息
  • 原文地址:https://blog.csdn.net/god_wen/article/details/136527072