android7dlopen,Android 7.0 dlopen 函数分析

android7dlopen,Android 7.0 dlopen 函数分析1 说明 Android7 0 后使用 dlopen 函数无法获取 soinfo 对应 因此也无法使用 dlsym 函数去调用第三方的 so 内的函数 这里给出 dlopen 函数的源码分析 2 源码分析 1 dlopen 函数函数调用会首先走到 dlfcn cpp 类内的 dlopen 函数 bionic linker dlfcn cpp 85void dlopen constch

1. 说明

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

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* 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 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(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(RTLD_DEFAULT) ||

3463 handle_ == reinterpret_cast(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 g_soinfo_handles_map 内,这个值与 soinfo 对应。

4. soinfo 结构体

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

176struct soinfo {

177 public:

178 typedef LinkedList soinfo_list_t;

179 typedef LinkedList android_namespace_list_t;

180#if defined(__work_around_b___)

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___)

192 uint32_t unused1; // DO NOT USE, maintained for compatibility.

193#endif

194

195 ElfW(Dyn)* dynamic;

196

197#if defined(__work_around_b___)

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___)

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<: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

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<: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};

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/224284.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午12:17
下一篇 2026年3月17日 下午12:17


相关推荐

  • eclipse中配置jdk

    eclipse中配置jdkwindow->preference->java->installjres->add->standardvm->设置好相应的jrehomeeclipse的实验版本:Version:4.3.0.v20130605-20001、点击eclipse菜单栏的window下拉菜单选中preference2、点击…

    2022年6月16日
    31
  • 汇编中的inc和dec

    汇编中的inc和dec

    2021年5月26日
    189
  • 个人电脑怎么架设FTP服务器全方案

    个人电脑怎么架设FTP服务器全方案1、架设FTP服务器1.1使用IIS架设FTP服务器如果只是想建立一个小型的同时在线用户数不超过10个的FTP服务器,且不会同时进行大流量的数据传输,则可以使用IIS5作为服务器软件来架设.这里我们对一下案例予以说明,大家借鉴:一台1.1.1安装IIS的FTP服务WindowsXP默认状态是不安装FTP服务的,需要手动添加安装,安装过程如下:(…

    2022年7月21日
    15
  • Claude Code 如何集成到 VSCode、PyCharm IDE 及使用技巧 · 测试之家

    Claude Code 如何集成到 VSCode、PyCharm IDE 及使用技巧 · 测试之家

    2026年3月16日
    1
  • savefiledialog是什么对话框_saveshowfile什么意思

    savefiledialog是什么对话框_saveshowfile什么意思c#获取要保存文件的对话框,用SaveFileDialog类。具体用法很简单分享一下吧,对于初学者可能有用//可能要获取的路径名stringlocalFilePath=””,fileNameExt=””,newFileName=””,FilePath =””;SaveFileDialogsaveFileDialog=newSaveFileDialog();

    2022年10月8日
    5
  • 软件测试基础知识整理(详细版)

    软件测试基础知识整理(详细版)一 软件测试概述 1 软件缺陷软件缺陷 又称之为 Bug 即计算机软件或程序中存在的某种破坏正常运行能力的问题 错误 或者隐藏的功能缺陷 缺陷的表现形式 软件没有实现产品规格说明书所要求的功能模块 软件中出现了产品规格说明指明不应该出现的错误 软件实现了产品规格说明中没有提到的功能需求 软件没有实现虽然产品规格说明没有明确提及但应该实现的目标 软件难以理解 不易使用 运行缓慢 用户体验不友好 产生软件缺陷的原因 需求不清晰 系统结构较为复杂 对程序逻辑路径或者数据范围考虑不全面

    2026年3月18日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号