linker是android的加载器和连接器,同时也是其自身的加载器。

bionic/linker/arch/arm64/begin.S
29#include <private/bionic_asm.h>
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<uintptr_t*>(raw_args);
37    argc = static_cast<int>(*args);
38    argv = reinterpret_cast<char**>(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<ElfW(auxv_t)*>(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<ElfW(Ehdr)*>(linker_addr);
492  ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(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<void*>(d->d_tag), reinterpret_cast<void*>(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<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
2866        nchain_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
2867        bucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8);
2868        chain_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8 + nbucket_ * 4);
2869        break;
2870
2871      case DT_GNU_HASH:
2872        gnu_nbucket_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
2873        // skip symndx
2874        gnu_maskwords_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[2];
2875        gnu_shift2_ = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[3];
2876
2877        gnu_bloom_filter_ = reinterpret_cast<ElfW(Addr)*>(load_bias + d->d_un.d_ptr + 16);
2878        gnu_bucket_ = reinterpret_cast<uint32_t*>(gnu_bloom_filter_ + gnu_maskwords_);
2879        // amend chain for symndx = header[1]
2880        gnu_chain_ = gnu_bucket_ + gnu_nbucket_ -
2881            reinterpret_cast<uint32_t*>(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<const char*>(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<ElfW(Sym)*>(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<size_t>(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<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
2930#else
2931        plt_rel_ = reinterpret_cast<ElfW(Rel)*>(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<ElfW(Rela)*>(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<uint8_t*>(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<size_t>(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<linker_ctor_function_t>(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<linker_dtor_function_t>(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<linker_ctor_function_t*>(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<uint32_t>(d->d_un.d_val) / sizeof(ElfW(Addr));
3074        break;
3075
3076      case DT_FINI_ARRAY:
3077        fini_array_ = reinterpret_cast<linker_dtor_function_t*>(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<uint32_t>(d->d_un.d_val) / sizeof(ElfW(Addr));
3083        break;
3084
3085      case DT_PREINIT_ARRAY:
3086        preinit_array_ = reinterpret_cast<linker_ctor_function_t*>(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<uint32_t>(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<void*>(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<ElfW(Versym)*>(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<void*>(d->d_tag), reinterpret_cast<void*>(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<sleb128_decoder>(
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<char*>(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<ElfW(Phdr)*>(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<ElfW(Addr)>(si->phdr) - si->phdr[i].p_vaddr;
305      si->base = reinterpret_cast<ElfW(Addr)>(si->phdr) - si->phdr[i].p_offset;
306      break;
307    }
308  }
309  si->dynamic = nullptr;
310
311  ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(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<const char*> 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<void*>(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 linker加载相关推荐

  1. android edittext html 图片,Android EditText加载HTML内容(内容包含网络图片) -电脑资料...

    android中的Html.fromHtml可以用来加载HTML的内容,fromHtml有三个参数需要设置,第一个是要显示的html内容,第二个就是要说的重点,ImageGetter,用来处理图片加载 ...

  2. android 动态 dex,Android 动态加载dex

    首先如果仅仅是因为64K method的问题可以直接看这里DexGuard.Proguard.Multi-dex给出的解决方案. 本文主要讨论从编译层面,dex动态加载器选择层面以及安全层面讨论dex ...

  3. Android动态加载技术初探

    一.前言: 现在,已经有实力强大的公司用这个技术开发应用了,比如淘宝,大众点评,百度地图等,之所以采用这个技术,实际上,就是方便更新功能,当然,前提是新旧功能的接口一致,不然会报Not Found等错 ...

  4. Android动态加载黑科技 动态创建Activity模式

    基本信息 Author:kaedea GitHub:android-dynamical-loading 代理Activity模式的限制 还记得我们在代理Activity模式里谈到启动插件APK里的Ac ...

  5. Android动态加载进阶 代理Activity模式

    基本信息 作者:kaedea 项目:android-dynamical-loading 技术背景 简单模式中,使用ClassLoader加载外部的Dex或Apk文件,可以加载一些本地APP不存在的类, ...

  6. Android动态加载技术

    基本信息 Author:kaedea GitHub:android-dynamical-loading 我们很早开始就在Android项目中采用了动态加载技术,主要目的是为了达到让用户不用重新安装AP ...

  7. android 双 webview,Android webview加载页面

    释放双眼,带上耳机,听听看~! Android webview加载页面 private WebView webView; public void init() { webView = (WebView ...

  8. Android应用开发提高系列(4)——Android动态加载(上)——加载未安装APK中的类...

    前言 近期做换肤功能,由于换肤程度较高,受限于平台本身,实现起来较复杂,暂时搁置了该功能,但也积累了一些经验,将分两篇文章来写这部分的内容,欢迎交流! 关键字:Android动态加载 声明 欢迎转载, ...

  9. android jar 加入图片,Android动态加载外部jar包及jar包中图片等资源文件

    Android动态加载外部jar包及jar包中图片等资源文件 Android应用程序由Java开发,因此Java中许多实用的特性,在Android中也有体现.动态加载Class,也就是外部jar包,在 ...

最新文章

  1. php in_array 和 str_replace
  2. 如何获取 SAP Commerce Cloud Spartacus UI 购物车 Cart 的加载状态
  3. mysql 优化表的作用_mysql实战优化之三:表优化
  4. codeforces1485 E. Move and Swap(dp)
  5. Python数模笔记-模拟退火算法(4)旅行商问题
  6. 你没听过的IT技术解读,能秒懂的都是老司机...
  7. Visual Studio常用的快捷键
  8. core net wireless net
  9. android动态指示箭头,android – 自定义选项卡指示器(箭头像指示器)
  10. 浅析关键词密度你真的控制好了吗
  11. 国内手机市场寒风持续,华为与OV竞争将更激烈
  12. KALI-LINUX桥接模式下网络配置(学习笔记)
  13. restapi是什么意思_网上整理的对于Rest和Restful api的理解
  14. Oracle在采购部增加一名员工,ORACLEEBS采购功能点操作手册1.doc
  15. 【SHOI 2002】百事世界杯之旅 (BSOI4841)
  16. 魂斗罗(CONTRA EVOLUTION):进化革命PC版
  17. Unicode排序编码表全部
  18. [导入][香港][动作][夺帅][DVD-R/400M][国语中字][吴京、洪金宝、任达华08最新巨献]...
  19. threejs地球、星空、世界轮廓绘制、飞线、坐标涟漪 、旋转动画(上篇)
  20. java flv 转swf_java实现视频文件转换为flv(带文件缩略图)

热门文章

  1. 百度飞桨公开课笔记——OPENCV库实现图像增广
  2. 深度解析云智慧监控宝新版API监控
  3. 互联网外行创始人的团队问题和解决方案
  4. Elisp之实现代码自动高亮并跳转(十八)
  5. codeforces #309 D D. Nudist Beach(浮点数二分+bfs)
  6. 内容较长:软件测试面试题汇总
  7. 时空AI技术:利用轨迹数据全方面「监测」路网交通状态
  8. loading怎么关闭 vant_页面loading解决方案
  9. 如何才能成为一个合格的项目负责人?
  10. 一文简介 CPIM 消息格式