美文网首页
Android 7.0 dlopen 函数分析

Android 7.0 dlopen 函数分析

作者: that_is_this | 来源:发表于2018-04-09 11:56 被阅读908次

    1. 说明

    Android 7.0 后使用 dlopen 函数无法获取 soinfo 对应,因此也无法使用 dlsym 函数去调用第三方的 so 内的函数。这里给出 dlopen() 函数的源码分析。

    不同点可参考:https://blog.csdn.net/u011247544/article/details/75262360

    2. 源码分析

    1. dlopen 函数

    函数调用会首先走到 dlfcn.cpp 类内的 dlopen 函数(/bionic/linker/dlfcn.cpp)

    85void* dlopen(const char* filename, int flags) {
    86  void* caller_addr = __builtin_return_address(0);
    87  return dlopen_ext(filename, flags, nullptr, caller_addr);
    88}
    
    69static void* dlopen_ext(const char* filename, int flags,
    70                        const android_dlextinfo* extinfo, void* caller_addr) {
    71  ScopedPthreadMutexLocker locker(&g_dl_mutex);
    72  void* result = do_dlopen(filename, flags, extinfo, caller_addr);        // 调到 linker.cpp 类内
    73  if (result == nullptr) {
    74    __bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
    75    return nullptr;
    76  }
    77  return result;
    78}
    

    2. do_dlopen() 函数

    这个函数实现在 linker.cpp 类内。do_dlopen 函数会调用 find_library 函数返回 soinfo 对象,并最终调用 si->to_handle() 函数返回 handle_。(/bionic/linker/linker.cpp)

    2333void* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo,
    2334                  void* caller_addr) {
    2335  soinfo* const caller = find_containing_library(caller_addr);
    2336
    2337  if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) {
    2338    DL_ERR("invalid flags to dlopen: %x", flags);
    2339    return nullptr;
    2340  }
    2341
    2342  android_namespace_t* ns = get_caller_namespace(caller);
    2343
    2344  if (extinfo != nullptr) {
    2345    if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {
    2346      DL_ERR("invalid extended flags to android_dlopen_ext: 0x%" PRIx64, extinfo->flags);
    2347      return nullptr;
    2348    }
    2349
    2350    if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 &&
    2351        (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
    2352      DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without "
    2353          "ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags);
    2354      return nullptr;
    2355    }
    2356
    2357    if ((extinfo->flags & ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS) != 0 &&
    2358        (extinfo->flags & (ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_RESERVED_ADDRESS_HINT)) != 0) {
    2359      DL_ERR("invalid extended flag combination: ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS is not "
    2360             "compatible with ANDROID_DLEXT_RESERVED_ADDRESS/ANDROID_DLEXT_RESERVED_ADDRESS_HINT");
    2361      return nullptr;
    2362    }
    2363
    2364    if ((extinfo->flags & ANDROID_DLEXT_USE_NAMESPACE) != 0) {
    2365      if (extinfo->library_namespace == nullptr) {
    2366        DL_ERR("ANDROID_DLEXT_USE_NAMESPACE is set but extinfo->library_namespace is null");
    2367        return nullptr;
    2368      }
    2369      ns = extinfo->library_namespace;
    2370    }
    2371  }
    2372
    2373  ProtectedDataGuard guard;
    2374  soinfo* si = find_library(ns, name, flags, extinfo, caller);      // 这里往下调用返回 soinfo 对象
    2375  if (si != nullptr) {
    2376    si->call_constructors();
    2377    return si->to_handle();       // 这里返回的是 调用 to_handle() 函数
    2378  }
    2379
    2380  return nullptr;
    2381}
    

    下面给处 find_library 函数的追踪:

    首先是 find_library 函数

    2159static soinfo* find_library(android_namespace_t* ns,
    2160                            const char* name, int rtld_flags,
    2161                            const android_dlextinfo* extinfo,
    2162                            soinfo* needed_by) {
    2163  soinfo* si;
    2164
    2165  if (name == nullptr) {
    2166    si = somain;
    2167  } else if (!find_libraries(ns, needed_by, &name, 1, &si, nullptr, 0, rtld_flags,
    2168                             extinfo, /* add_as_children */ false)) {
    2169    return nullptr;
    2170  }
    2171
    2172  return si;
    2173}
    

    接着是 find_libraries 函数,源码分析知道这个函数分为 4 步,暂未做具体分析

    1994static bool find_libraries(android_namespace_t* ns,
    1995                           soinfo* start_with,
    1996                           const char* const library_names[],
    1997                           size_t library_names_count, soinfo* soinfos[],
    1998                           std::vector<soinfo*>* ld_preloads,
    1999                           size_t ld_preloads_count, int rtld_flags,
    2000                           const android_dlextinfo* extinfo,
    2001                           bool add_as_children) {
    2002  // Step 0: prepare.
    2003  LoadTaskList load_tasks;
    2004  std::unordered_map<const soinfo*, ElfReader> readers_map;
    ...
    2053    if(!find_library_internal(ns, task, &zip_archive_cache, &load_tasks, rtld_flags)) {
    2054      return false;
    2055    }
    ...
    2156  return linked;
    2157}
    

    然后是 find_library_internal 函数

    1896static bool find_library_internal(android_namespace_t* ns,
    1897                                  LoadTask* task,
    1898                                  ZipArchiveCache* zip_archive_cache,
    1899                                  LoadTaskList* load_tasks,
    1900                                  int rtld_flags) {
    1901  soinfo* candidate;
    1902
    1903  if (find_loaded_library_by_soname(ns, task->get_name(), &candidate)) {
    1904    task->set_soinfo(candidate);
    1905    return true;
    1906  }
    1907
    1908  if (ns != &g_default_namespace) {
    1909    // check public namespace
    1910    candidate = g_public_namespace.find_if([&](soinfo* si) {
    1911      return strcmp(task->get_name(), si->get_soname()) == 0;
    1912    });
    1913
    1914    if (candidate != nullptr) {
    1915      ns->add_soinfo(candidate);
    1916      task->set_soinfo(candidate);
    1917      return true;
    1918    }
    1919  }
    1920
    1921  // Library might still be loaded, the accurate detection
    1922  // of this fact is done by load_library.
    1923  TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder...]",
    1924      task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
    1925
    1926  if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags)) {
    1927    return true;
    1928  } else {
    1929    // In case we were unable to load the library but there
    1930    // is a candidate loaded under the same soname but different
    1931    // sdk level - return it anyways.
    1932    if (candidate != nullptr) {
    1933      task->set_soinfo(candidate);
    1934      return true;
    1935    }
    1936  }
    1937
    1938  return false;
    1939}
    

    3. soinfo::to_handle() 函数

    (/bionic/linker/linker.cpp)
    do_dlopen 函数的最终返回是这个函数的返回,看下 这个函数的实现:

    3442void* soinfo::to_handle() {
    3443  if (get_application_target_sdk_version() <= 23 || !has_min_version(3)) {
    3444    return this;
    3445  }
    3446
    3447  return reinterpret_cast<void*>(get_handle());
    3448}
    

    然后调用了 get_handle() 函数。这个函数就是返回了 handle_

    3436uintptr_t soinfo::get_handle() const {
    3437  CHECK(has_min_version(3));
    3438  CHECK(handle_ != 0);
    3439  return handle_;
    3440}
    

    那 handle_ 的生成是在哪里呢?是在同目录下的 generate_handle 函数

    3450void soinfo::generate_handle() {
    3451  CHECK(has_min_version(3));
    3452  CHECK(handle_ == 0); // Make sure this is the first call
    3453
    3454  // Make sure the handle is unique and does not collide
    3455  // with special values which are RTLD_DEFAULT and RTLD_NEXT.
    3456  do {
    3457    arc4random_buf(&handle_, sizeof(handle_));
    3458    // the least significant bit for the handle is always 1
    3459    // making it easy to test the type of handle passed to
    3460    // dl* functions.
    3461    handle_ = handle_ | 1;
    3462  } while (handle_ == reinterpret_cast<uintptr_t>(RTLD_DEFAULT) ||
    3463           handle_ == reinterpret_cast<uintptr_t>(RTLD_NEXT) ||
    3464           g_soinfo_handles_map.find(handle_) != g_soinfo_handles_map.end());
    3465
    3466  g_soinfo_handles_map[handle_] = this;
    3467}
    

    由上可以看出, handle_ 是 arc4random_buf(&handle_, sizeof(handle_)); 函数生成的随机值。并将这个值放到 static std::unordered_map<uintptr_t, soinfo*> g_soinfo_handles_map 内,这个值与 soinfo 对应。

    4. soinfo 结构体

    soinfo 结构体就是 so 文件解析后的数据信息,解析处的 节信息,等等等等~~

    176struct soinfo {
    177 public:
    178  typedef LinkedList<soinfo, SoinfoListAllocator> soinfo_list_t;
    179  typedef LinkedList<android_namespace_t, NamespaceListAllocator> android_namespace_list_t;
    180#if defined(__work_around_b_24465209__)
    181 private:
    182  char old_name_[SOINFO_NAME_LEN];
    183#endif
    184 public:
    185  const ElfW(Phdr)* phdr;
    186  size_t phnum;
    187  ElfW(Addr) entry;
    188  ElfW(Addr) base;
    189  size_t size;
    190
    191#if defined(__work_around_b_24465209__)
    192  uint32_t unused1;  // DO NOT USE, maintained for compatibility.
    193#endif
    194
    195  ElfW(Dyn)* dynamic;
    196
    197#if defined(__work_around_b_24465209__)
    198  uint32_t unused2; // DO NOT USE, maintained for compatibility
    199  uint32_t unused3; // DO NOT USE, maintained for compatibility
    200#endif
    201
    202  soinfo* next;
    203 private:
    204  uint32_t flags_;
    205
    206  const char* strtab_;
    207  ElfW(Sym)* symtab_;
    208
    209  size_t nbucket_;
    210  size_t nchain_;
    211  uint32_t* bucket_;
    212  uint32_t* chain_;
    213
    214#if defined(__mips__) || !defined(__LP64__)
    215  // This is only used by mips and mips64, but needs to be here for
    216  // all 32-bit architectures to preserve binary compatibility.
    217  ElfW(Addr)** plt_got_;
    218#endif
    219
    220#if defined(USE_RELA)
    221  ElfW(Rela)* plt_rela_;
    222  size_t plt_rela_count_;
    223
    224  ElfW(Rela)* rela_;
    225  size_t rela_count_;
    226#else
    227  ElfW(Rel)* plt_rel_;
    228  size_t plt_rel_count_;
    229
    230  ElfW(Rel)* rel_;
    231  size_t rel_count_;
    232#endif
    233
    234  linker_function_t* preinit_array_;
    235  size_t preinit_array_count_;
    236
    237  linker_function_t* init_array_;
    238  size_t init_array_count_;
    239  linker_function_t* fini_array_;
    240  size_t fini_array_count_;
    241
    242  linker_function_t init_func_;
    243  linker_function_t fini_func_;
    244
    245#if defined(__arm__)
    246 public:
    247  // ARM EABI section used for stack unwinding.
    248  uint32_t* ARM_exidx;
    249  size_t ARM_exidx_count;
    250 private:
    251#elif defined(__mips__)
    252  uint32_t mips_symtabno_;
    253  uint32_t mips_local_gotno_;
    254  uint32_t mips_gotsym_;
    255  bool mips_relocate_got(const VersionTracker& version_tracker,
    256                         const soinfo_list_t& global_group,
    257                         const soinfo_list_t& local_group);
    258#if !defined(__LP64__)
    259  bool mips_check_and_adjust_fp_modes();
    260#endif
    261#endif
    262  size_t ref_count_;
    263 public:
    264  link_map link_map_head;
    265
    266  bool constructors_called;
    267
    268  // When you read a virtual address from the ELF file, add this
    269  // value to get the corresponding address in the process' address space.
    270  ElfW(Addr) load_bias;
    271
    272#if !defined(__LP64__)
    273  bool has_text_relocations;
    274#endif
    275  bool has_DT_SYMBOLIC;
    276
    277 public:
    278  soinfo(android_namespace_t* ns, const char* name, const struct stat* file_stat,
    279         off64_t file_offset, int rtld_flags);
    280  ~soinfo();
    281
    282  void call_constructors();
    283  void call_destructors();
    284  void call_pre_init_constructors();
    285  bool prelink_image();
    286  bool link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,
    287                  const android_dlextinfo* extinfo);
    288  bool protect_relro();
    289
    290  void add_child(soinfo* child);
    291  void remove_all_links();
    292
    293  ino_t get_st_ino() const;
    294  dev_t get_st_dev() const;
    295  off64_t get_file_offset() const;
    296
    297  uint32_t get_rtld_flags() const;
    298  uint32_t get_dt_flags_1() const;
    299  void set_dt_flags_1(uint32_t dt_flags_1);
    300
    301  soinfo_list_t& get_children();
    302  const soinfo_list_t& get_children() const;
    303
    304  soinfo_list_t& get_parents();
    305
    306  bool find_symbol_by_name(SymbolName& symbol_name,
    307                           const version_info* vi,
    308                           const ElfW(Sym)** symbol) const;
    309
    310  ElfW(Sym)* find_symbol_by_address(const void* addr);
    311  ElfW(Addr) resolve_symbol_address(const ElfW(Sym)* s) const;
    312
    313  const char* get_string(ElfW(Word) index) const;
    314  bool can_unload() const;
    315  bool is_gnu_hash() const;
    316
    317  bool inline has_min_version(uint32_t min_version __unused) const {
    318#if defined(__work_around_b_24465209__)
    319    return (flags_ & FLAG_NEW_SOINFO) != 0 && version_ >= min_version;
    320#else
    321    return true;
    322#endif
    323  }
    325  bool is_linked() const;
    326  bool is_linker() const;
    327  bool is_main_executable() const;
    328
    329  void set_linked();
    330  void set_linker_flag();
    331  void set_main_executable();
    332  void set_nodelete();
    333
    334  void increment_ref_count();
    335  size_t decrement_ref_count();
    336
    337  soinfo* get_local_group_root() const;
    338
    339  void set_soname(const char* soname);
    340  const char* get_soname() const;
    341  const char* get_realpath() const;
    342  const ElfW(Versym)* get_versym(size_t n) const;
    343  ElfW(Addr) get_verneed_ptr() const;
    344  size_t get_verneed_cnt() const;
    345  ElfW(Addr) get_verdef_ptr() const;
    346  size_t get_verdef_cnt() const;
    347
    348  bool find_verdef_version_index(const version_info* vi, ElfW(Versym)* versym) const;
    349
    350  uint32_t get_target_sdk_version() const;
    351
    352  void set_dt_runpath(const char *);
    353  const std::vector<std::string>& get_dt_runpath() const;
    354  android_namespace_t* get_primary_namespace();
    355  void add_secondary_namespace(android_namespace_t* secondary_ns);
    356
    357  void set_mapped_by_caller(bool reserved_map);
    358  bool is_mapped_by_caller() const;
    359
    360  uintptr_t get_handle() const;
    361  void generate_handle();
    362  void* to_handle();
    363
    364 private:
    365  bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
    366  ElfW(Sym)* elf_addr_lookup(const void* addr);
    367  bool gnu_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
    368  ElfW(Sym)* gnu_addr_lookup(const void* addr);
    369
    370  bool lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym,
    371                           const char* sym_name, const version_info** vi);
    372
    373  void call_array(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
    374  void call_function(const char* function_name, linker_function_t function);
    375  template<typename ElfRelIteratorT>
    376  bool relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
    377                const soinfo_list_t& global_group, const soinfo_list_t& local_group);
    378
    379 private:
    380  // This part of the structure is only available
    381  // when FLAG_NEW_SOINFO is set in this->flags.
    382  uint32_t version_;
    383
    384  // version >= 0
    385  dev_t st_dev_;
    386  ino_t st_ino_;
    387
    388  // dependency graph
    389  soinfo_list_t children_;
    390  soinfo_list_t parents_;
    391
    392  // version >= 1
    393  off64_t file_offset_;
    394  uint32_t rtld_flags_;
    395  uint32_t dt_flags_1_;
    396  size_t strtab_size_;
    397
    398  // version >= 2
    399
    400  size_t gnu_nbucket_;
    401  uint32_t* gnu_bucket_;
    402  uint32_t* gnu_chain_;
    403  uint32_t gnu_maskwords_;
    404  uint32_t gnu_shift2_;
    405  ElfW(Addr)* gnu_bloom_filter_;
    406
    407  soinfo* local_group_root_;
    408
    409  uint8_t* android_relocs_;
    410  size_t android_relocs_size_;
    411
    412  const char* soname_;
    413  std::string realpath_;
    414
    415  const ElfW(Versym)* versym_;
    416
    417  ElfW(Addr) verdef_ptr_;
    418  size_t verdef_cnt_;
    419
    420  ElfW(Addr) verneed_ptr_;
    421  size_t verneed_cnt_;
    422
    423  uint32_t target_sdk_version_;
    424
    425  // version >= 3
    426  std::vector<std::string> dt_runpath_;
    427  android_namespace_t* primary_namespace_;
    428  android_namespace_list_t secondary_namespaces_;
    429  uintptr_t handle_;
    430
    431  friend soinfo* get_libdl_info();
    432};
    

    相关文章

      网友评论

          本文标题:Android 7.0 dlopen 函数分析

          本文链接:https://www.haomeiwen.com/subject/kpobhftx.html