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};
网友评论