linker是android的加载器和连接器,同时也是其自身的加载器。
bionic/linker/arch/arm64/begin.S
29#include
30
31ENTRY(_start)
32 mov x0, sp
33 bl __linker_init
34
35 /* linker init returns the _entry address in the main image */
36 br x0
37END(_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;
40
41 // 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.
48
49 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);
495
496 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);
526
527 // We didn't protect the linker's RELRO pages in link_image because we
528 // 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]);
530
531 // 初始化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);
560
561 // 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);
2826
2827 /* 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.html
2855 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;
2863
2864 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;
2870
2871 case DT_GNU_HASH:
2872 gnu_nbucket_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[0];
2873 // skip symndx
2874 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];
2876
2877 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];
2882
2883 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_;
2889
2890 flags_ |= FLAG_GNU_HASH;
2891 break;
2892
2893 case DT_STRTAB:
2894 strtab_ = reinterpret_cast(load_bias + d->d_un.d_ptr);
2895 break;
2896
2897 case DT_STRSZ:
2898 strtab_size_ = d->d_un.d_val;
2899 break;
2900
2901 case DT_SYMTAB:
2902 symtab_ = reinterpret_cast(load_bias + d->d_un.d_ptr);
2903 break;
2904
2905 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;
2912
2913 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#else
2920 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#endif
2925 break;
2926
2927 case DT_JMPREL:
2928#if defined(USE_RELA)
2929 plt_rela_ = reinterpret_cast(load_bias + d->d_un.d_ptr);
2930#else
2931 plt_rel_ = reinterpret_cast(load_bias + d->d_un.d_ptr);
2932#endif
2933 break;
2934
2935 case DT_PLTRELSZ:
2936#if defined(USE_RELA)
2937 plt_rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));
2938#else
2939 plt_rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel));
2940#endif
2941 break;
2951 case DT_DEBUG:
2952 // Set the DT_DEBUG entry to the address of _r_debug for GDB
2953 // if the dynamic table is writable
2963 break;
2965 case DT_RELA:
2966 rela_ = reinterpret_cast(load_bias + d->d_un.d_ptr);
2967 break;
2968
2969 case DT_RELASZ:
2970 rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela));
2971 break;
2972
2973 case DT_ANDROID_RELA:
2974 android_relocs_ = reinterpret_cast(load_bias + d->d_un.d_ptr);
2975 break;
2976
2977 case DT_ANDROID_RELASZ:
2978 android_relocs_size_ = d->d_un.d_val;
2979 break;
2980
2981 case DT_ANDROID_REL:
2982 DL_ERR("unsupported DT_ANDROID_REL in \"%s\"", get_realpath());
2983 return false;
2984
2985 case DT_ANDROID_RELSZ:
2986 DL_ERR("unsupported DT_ANDROID_RELSZ in \"%s\"", get_realpath());
2987 return false;
2988
2989 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;
2995
2996 // ignored (see DT_RELCOUNT comments for details)
2997 case DT_RELACOUNT:
2998 break;
2999
3000 case DT_REL:
3001 DL_ERR("unsupported DT_REL in \"%s\"", get_realpath());
3002 return false;
3003
3004 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;
3061
3062 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;
3066
3067 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;
3071
3072 case DT_INIT_ARRAYSZ:
3073 init_array_count_ = static_cast(d->d_un.d_val) / sizeof(ElfW(Addr));
3074 break;
3075
3076 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;
3080
3081 case DT_FINI_ARRAYSZ:
3082 fini_array_count_ = static_cast(d->d_un.d_val) / sizeof(ElfW(Addr));
3083 break;
3084
3085 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;
3089
3090 case DT_PREINIT_ARRAYSZ:
3091 preinit_array_count_ = static_cast(d->d_un.d_val) / sizeof(ElfW(Addr));
3092 break;
3093
3094 case DT_TEXTREL:
3103 case DT_SYMBOLIC:
3104 has_DT_SYMBOLIC = true;
3105 break;
3106
3107 case DT_NEEDED:
3108 ++needed_count;
3109 break;
3110
3111 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#else
3117 has_text_relocations = true;
3118#endif
3119 }
3120 if (d->d_un.d_val & DF_SYMBOLIC) {
3121 has_DT_SYMBOLIC = true;
3122 }
3123 break;
3124
3125 case DT_FLAGS_1:
3126 set_dt_flags_1(d->d_un.d_val);
3127
3128 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;
3170
3171 case DT_VERSYM:
3172 versym_ = reinterpret_cast(load_bias + d->d_un.d_ptr);
3173 break;
3174
3175 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;
3181
3182 case DT_VERNEED:
3183 verneed_ptr_ = load_bias + d->d_un.d_ptr;
3184 break;
3185
3186 case DT_VERNEEDNUM:
3187 verneed_cnt_ = d->d_un.d_val;
3188 break;
3189
3190 case DT_RUNPATH:
3191 // this is parsed after we have strtab initialized (see below).
3192 break;
3193
3194 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 }
3230
3231 // second pass - parse entries relying on strtab
3232 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 }
3242
3243 // Before M release linker was using basename in place of soname.
3244 // In the case when dt_soname is absent some apps stop working
3245 // because they can't find dt_needed library by soname.
3246 // This workaround should keep them working. (applies only
3247 // for apps targeting sdk version < M). Make an exception for
3248 // the main executable and linker; they do not need to have dt_soname
3249 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 UI
3257 }
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) {
3263
3264 local_group_root_ = local_group.front(); //当前是个空list
3265 if (local_group_root_ == nullptr) {
3266 local_group_root_ = this;
3267 }
3268
3269 if ((flags_ & FLAG_LINKER) == 0 && local_group_root_ == this) { //已经设置FLAG_LINKER
3270 target_sdk_version_ = get_application_target_sdk_version();
3271 }
3272
3273 VersionTracker version_tracker;
3274
3275 if (!version_tracker.init(this)) {
3276 return false;
3277 }
......
3299 if (android_relocs_ != nullptr) { //android_relocs_在prelink_image()中设置,动态节有DT_ANDROID_REL才会设置
3300 // check signature
3301 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());
3307
3308 bool relocated = false;
3309 const uint8_t* packed_relocs = android_relocs_ + 4;
3310 const size_t packed_relocs_size = android_relocs_size_ - 4;
3311
3312 relocated = relocate(
3313 version_tracker,
3314 packed_reloc_iterator(
3315 sleb128_decoder(packed_relocs, packed_relocs_size)),
3316 global_group, local_group);//调用relocate完成重定位relocs
3317
3318 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 linker
3379 // itself --- it can't make system calls yet, and will have to call protect_relro later.
3380 if (!is_linker() && !protect_relro()) {//当前是linker
3381 return false;
3382 }
3383
3384 /* 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 }
3400
3401 notify_gdb_of_load(this);//linker不支持gdb debug
3402 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);
221
222 //初始化系统属性
223 __system_properties_init(); // may use 'environ'
224
225 // 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#endif
235
236 g_linker_logger.ResetState();
237
238 // 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 }
264
265 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 }
272
273 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 }
278
279 /* 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);
282
283 // Register the main executable and the linker upfront to have
284 // gdb aware of them before loading the rest of the dependency
285 // 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);
290
291 // Extract information passed from the kernel.
292 si->phdr = reinterpret_cast(args.getauxval(AT_PHDR));
293 si->phnum = args.getauxval(AT_PHNUM);
294
295 /* Compute the value of si->base. We can't rely on the fact that
296 * the first entry is the PHDR because this will not be true
297 * 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;
310
311 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);
332
333 somain = si;
334
335 init_default_namespace(executable_path);
336
337 if (!si->prelink_image()) {
338 __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
339 }
340
341 // add somain to global group
342 si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL);
343
344 // Load ld_preloads and dependencies.
345 std::vector needed_library_name_list;
346 size_t ld_preloads_count = 0;
347
348 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 }
352
353 for_each_dt_needed(si, [&](const char* name) {
354 needed_library_name_list.push_back(name);
355 });
356 //找出依赖库,并调用find_libraries
357 const char** needed_library_names = &needed_library_name_list[0];
358 size_t needed_libraries_count = needed_library_name_list.size();
359
360 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 }
379
380 add_vdso(args);
381
382 if (!get_cfi_shadow()->InitialLinkDone(solist)) {
383 __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
384 }
385
386 si->call_pre_init_constructors();
387
388 /* 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_Backtrace
391 * 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