android linker加载
16lz
2021-01-23
linker是android的加载器和连接器,同时也是其自身的加载器。
将堆栈指针sp给r0,然后跳到函数__linker_init,传入的参数就是r0,返回值为程序镜像的入口地址,传给pc,开始正式地执行程序。
调用 __linker_init() 之前,linker 的重定位还没有完成(GOT还不可用),所以任何对外部变量或函数的引用都会产生 segfault,google已对__linker_init作出明确说明:extern "C" ElfW(Addr) __linker_init(void* raw_args);
二、__linker_init()实现
__linker_init()code位置,bionic/linker/linker_main.cpp
其第一步就是对参数进行解析,KernelArgumentBlock是一个类
KernelArgumentBlock args(raw_args);
其构造函数如下,可见主要是从参数解析出argc、argv、envp、auxv等参数,最终这几个参数会在linker加载完毕后赋值给linker的几个全局变量
三、prelink_image()的实现
四、link_image实现
五、__linker_init_post_relocation()是完成重定位后的一些处理,例如注册信号处理函数。
参考:
https://blog.csdn.net/xiongtiancheng/article/details/78786389
https://www.cnblogs.com/ilocker/p/4540797.html
https://blog.csdn.net/wl429585967/article/details/51019906
https://blog.csdn.net/suningning/article/details/61429932
bionic/linker/arch/arm64/begin.S29#include 3031ENTRY(_start)32 mov x0, sp33 bl __linker_init3435 /* linker init returns the _entry address in the main image */36 br x037END(_start)
将堆栈指针sp给r0,然后跳到函数__linker_init,传入的参数就是r0,返回值为程序镜像的入口地址,传给pc,开始正式地执行程序。
调用 __linker_init() 之前,linker 的重定位还没有完成(GOT还不可用),所以任何对外部变量或函数的引用都会产生 segfault,google已对__linker_init作出明确说明:extern "C" ElfW(Addr) __linker_init(void* raw_args);
二、__linker_init()实现
__linker_init()code位置,bionic/linker/linker_main.cpp
其第一步就是对参数进行解析,KernelArgumentBlock是一个类
KernelArgumentBlock args(raw_args);
其构造函数如下,可见主要是从参数解析出argc、argv、envp、auxv等参数,最终这几个参数会在linker加载完毕后赋值给linker的几个全局变量
35 KernelArgumentBlock(void* raw_args) {36 uintptr_t* args = reinterpret_cast(raw_args);37 argc = static_cast(*args);38 argv = reinterpret_cast(args + 1);39 envp = argv + argc + 1;4041 // Skip over all environment variable definitions to find the aux vector.42 // The end of the environment block is marked by a NULL pointer.43 char** p = envp;44 while (*p != NULL) {45 ++p;46 }47 ++p; // Skip the NULL itself.4849 auxv = reinterpret_cast(p);50 }
//最后会赋值给几个全局变量 535 g_argc = args.argc;536 g_argv = args.argv;537 g_envp = args.envp;
然后,获取linker的入口、elf header、程序头(program header,elf文件的一个段)地址 490 ElfW(Addr) entry_point = args.getauxval(AT_ENTRY);491 ElfW(Ehdr)* elf_hdr = reinterpret_cast(linker_addr);492 ElfW(Phdr)* phdr = reinterpret_cast(linker_addr + elf_hdr->e_phoff);
//初始化soinfo对象成员,其描述了so库的 494 soinfo linker_so(nullptr, nullptr, nullptr, 0, 0);495496 linker_so.base = linker_addr;//linker地址497 linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum);//获取linker镜像大小,仅计算load字段,且页对齐,也可以readelf -S linker查看498 linker_so.load_bias = get_elf_exec_load_bias(elf_hdr);//linker内存中的加载虚拟地址499 linker_so.dynamic = nullptr;500 linker_so.phdr = phdr;501 linker_so.phnum = elf_hdr->e_phnum;502 linker_so.set_linker_flag(); //flags!=FLAG_LINKER
//调用phdr_table_get_dynamic_section函数,获取PT_DYNAMIC段,然后解析并保存相关内容,包括了init_array、string表、system table表等等505 if (!linker_so.prelink_image()) __linker_cannot_link(args.argv[0]); //完成linker的重定位,重点是里面调用的relocate方法,根据.rela.dyn 、.rela.plt的信息修改got表中的内容513 if (!linker_so.link_image(g_empty_list, g_empty_list, nullptr)) __linker_cannot_link(args.argv[0]);524 //主要初始化pthread_internal_t对象main_thread的各个成员525 __libc_init_main_thread(args);526527 // We didn't protect the linker's RELRO pages in link_image because we528 // couldn't make system calls on x86 at that point, but we can now...529 if (!linker_so.protect_relro()) __linker_cannot_link(args.argv[0]);530531 // 初始化libc的静态全局变量,如 __libc_globals、__libc_auxv等532 __libc_init_globals(args);539 //调用linker的构造方法,初始化linker的全局变量,即执行init段540 linker_so.call_constructors();...... //主要是new 一个soinfo对象,并初始化成员,kLinkerPath即路径/system/bin/linker,并保存在全局对象g_default_namespace的一个成员Vector中558 sonext = solist = get_libdl_info(kLinkerPath);559 g_default_namespace.add_soinfo(solist);560561 // linker已重定位完毕,准备执行563 args.abort_message_ptr = &g_abort_message;564 ElfW(Addr) start_address = __linker_init_post_relocation(args, linker_addr);568 //返回要执行的汇编地址569 return start_address;570}
三、prelink_image()的实现
2822bool soinfo::prelink_image() {2823 //提取动态节(dynamic section)2825 phdr_table_get_dynamic_section(phdr, phnum, load_bias, &dynamic, &dynamic_flags);28262827 /* We can't log anything until the linker is relocated */2828 bool relocating_linker = (flags_ & FLAG_LINKER) != 0;......2850 // 从动态节提取有用信息2854 // source: http://www.sco.com/developers/gabi/1998-04-29/ch5.dynamic.html2855 uint32_t needed_count = 0; //循环遍历每个动态节,并做对应节处理2856 for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {2857 DEBUG("d = %p, d[0](tag) = %p d[1](val) = %p",2858 d, reinterpret_cast(d->d_tag), reinterpret_cast(d->d_un.d_val));2859 switch (d->d_tag) {2860 case DT_SONAME:2861 // this is parsed after we have strtab initialized (see below).2862 break;28632864 case DT_HASH:2865 nbucket_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[0];2866 nchain_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[1];2867 bucket_ = reinterpret_cast(load_bias + d->d_un.d_ptr + 8);2868 chain_ = reinterpret_cast(load_bias + d->d_un.d_ptr + 8 + nbucket_ * 4);2869 break;28702871 case DT_GNU_HASH:2872 gnu_nbucket_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[0];2873 // skip symndx2874 gnu_maskwords_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[2];2875 gnu_shift2_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[3];28762877 gnu_bloom_filter_ = reinterpret_cast(load_bias + d->d_un.d_ptr + 16);2878 gnu_bucket_ = reinterpret_cast(gnu_bloom_filter_ + gnu_maskwords_);2879 // amend chain for symndx = header[1]2880 gnu_chain_ = gnu_bucket_ + gnu_nbucket_ -2881 reinterpret_cast(load_bias + d->d_un.d_ptr)[1];28822883 if (!powerof2(gnu_maskwords_)) {2884 DL_ERR("invalid maskwords for gnu_hash = 0x%x, in \"%s\" expecting power to two",2885 gnu_maskwords_, get_realpath());2886 return false;2887 }2888 --gnu_maskwords_;28892890 flags_ |= FLAG_GNU_HASH;2891 break;28922893 case DT_STRTAB:2894 strtab_ = reinterpret_cast(load_bias + d->d_un.d_ptr);2895 break;28962897 case DT_STRSZ:2898 strtab_size_ = d->d_un.d_val;2899 break;29002901 case DT_SYMTAB:2902 symtab_ = reinterpret_cast(load_bias + d->d_un.d_ptr);2903 break;29042905 case DT_SYMENT:2906 if (d->d_un.d_val != sizeof(ElfW(Sym))) {2907 DL_ERR("invalid DT_SYMENT: %zd in \"%s\"",2908 static_cast(d->d_un.d_val), get_realpath());2909 return false;2910 }2911 break;29122913 case DT_PLTREL:2914#if defined(USE_RELA)2915 if (d->d_un.d_val != DT_RELA) {2916 DL_ERR("unsupported DT_PLTREL in \"%s\"; expected DT_RELA", get_realpath());2917 return false;2918 }2919#else2920 if (d->d_un.d_val != DT_REL) {2921 DL_ERR("unsupported DT_PLTREL in \"%s\"; expected DT_REL", get_realpath());2922 return false;2923 }2924#endif2925 break;29262927 case DT_JMPREL:2928#if defined(USE_RELA)2929 plt_rela_ = reinterpret_cast(load_bias + d->d_un.d_ptr);2930#else2931 plt_rel_ = reinterpret_cast(load_bias + d->d_un.d_ptr);2932#endif2933 break;29342935 case DT_PLTRELSZ:2936#if defined(USE_RELA)2937 plt_rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));2938#else2939 plt_rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel));2940#endif2941 break;2951 case DT_DEBUG:2952 // Set the DT_DEBUG entry to the address of _r_debug for GDB2953 // if the dynamic table is writable2963 break;2965 case DT_RELA:2966 rela_ = reinterpret_cast(load_bias + d->d_un.d_ptr);2967 break;29682969 case DT_RELASZ:2970 rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));2971 break;29722973 case DT_ANDROID_RELA:2974 android_relocs_ = reinterpret_cast(load_bias + d->d_un.d_ptr);2975 break;29762977 case DT_ANDROID_RELASZ:2978 android_relocs_size_ = d->d_un.d_val;2979 break;29802981 case DT_ANDROID_REL:2982 DL_ERR("unsupported DT_ANDROID_REL in \"%s\"", get_realpath());2983 return false;29842985 case DT_ANDROID_RELSZ:2986 DL_ERR("unsupported DT_ANDROID_RELSZ in \"%s\"", get_realpath());2987 return false;29882989 case DT_RELAENT:2990 if (d->d_un.d_val != sizeof(ElfW(Rela))) {2991 DL_ERR("invalid DT_RELAENT: %zd", static_cast(d->d_un.d_val));2992 return false;2993 }2994 break;29952996 // ignored (see DT_RELCOUNT comments for details)2997 case DT_RELACOUNT:2998 break;29993000 case DT_REL:3001 DL_ERR("unsupported DT_REL in \"%s\"", get_realpath());3002 return false;30033004 case DT_RELSZ:3005 DL_ERR("unsupported DT_RELSZ in \"%s\"", get_realpath());3006 return false;3057 case DT_INIT:3058 init_func_ = reinterpret_cast(load_bias + d->d_un.d_ptr);3059 DEBUG("%s constructors (DT_INIT) found at %p", get_realpath(), init_func_);3060 break;30613062 case DT_FINI:3063 fini_func_ = reinterpret_cast(load_bias + d->d_un.d_ptr);3064 DEBUG("%s destructors (DT_FINI) found at %p", get_realpath(), fini_func_);3065 break;30663067 case DT_INIT_ARRAY:3068 init_array_ = reinterpret_cast(load_bias + d->d_un.d_ptr);3069 DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", get_realpath(), init_array_);3070 break;30713072 case DT_INIT_ARRAYSZ:3073 init_array_count_ = static_cast(d->d_un.d_val) / sizeof(ElfW(Addr));3074 break;30753076 case DT_FINI_ARRAY:3077 fini_array_ = reinterpret_cast(load_bias + d->d_un.d_ptr);3078 DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", get_realpath(), fini_array_);3079 break;30803081 case DT_FINI_ARRAYSZ:3082 fini_array_count_ = static_cast(d->d_un.d_val) / sizeof(ElfW(Addr));3083 break;30843085 case DT_PREINIT_ARRAY:3086 preinit_array_ = reinterpret_cast(load_bias + d->d_un.d_ptr);3087 DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", get_realpath(), preinit_array_);3088 break;30893090 case DT_PREINIT_ARRAYSZ:3091 preinit_array_count_ = static_cast(d->d_un.d_val) / sizeof(ElfW(Addr));3092 break;30933094 case DT_TEXTREL:3103 case DT_SYMBOLIC:3104 has_DT_SYMBOLIC = true;3105 break;31063107 case DT_NEEDED:3108 ++needed_count;3109 break;31103111 case DT_FLAGS:3112 if (d->d_un.d_val & DF_TEXTREL) {3113#if defined(__LP64__)3114 DL_ERR("\"%s\" has text relocations", get_realpath());3115 return false;3116#else3117 has_text_relocations = true;3118#endif3119 }3120 if (d->d_un.d_val & DF_SYMBOLIC) {3121 has_DT_SYMBOLIC = true;3122 }3123 break;31243125 case DT_FLAGS_1:3126 set_dt_flags_1(d->d_un.d_val);31273128 if ((d->d_un.d_val & ~SUPPORTED_DT_FLAGS_1) != 0) {3129 DL_WARN("\"%s\" has unsupported flags DT_FLAGS_1=%p", get_realpath(), reinterpret_cast(d->d_un.d_val));3130 }3131 break;3167 // Ignored: "Its use has been superseded by the DF_BIND_NOW flag"3168 case DT_BIND_NOW:3169 break;31703171 case DT_VERSYM:3172 versym_ = reinterpret_cast(load_bias + d->d_un.d_ptr);3173 break;31743175 case DT_VERDEF:3176 verdef_ptr_ = load_bias + d->d_un.d_ptr;3177 break;3178 case DT_VERDEFNUM:3179 verdef_cnt_ = d->d_un.d_val;3180 break;31813182 case DT_VERNEED:3183 verneed_ptr_ = load_bias + d->d_un.d_ptr;3184 break;31853186 case DT_VERNEEDNUM:3187 verneed_cnt_ = d->d_un.d_val;3188 break;31893190 case DT_RUNPATH:3191 // this is parsed after we have strtab initialized (see below).3192 break;31933194 default:3195 if (!relocating_linker) {3196 DL_WARN("\"%s\" unused DT entry: type %p arg %p", get_realpath(),3197 reinterpret_cast(d->d_tag), reinterpret_cast(d->d_un.d_val));3198 }3199 break;3200 }3201 }3212 // Sanity checks.3213 if (relocating_linker && needed_count != 0) {3214 DL_ERR("linker cannot have DT_NEEDED dependencies on other libraries");3215 return false;3216 }3217 if (nbucket_ == 0 && gnu_nbucket_ == 0) {3218 DL_ERR("empty/missing DT_HASH/DT_GNU_HASH in \"%s\" "3219 "(new hash type from the future?)", get_realpath());3220 return false;3221 }3222 if (strtab_ == 0) {3223 DL_ERR("empty/missing DT_STRTAB in \"%s\"", get_realpath());3224 return false;3225 }3226 if (symtab_ == 0) {3227 DL_ERR("empty/missing DT_SYMTAB in \"%s\"", get_realpath());3228 return false;3229 }32303231 // second pass - parse entries relying on strtab3232 for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {3233 switch (d->d_tag) {3234 case DT_SONAME:3235 set_soname(get_string(d->d_un.d_val));3236 break;3237 case DT_RUNPATH:3238 set_dt_runpath(get_string(d->d_un.d_val));3239 break;3240 }3241 }32423243 // Before M release linker was using basename in place of soname.3244 // In the case when dt_soname is absent some apps stop working3245 // because they can't find dt_needed library by soname.3246 // This workaround should keep them working. (applies only3247 // for apps targeting sdk version < M). Make an exception for3248 // the main executable and linker; they do not need to have dt_soname3249 if (soname_ == nullptr &&3250 this != solist_get_somain() &&3251 (flags_ & FLAG_LINKER) == 0 &&3252 get_application_target_sdk_version() < __ANDROID_API_M__) {3253 soname_ = basename(realpath_.c_str());3254 DL_WARN("%s: is missing DT_SONAME will use basename as a replacement: \"%s\"",3255 get_realpath(), soname_);3256 // Don't call add_dlwarning because a missing DT_SONAME isn't important enough to show in the UI3257 }3258 return true;3259}
四、link_image实现
3261bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group,3262 const android_dlextinfo* extinfo) {32633264 local_group_root_ = local_group.front(); //当前是个空list3265 if (local_group_root_ == nullptr) {3266 local_group_root_ = this;3267 }32683269 if ((flags_ & FLAG_LINKER) == 0 && local_group_root_ == this) { //已经设置FLAG_LINKER3270 target_sdk_version_ = get_application_target_sdk_version();3271 }32723273 VersionTracker version_tracker;32743275 if (!version_tracker.init(this)) {3276 return false;3277 }......3299 if (android_relocs_ != nullptr) { //android_relocs_在prelink_image()中设置,动态节有DT_ANDROID_REL才会设置3300 // check signature3301 if (android_relocs_size_ > 3 &&3302 android_relocs_[0] == 'A' &&3303 android_relocs_[1] == 'P' &&3304 android_relocs_[2] == 'S' &&3305 android_relocs_[3] == '2') {3306 DEBUG("[ android relocating %s ]", get_realpath());33073308 bool relocated = false;3309 const uint8_t* packed_relocs = android_relocs_ + 4;3310 const size_t packed_relocs_size = android_relocs_size_ - 4;33113312 relocated = relocate(3313 version_tracker,3314 packed_reloc_iterator(3315 sleb128_decoder(packed_relocs, packed_relocs_size)),3316 global_group, local_group);//调用relocate完成重定位relocs33173318 if (!relocated) {3319 return false;3320 }3321 } else {3322 DL_ERR("bad android relocation header.");3323 return false;3324 }3325 }3328 if (rela_ != nullptr) { //rela_在prelink_image()中设置,动态节有DT_RELA才会设置3329 DEBUG("[ relocating %s ]", get_realpath());3330 if (!relocate(version_tracker, //调用relocate完成重定位rela_3331 plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) {3332 return false;3333 }3334 }3335 if (plt_rela_ != nullptr) {//plt_rela_在prelink_image()中设置,动态节有DT_RELA才会设置3336 DEBUG("[ relocating %s plt ]", get_realpath());3337 if (!relocate(version_tracker, //调用relocate完成重定位plt_rela_3338 plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) {3339 return false;3340 }3341 }......3378 // We can also turn on GNU RELRO protection if we're not linking the dynamic linker3379 // itself --- it can't make system calls yet, and will have to call protect_relro later.3380 if (!is_linker() && !protect_relro()) {//当前是linker3381 return false;3382 }33833384 /* Handle serializing/sharing the RELRO segment */3385 if (extinfo && (extinfo->flags & ANDROID_DLEXT_WRITE_RELRO)) {3386 if (phdr_table_serialize_gnu_relro(phdr, phnum, load_bias,3387 extinfo->relro_fd) < 0) {3388 DL_ERR("failed serializing GNU RELRO section for \"%s\": %s",3389 get_realpath(), strerror(errno));3390 return false;3391 }3392 } else if (extinfo && (extinfo->flags & ANDROID_DLEXT_USE_RELRO)) {3393 if (phdr_table_map_gnu_relro(phdr, phnum, load_bias,3394 extinfo->relro_fd) < 0) {3395 DL_ERR("failed mapping GNU RELRO section for \"%s\": %s",3396 get_realpath(), strerror(errno));3397 return false;3398 }3399 }34003401 notify_gdb_of_load(this);//linker不支持gdb debug3402 return true;3403}可见link_image方法也主要是调用了relocate完成重定位。
五、__linker_init_post_relocation()是完成重定位后的一些处理,例如注册信号处理函数。
211static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(Addr) linker_base) {220 __libc_init_AT_SECURE(args);221222 //初始化系统属性223 __system_properties_init(); // may use 'environ'224225 // Register the debuggerd signal handler.226#ifdef __ANDROID__227 debuggerd_callbacks_t callbacks = {228 .get_abort_message = []() {229 return g_abort_message;230 },231 .post_dump = ¬ify_gdb_of_libraries,232 };233 debuggerd_init(&callbacks); //很重要注册了7个信号处理函数234#endif235236 g_linker_logger.ResetState();237238 // Get a few environment variables.239 const char* LD_DEBUG = getenv("LD_DEBUG");240 if (LD_DEBUG != nullptr) {241 g_ld_debug_verbosity = atoi(LD_DEBUG);242 }......254 if (!getauxval(AT_SECURE)) {255 ldpath_env = getenv("LD_LIBRARY_PATH");256 if (ldpath_env != nullptr) {257 INFO("[ LD_LIBRARY_PATH set to \"%s\" ]", ldpath_env);258 }259 ldpreload_env = getenv("LD_PRELOAD");260 if (ldpreload_env != nullptr) {261 INFO("[ LD_PRELOAD set to \"%s\" ]", ldpreload_env);262 }263 }264265 struct stat file_stat;269 if (TEMP_FAILURE_RETRY(stat("/proc/self/exe", &file_stat)) != 0) {270 __libc_fatal("unable to stat \"/proc/self/exe\": %s", strerror(errno));271 }272273 const char* executable_path = get_executable_path();274 soinfo* si = soinfo_alloc(&g_default_namespace, executable_path, &file_stat, 0, RTLD_GLOBAL);275 if (si == nullptr) {276 __libc_fatal("Couldn't allocate soinfo: out of memory?");277 }278279 /* bootstrap the link map, the main exe always needs to be first */280 si->set_main_executable();281 link_map* map = &(si->link_map_head);282283 // Register the main executable and the linker upfront to have284 // gdb aware of them before loading the rest of the dependency285 // tree.286 map->l_addr = 0;287 map->l_name = const_cast(executable_path);288 insert_link_map_into_debug_map(map);289 init_linker_info_for_gdb(linker_base, kLinkerPath);290291 // Extract information passed from the kernel.292 si->phdr = reinterpret_cast(args.getauxval(AT_PHDR));293 si->phnum = args.getauxval(AT_PHNUM);294295 /* Compute the value of si->base. We can't rely on the fact that296 * the first entry is the PHDR because this will not be true297 * for certain executables (e.g. some in the NDK unit test suite)298 */299 si->base = 0;300 si->size = phdr_table_get_load_size(si->phdr, si->phnum);301 si->load_bias = 0;302 for (size_t i = 0; i < si->phnum; ++i) {303 if (si->phdr[i].p_type == PT_PHDR) {304 si->load_bias = reinterpret_cast(si->phdr) - si->phdr[i].p_vaddr;305 si->base = reinterpret_cast(si->phdr) - si->phdr[i].p_offset;306 break;307 }308 }309 si->dynamic = nullptr;310311 ElfW(Ehdr)* elf_hdr = reinterpret_cast(si->base);312......329 // Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).330 parse_LD_LIBRARY_PATH(ldpath_env);331 parse_LD_PRELOAD(ldpreload_env);332333 somain = si;334335 init_default_namespace(executable_path);336337 if (!si->prelink_image()) {338 __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());339 }340341 // add somain to global group342 si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);343344 // Load ld_preloads and dependencies.345 std::vector needed_library_name_list;346 size_t ld_preloads_count = 0;347348 for (const auto& ld_preload_name : g_ld_preload_names) {349 needed_library_name_list.push_back(ld_preload_name.c_str());350 ++ld_preloads_count;351 }352353 for_each_dt_needed(si, [&](const char* name) {354 needed_library_name_list.push_back(name);355 });356 //找出依赖库,并调用find_libraries357 const char** needed_library_names = &needed_library_name_list[0];358 size_t needed_libraries_count = needed_library_name_list.size();359360 if (needed_libraries_count > 0 &&361 !find_libraries(&g_default_namespace,362 si,363 needed_library_names,364 needed_libraries_count,365 nullptr,366 &g_ld_preloads,367 ld_preloads_count,368 RTLD_GLOBAL,369 nullptr,370 true /* add_as_children */,371 true /* search_linked_namespaces */)) {372 __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());373 } else if (needed_libraries_count == 0) {374 if (!si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr)) {375 __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());376 }377 si->increment_ref_count();378 }379380 add_vdso(args);381382 if (!get_cfi_shadow()->InitialLinkDone(solist)) {383 __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());384 }385386 si->call_pre_init_constructors();387388 /* After the prelink_image, the si->load_bias is initialized.389 * For so lib, the map->l_addr will be updated in notify_gdb_of_load.390 * We need to update this value for so exe here. So Unwind_Backtrace391 * for some arch like x86 could work correctly within so exe.392 */393 map->l_addr = si->load_bias;394 si->call_constructors();395......437 ElfW(Addr) entry = args.getauxval(AT_ENTRY);//程序执行入口438 TRACE("[ Ready to execute \"%s\" @ %p ]", si->get_realpath(), reinterpret_cast(entry));439 return entry;440}
参考:
https://blog.csdn.net/xiongtiancheng/article/details/78786389
https://www.cnblogs.com/ilocker/p/4540797.html
https://blog.csdn.net/wl429585967/article/details/51019906
https://blog.csdn.net/suningning/article/details/61429932
更多相关文章
- Android学习(十) SQLite 基于内置函数的操作方式
- android的webview调用javascript函数并得到返回值
- 可动态布局的Android抽屉之完整篇
- Android 数据查询query函数参数解析
- android中的类加载和静态成员变量的初始化
- android动态申请拍照获取照片权限
- Android中显示gif动态图片
- Android 禁止屏幕旋转 & 屏幕旋转不刷新 Activity & 动态更改屏