image001

一、Java层加载so文件

Android在Java层加载so的接口是System.loadLibrary()逐级调用的过程:

image002

image003

       System.loadLibrary()系统源码:

987    public static void loadLibrary(String libName) {
988        Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
989    }

例程 System.loadLibrary(“xxx”)     [xxx:libname名称]

Ctrl+左键Loadlibrary跟踪(如果不显示代码,添加SDK目录下\sources\android-18文件夹)

image004

Ctrl+左键 Runtime.getRuntime().loadLibrary() 中的 loadLibrary跟踪

image005

系统重载了loadLibrary()函数察看重载的 loadLibrary()

其中String libraryName参数为so文件的绝对路径

356     * Searches for and loads the given shared library using the given ClassLoader.
357     */
358    void loadLibrary(String libraryName, ClassLoader loader) {
359        if (loader != null) {
360            String filename = loader.findLibrary(libraryName);
361            if (filename == null) {
362                // It's not necessarily true that the ClassLoader used
363                // System.mapLibraryName, but the default setup does, and it's
364                // misleading to say we didn't find "libMyLibrary.so" when we
365                // actually searched for "liblibMyLibrary.so.so".
366                throw new UnsatisfiedLinkError(loader + " couldn't find \"" +
367                                               System.mapLibraryName(libraryName) + "\"");
368            }
369            String error = doLoad(filename, loader);
370            if (error != null) {
371                throw new UnsatisfiedLinkError(error);
372            }
373            return;
374        }
375
376        String filename = System.mapLibraryName(libraryName);
377        List<String> candidates = new ArrayList<String>();
378        String lastError = null;
379        for (String directory : mLibPaths) {
380            String candidate = directory + filename;
381            candidates.add(candidate);
382
383            if (IoUtils.canOpenReadOnly(candidate)) {
384                String error = doLoad(candidate, loader);
385                if (error == null) {
386                    return; // We successfully loaded the library. Job done.
387                }
388                lastError = error;
389            }
390        }
391
392        if (lastError != null) {
393            throw new UnsatisfiedLinkError(lastError);
394        }
395        throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
396    }
loadLibrary()

 

其中doLoad()为加载函数,源码:

400    private String doLoad(String name, ClassLoader loader) {
401        // Android apps are forked from the zygote, so they can't have a custom LD_LIBRARY_PATH,
402        // which means that by default an app's shared library directory isn't on LD_LIBRARY_PATH.
403
404        // The PathClassLoader set up by frameworks/base knows the appropriate path, so we can load
405        // libraries with no dependencies just fine, but an app that has multiple libraries that
406        // depend on each other needed to load them in most-dependent-first order.
407
408        // We added API to Android's dynamic linker so we can update the library path used for
409        // the currently-running process. We pull the desired path out of the ClassLoader here
410        // and pass it to nativeLoad so that it can call the private dynamic linker API.
411
412        // We didn't just change frameworks/base to update the LD_LIBRARY_PATH once at the
413        // beginning because multiple apks can run in the same process and third party code can
414        // use its own BaseDexClassLoader.
415
416        // We didn't just add a dlopen_with_custom_LD_LIBRARY_PATH call because we wanted any
417        // dlopen(3) calls made from a .so's JNI_OnLoad to work too.
418
419        // So, find out what the native library search path is for the ClassLoader in question...
420        String ldLibraryPath = null;
421        if (loader != null && loader instanceof BaseDexClassLoader) {
422            ldLibraryPath = ((BaseDexClassLoader) loader).getLdLibraryPath();
423        }
424        // nativeLoad should be synchronized so there's only one LD_LIBRARY_PATH in use regardless
425        // of how many ClassLoaders are in the system, but dalvik doesn't support synchronized
426        // internal natives.
427        synchronized (this) {
428            return nativeLoad(name, loader, ldLibraryPath);
429        }
430    }
doLoad()

 

       nativeLoad()用来加载name指向的so文件,nativeLoad()是Runtime类的一个native函数,在native层对应Runtime_nativeLoad()。

至此Java层的so文件加载跟踪完。根据nativeLoad进入Native层跟踪

二、nativeload开始 Native层的调用

       Nativeload函数分析图

image006

分三个阶段:

1. so文件加载

在java_lang_Runtime.cc文件中

image007

可知Java层的nativeLoad对应Native层的Runtime_nativeLoad()

46static jstring Runtime_nativeLoad(JNIEnv* env, jclass, jstring javaFilename, jobject javaLoader, jstring javaLdLibraryPath) {
47  ScopedUtfChars filename(env, javaFilename);
48  if (filename.c_str() == NULL) {
49    return NULL;
50  }
51
52  if (javaLdLibraryPath != NULL) {
53    ScopedUtfChars ldLibraryPath(env, javaLdLibraryPath);
54    if (ldLibraryPath.c_str() == NULL) {
55      return NULL;
56    }
57    void* sym = dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH");
58    if (sym != NULL) {
59      typedef void (*Fn)(const char*);
60      Fn android_update_LD_LIBRARY_PATH = reinterpret_cast<Fn>(sym);
61      (*android_update_LD_LIBRARY_PATH)(ldLibraryPath.c_str());
62    } else {
63      LOG(ERROR) << "android_update_LD_LIBRARY_PATH not found; .so dependencies will not work!";
64    }
65  }
66
67  std::string detail;
68  {
69    ScopedObjectAccess soa(env);
70    StackHandleScope<1> hs(soa.Self());
71    Handle<mirror::ClassLoader> classLoader(
72        hs.NewHandle(soa.Decode<mirror::ClassLoader*>(javaLoader)));
73    JavaVMExt* vm = Runtime::Current()->GetJavaVM();
        // 调用JavaVMExt类的LoadNativeLibrary()加载so文件,detail用于存储加载过程中的Log信息
74    bool success = vm->LoadNativeLibrary(filename.c_str(), classLoader, &detail);
75    if (success) {
76      return nullptr;
77    }
78  }
79
80  // Don't let a pending exception from JNI_OnLoad cause a CheckJNI issue with NewStringUTF.
81  env->ExceptionClear();
82  return env->NewStringUTF(detail.c_str());
83}
Runtime_nativeLoad()

根据代码加载so的分析,查看LoadNativeLibrary()源代码

3225bool JavaVMExt::LoadNativeLibrary(const std::string& path,
3226                                  Handle<mirror::ClassLoader> class_loader,
3227                                  std::string* detail) {
3228  detail->clear();
3229
3230  // 是否加载过该so文件,如果是就不需要再次加载
3234  SharedLibrary* library;
3235  Thread* self = Thread::Current();
3236  {
3237    // TODO: move the locking (and more of this logic) into Libraries.
3238    MutexLock mu(self, libraries_lock);
3239    library = libraries->Get(path);
3240  }
3241  if (library != nullptr) {
3242    if (library->GetClassLoader() != class_loader.Get()) {
3243      // The library will be associated with class_loader. The JNI
3244      // spec says we can't load the same library into more than one
3245      // class loader.
3246      StringAppendF(detail, "Shared library \"%s\" already opened by "
3247          "ClassLoader %p; can't open in ClassLoader %p",
3248          path.c_str(), library->GetClassLoader(), class_loader.Get());
3249      LOG(WARNING) << detail;
3250      return false;
3251    }
3252    VLOG(jni) << "[Shared library \"" << path << "\" already loaded in "
3253              << "ClassLoader " << class_loader.Get() << "]";
3254    if (!library->CheckOnLoadResult()) {
3255      StringAppendF(detail, "JNI_OnLoad failed on a previous attempt "
3256          "to load \"%s\"", path.c_str());
3257      return false;
3258    }
3259    return true;
3260  }


3274  // 没有加载过该so,需要加载
3275  self->TransitionFromRunnableToSuspended(kWaitingForJniOnLoad);
3276  const char* path_str = path.empty() ? nullptr : path.c_str();
      // 调用dlopen()加载so文件
3277  void* handle = dlopen(path_str, RTLD_LAZY);
3278  bool needs_native_bridge = false;
3279  if (handle == nullptr) {
3280    if (android::NativeBridgeIsSupported(path_str)) {
3281      handle = android::NativeBridgeLoadLibrary(path_str, RTLD_LAZY);
3282      needs_native_bridge = true;
3283    }
3284  }
3285  self->TransitionFromSuspendedToRunnable();
3286
3287  VLOG(jni) << "[Call to dlopen(\"" << path << "\", RTLD_LAZY) returned " << handle << "]";
3288
3289  if (handle == nullptr) {
3290    *detail = dlerror();
3291    LOG(ERROR) << "dlopen(\"" << path << "\", RTLD_LAZY) failed: " << *detail;
3292    return false;
3293  }
3294
3295  // Create a new entry.
3296  // TODO: move the locking (and more of this logic) into Libraries.
3297  bool created_library = false;
3298  {
3299    MutexLock mu(self, libraries_lock);
3300    library = libraries->Get(path);
3301    if (library == nullptr) {  // 加载完后,新建SharedLibrary对象,并将path存入libraries
3302      library = new SharedLibrary(path, handle, class_loader.Get());
3303      libraries->Put(path, library);
3304      created_library = true;
3305    }
3306  }
3307  if (!created_library) {
3308    LOG(INFO) << "WOW: we lost a race to add shared library: "
3309        << "\"" << path << "\" ClassLoader=" << class_loader.Get();
3310    return library->CheckOnLoadResult();
3311  }
3312
3313  VLOG(jni) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader.Get()
3314      << "]";
3315
3316  bool was_successful = false;
3317  void* sym = nullptr;
3318  if (UNLIKELY(needs_native_bridge)) {
3319    library->SetNeedsNativeBridge();
3320    sym = library->FindSymbolWithNativeBridge("JNI_OnLoad", nullptr);
3321  } else {
3322    sym = dlsym(handle, "JNI_OnLoad");// 找到JNI_OnLoad()
3323  }
3324
3325  if (sym == nullptr) {
3326    VLOG(jni) << "[No JNI_OnLoad found in \"" << path << "\"]";
3327    was_successful = true;
3328  } else {
3329    // Call JNI_OnLoad.  We have to override the current class
3330    // loader, which will always be "null" since the stuff at the
3331    // top of the stack is around Runtime.loadLibrary().  (See
3332    // the comments in the JNI FindClass function.)
3333    typedef int (*JNI_OnLoadFn)(JavaVM*, void*);
3334    JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym);
3335    StackHandleScope<1> hs(self);
3336    Handle<mirror::ClassLoader> old_class_loader(hs.NewHandle(self->GetClassLoaderOverride()));
3337    self->SetClassLoaderOverride(class_loader.Get());
3338
3339    int version = 0;
3340    {
3341      ScopedThreadStateChange tsc(self, kNative);
3342      VLOG(jni) << "[Calling JNI_OnLoad in \"" << path << "\"]";
          // 调用JNI_Onload()
3343      version = (*jni_on_load)(this, nullptr);
3344    }
3345
3346    if (runtime->GetTargetSdkVersion() != 0 && runtime->GetTargetSdkVersion() <= 21) {
3347      fault_manager.EnsureArtActionInFrontOfSignalChain();
3348    }
3349    self->SetClassLoaderOverride(old_class_loader.Get());
3350
3351    if (version == JNI_ERR) {
3352      StringAppendF(detail, "JNI_ERR returned from JNI_OnLoad in \"%s\"", path.c_str());
3353    } else if (IsBadJniVersion(version)) {
3354      StringAppendF(detail, "Bad JNI version returned from JNI_OnLoad in \"%s\": %d",
3355                    path.c_str(), version);
3356      // It's unwise to call dlclose() here, but we can mark it
3357      // as bad and ensure that future load attempts will fail.
3358      // We don't know how far JNI_OnLoad got, so there could
3359      // be some partially-initialized stuff accessible through
3360      // newly-registered native method calls.  We could try to
3361      // unregister them, but that doesn't seem worthwhile.
3362    } else {
3363      was_successful = true;
3364    }
3365    VLOG(jni) << "[Returned " << (was_successful ? "successfully" : "failure")
3366              << " from JNI_OnLoad in \"" << path << "\"]";
3367  }
3368
3369  library->SetResult(was_successful);
3370  return was_successful;
3371}
LoadNativeLibrary()

LoadNativeLibrary()函数执行过程:

  1. 判断so文件是否已经加载,若已经加载判断与class_Loader是否重复

  2. 如果so文件没有被加载,dlopen()打开so文件加载

  3. 调用dlsym() 加载 “JNI_OnLoad”函数地址

  4. 调用JNI_OnLoad()函数

  至此Native层so文件加载完成,根据分析结果追踪dlopen()

      dlopen()源码: /bionic/linker/dlfcn.cpp

82void* dlopen(const char* filename, int flags) {
83  return dlopen_ext(filename, flags, nullptr);
84}

跟踪dlopen_ext()

68static void* dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) {
69  ScopedPthreadMutexLocker locker(&g_dl_mutex);
70  soinfo* result = do_dlopen(filename, flags, extinfo);
71  if (result == nullptr) {
72    __bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
73    return nullptr;
74  }
75  return result;
76}
dlopen_ext()

根据代码filename指向的 .so文件,返回值为soinfo*,指向so文件指针,所以dlopen_ext()返回的指针指向 soinfo对象

跟踪 do_dlopen():/bionic/linker/linker.cpp

1041soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo) {

1042  if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NOLOAD)) != 0) {
1043    DL_ERR("invalid flags to dlopen: %x", flags);
1044    return nullptr;
1045  }
1046  if (extinfo != nullptr) {
1047    if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) {
1048      DL_ERR("invalid extended flags to android_dlopen_ext: 0x%" PRIx64, extinfo->flags);
1049      return nullptr;
1050    }
1051    if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 &&
1052        (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
1053      DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags);
1054      return nullptr;
1055    }
1056  }
       // extinfo为null

1057  protect_data(PROT_READ | PROT_WRITE);
1058  soinfo* si = find_library(name, flags, extinfo);
1059  if (si != nullptr) {
        // 初始化
1060    si->CallConstructors();
1061  }
1062  protect_data(PROT_READ);
1063  return si;
1064}
do_dlopen()

find_library()得到soinfo对象,分析源码需要跟踪find_library()和CallConstructors(),根据代码顺序继续分析

  do_dlopen()总共两部分

  do_dlopen()的第一部分:

    find_library():

968static soinfo* find_library(const char* name, int dlflags, const android_dlextinfo* extinfo) {

969  if (name == nullptr) {
970    somain->ref_count++;
971    return somain;
972  }
973
974  soinfo* si;
975
976  if (!find_libraries(&name, 1, &si, nullptr, 0, dlflags, extinfo)) {
977    return nullptr;
978  }
979
980  return si;
981}
find_library()

根据代码跟踪 find_libraries()的参数:/bionic/linker/linker.cpp

    find_libraries()参数:

    const char* const library_names[], //so文件名的数组

    size_t library_names_size, //

    soinfo* soinfos[], //指向soinfos数组的指针,将library_names中so的结果存入soinfos数组中

    soinfo* ld_preloads[], //ld_preloads = NULL

    size_t ld_preloads_size, //ld_preloads_size = 0

    int dlflags,

    const android_dlextinfo* extinfo //extinfo = NULL

896static bool find_libraries(const char* const library_names[], size_t library_names_size, soinfo* soinfos[],
897    soinfo* ld_preloads[], size_t ld_preloads_size, int dlflags, const android_dlextinfo* extinfo) {
898    // Step 1: prepare.
               // a.宽度优先搜索的栈,父节点的依赖库为其子节点,根节点是代加载的.so文件    
899  LoadTaskList load_tasks;
               // b.初始化
900  for (size_t i = 0; i < library_names_size; ++i) {
901    const char* name = library_names[i];
902    load_tasks.push_back(LoadTask::create(name, nullptr));
903  }
904
905  
                // c.该so文件和其它所有依赖库的列表
907  SoinfoLinkedList found_libs;
908  size_t soinfos_size = 0;
909
910  auto failure_guard = make_scope_guard([&]() {
911    // Housekeeping
912    load_tasks.for_each([] (LoadTask* t) {
913      LoadTask::deleter(t);
914    });
915
916    for (size_t i = 0; i<soinfos_size; ++i) {
917      soinfo_unload(soinfos[i]);
918    }
919  });
920
921  // Step 2: 
        //  优先搜索加载该.so文件和其依赖库

922  for (LoadTask::unique_ptr task(load_tasks.pop_front()); task.get() != nullptr; task.reset(load_tasks.pop_front())) {
               // 加载so文件
923    soinfo* si = find_library_internal(load_tasks, task->get_name(), dlflags, extinfo);// extinfo == null
924    if (si == nullptr) {
925      return false;
926    }
927     // needed_by依赖于si
928    soinfo* needed_by = task->get_needed_by();
929
930    if (is_recursive(si, needed_by)) {
        // 判断是否有递归依赖关系
931      return false;
932    }
933     // si引用计数
934    si->ref_count++;        
935    if (needed_by != nullptr) {
936      needed_by->add_child(si);
937    }
938    found_libs.push_front(si);
939
940    // When ld_preloads is not null first
941    // ld_preloads_size libs are in fact ld_preloads.
942    if (ld_preloads != nullptr && soinfos_size < ld_preloads_size) {
943      ld_preloads[soinfos_size] = si;
944    }
945
946    if (soinfos_size<library_names_size) {
        // 只将library_names中对应的soinfos存入soinfos
947      soinfos[soinfos_size++] = si;
948    }
949  }
950
951     // Step 3: 
        // 链接加载库
952  soinfo* si;
953  while ((si = found_libs.pop_front()) != nullptr) {
954    if ((si->flags & FLAG_LINKED) == 0) {
          // 如果si没有链接,对si进行链接
955      if (!si->LinkImage(extinfo)) {
           // extinfo == null
956        return false;
957      }
958      si->flags |= FLAG_LINKED;
959    }
960  }
961
962  // All is well - found_libs and load_tasks are empty at this point
963  // and all libs are successfully linked.
964  failure_guard.disable();
965  return true;
966}
find_libraries()

find_libraries()对library_names[ ]中的so文件加载到内存,进行链接

  find_libraries()分三步骤:

    第一步:初始化:

      a) 加载的so可能以来其他库,采用优先搜索依次加载方式。搜索树中父节点的依赖库为其子节点。根节点是so文件

      b) 初始化

      c) found_libs是so文件和其依赖库的列表

    第二步:宽度优先搜索加载so:

      d) find_library_internal()将so载入内存

    第三步:对加载的so进行链接:

      根据上述分析,查看

      find_library_internal()函数源码,用于加载so /bionic/linker/linker.cpp

865static soinfo* find_library_internal(LoadTaskList& load_tasks, const char* name, int dlflags, const android_dlextinfo* extinfo) {// extinfo==null
866   // 检查是否被加载过
867  soinfo* si = find_loaded_library_by_name(name);
868
869  // 加载过直接返回si,否则调用load_library
871  if (si == nullptr) {
872    TRACE("[ '%s' has not been found by name.  Trying harder...]", name);
873    si = load_library(load_tasks, name, dlflags, extinfo);
874  }
875
876  return si;
877}
find_library_internal()

跟进查看load_library()源码:

777static soinfo* load_library(LoadTaskList& load_tasks, const char* name, int dlflags, const android_dlextinfo* extinfo) {// extinfo == null

778  int fd = -1; // so文件描述符
779  off64_t file_offset = 0;
780  ScopedFd file_guard(-1);
781   // 第一部分:
782  if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
783    fd = extinfo->library_fd;
784    if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
785      file_offset = extinfo->library_fd_offset;
786    }
787  } else {
788    // 打开so文件
789    fd = open_library(name);
790    if (fd == -1) {
791      DL_ERR("library \"%s\" not found", name);
792      return nullptr;
793    }
794
795    file_guard.reset(fd);
796  }
797     // 文件偏移必须是PAGE_SIZE的整数倍,这里file_offset == 0
798  if ((file_offset % PAGE_SIZE) != 0) {
799    DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset);
800    return nullptr;
801  }
802
803  struct stat file_stat;
804  if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) {
        // 获取so文件的状态
805    DL_ERR("unable to stat file for the library \"%s\": %s", name, strerror(errno));
806    return nullptr;
807  }
808
809  // 因为Linux下可以生成文件的链接文件,这里检查so文件是否以不同名字加载
811  for (soinfo* si = solist; si != nullptr; si = si->next) {
812    if (si->get_st_dev() != 0 &&
813        si->get_st_ino() != 0 &&
814        si->get_st_dev() == file_stat.st_dev &&
815        si->get_st_ino() == file_stat.st_ino &&
816        si->get_file_offset() == file_offset) {
817      TRACE("library \"%s\" is already loaded under different name/path \"%s\" - will return existing soinfo", name, si->name);
818      return si;
819    }
820  }
821
822  if ((dlflags & RTLD_NOLOAD) != 0) {
823    DL_ERR("library \"%s\" wasn't loaded and RTLD_NOLOAD prevented it", name);
824    return nullptr;
825  }
826   // 第二部分:
827  // 读取ELF头,加载段     file_offset == 0
828  ElfReader elf_reader(name, fd, file_offset);
829  if (!elf_reader.Load(extinfo)) {
830    return nullptr;
831  }
832   // 第三部分
      //  为soinfo分配空间
833  soinfo* si = soinfo_alloc(SEARCH_NAME(name), &file_stat, file_offset);
834  if (si == nullptr) {
835    return nullptr;
836  }
        // 加载 so 文件时,mmap 得到的空间的首地址
837  si->base = elf_reader.load_start();
        // ReserveAddressSpace 中开辟的内存空间的大小
838  si->size = elf_reader.load_size();
        // 加载段时的基址,load_bias+p_vaddr 为段的实际内存地址
839  si->load_bias = elf_reader.load_bias();
        // program header 的个数
840  si->phnum = elf_reader.phdr_count();
        // program header table 在内存中的起始地址
841  si->phdr = elf_reader.loaded_phdr();
842
843  if (!si->PrelinkImage()) {
        // 解析.dynmaic section
844    soinfo_free(si);
845    return nullptr;
846  }
847     // 将该so文件依赖的库添加到待加载队列中
848  for_each_dt_needed(si, [&] (const char* name) {
        // si依赖于name的库
849    load_tasks.push_back(LoadTask::create(name, si));
850  });
851
852  return si;
853}
854
855static soinfo *find_loaded_library_by_name(const char* name) {
856  const char* search_name = SEARCH_NAME(name);
857  for (soinfo* si = solist; si != nullptr; si = si->next) {
858    if (!strcmp(search_name, si->name)) {
859      return si;
860    }
861  }
862  return nullptr;
863}
load_library()
        load_library()分三个部分:

        第一部分:打开.so文件,并判断是否已经加载

              内存页的大小:PAGE_SIZE为4096

        第二部分:加载.so文件的可加载段

              用ElfReader类解析ELF头

根据源码Load()的源码:

135bool ElfReader::Load(const android_dlextinfo* extinfo) {
             // ReadElfHeader()读取ELF头结果给ElfReader的Elf32_Ehdr header_,成员变量
136  return ReadElfHeader() &&
137         VerifyElfHeader() &&
138         ReadProgramHeader() &&
139         ReserveAddressSpace(extinfo) &&
140         LoadSegments() &&
141         FindPhdr();
142}
Load()

根据ElfReader源码,分析return的返回值的函数源码

 VerifyElfHeader():检查ELF头某些字段是否合法,根据源码,ELF头中,byte_ident[16]字段的后10位没有进行校验

159bool ElfReader::VerifyElfHeader() {

        // 检查magicNum 与 \177ELF
160  if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) {
161    DL_ERR("\"%s\" has bad ELF magic", name_);
162    return false;
163  }
164
165  // 检测ELF为数与目前操作系统的为数是否相同(32位或64位)
167  int elf_class = header_.e_ident[EI_CLASS];
168#if defined(__LP64__)
169  if (elf_class != ELFCLASS64) {
170    if (elf_class == ELFCLASS32) {
171      DL_ERR("\"%s\" is 32-bit instead of 64-bit", name_);
172    } else {
173      DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class);
174    }
175    return false;
176  }
177#else
178  if (elf_class != ELFCLASS32) {
179    if (elf_class == ELFCLASS64) {
180      DL_ERR("\"%s\" is 64-bit instead of 32-bit", name_);
181    } else {
182      DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class);
183    }
184    return false;
185  }
186#endif
187   // 该so文件必须是小端存储
188  if (header_.e_ident[EI_DATA] != ELFDATA2LSB) {
        // EI_DATA=5,ELFDATA2LSB=1
189    DL_ERR("\"%s\" not little-endian: %d", name_, header_.e_ident[EI_DATA]);
190    return false;
191  }
192   // 该so文件必须共享目标文件
193  if (header_.e_type != ET_DYN) {
        // ET_DYN=3
194    DL_ERR("\"%s\" has unexpected e_type: %d", name_, header_.e_type);
195    return false;
196  }
197   // 版本号必须为1
198  if (header_.e_version != EV_CURRENT) {
199    DL_ERR("\"%s\" has unexpected e_version: %d", name_, header_.e_version);
200    return false;
201  }
202   // 如果目标平台是arm,ELF_TARG_MACH=40
203  if (header_.e_machine != ELF_TARG_MACH) {
204    DL_ERR("\"%s\" has unexpected e_machine: %d", name_, header_.e_machine);
205    return false;
206  }
207
208  return true;
209}
VerifyElfHeader()

 ReadProgramHeader()将 program header table从.so 文件通过 mmap64 映射到只读私有匿名内存

213bool ElfReader::ReadProgramHeader() {
214  phdr_num_ = header_.e_phnum;// phdr的数目
215
216  // Like the kernel, we only accept program header tables that
217  // are smaller than 64KiB.
218  if (phdr_num_ < 1 || phdr_num_ > 65536/sizeof(ElfW(Phdr))) {
219    DL_ERR("\"%s\" has invalid e_phnum: %zd", name_, phdr_num_);
220    return false;
221  }
222
223  ElfW(Addr) page_min = PAGE_START(header_.e_phoff);// 0
224  ElfW(Addr) page_max = PAGE_END(header_.e_phoff + (phdr_num_ * sizeof(ElfW(Phdr))));
      // pht在页中的偏移
225  ElfW(Addr) page_offset = PAGE_OFFSET(header_.e_phoff);
226   // pht需要的映射内存大小
227  phdr_size_ = page_max - page_min;
228
229  void* mmap_result = mmap64(nullptr, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, file_offset_ + page_min);
230  if (mmap_result == MAP_FAILED) {
231    DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
232    return false;
233  }
234
235  phdr_mmap_ = mmap_result;
236  phdr_table_ = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(mmap_result) + page_offset);
237  return true;
238}
ReadProgramHeader()

 ReserveAddressSpace()通过 mmap 创建足够大的匿名内存空间, 以便能够容纳所有可以加载的段

292bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) {

293  ElfW(Addr) min_vaddr;
      // 加载所有段所需要的内存空间
294  load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr);
295  if (load_size_ == 0) {
296    DL_ERR("\"%s\" has no loadable segments", name_);
297    return false;
298  }
299
300  uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
301  void* start;
302  size_t reserved_size = 0;
303  bool reserved_hint = true;
304
305  if (extinfo != nullptr) {
306    if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
307      reserved_size = extinfo->reserved_size;
308      reserved_hint = false;
309    } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
310      reserved_size = extinfo->reserved_size;
311    }
312  }
313
314  if (load_size_ > reserved_size) {
315    if (!reserved_hint) {
316      DL_ERR("reserved address space %zd smaller than %zd bytes needed for \"%s\"",
317             reserved_size - load_size_, load_size_, name_);
318      return false;
319    }
320    int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
        // 分配空间
321    start = mmap(addr, load_size_, PROT_NONE, mmap_flags, -1, 0);
322    if (start == MAP_FAILED) {
323      DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_);
324      return false;
325    }
326  } else {
327    start = extinfo->reserved_addr;
328  }
329   // 分配匿名内存空间首地址
330  load_start_ = start;
331  load_bias_ = reinterpret_cast<uint8_t*>(start) - addr;
332  return true;
333}
ReserveAddressSpace()

 LoadSegments()函数

335bool ElfReader::LoadSegments() {

336  for (size_t i = 0; i < phdr_num_; ++i) {
337    const ElfW(Phdr)* phdr = &phdr_table_[i];
338     // 遍历 program header table 找到可加载段
339    if (phdr->p_type != PT_LOAD) {
340      continue;
341    }
342
343    // Segment addresses in memory.
        // 段在内存中的起始地址
344    ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
        // 段在内存中的结束地址
345    ElfW(Addr) seg_end   = seg_start + phdr->p_memsz;
346     // seg_start 所在页的起始地址
347    ElfW(Addr) seg_page_start = PAGE_START(seg_start);
        // seg_end 所在页的下一页的起始地址
348    ElfW(Addr) seg_page_end   = PAGE_END(seg_end);
349     // 文件中段的结束位置在内存中的地址
350    ElfW(Addr) seg_file_end   = seg_start + phdr->p_filesz;
351
352    // File offsets.
        // 段在文件中的偏移首地址
353    ElfW(Addr) file_start = phdr->p_offset;
        // 段在文件中的结束地址
354    ElfW(Addr) file_end   = file_start + phdr->p_filesz;
355     // file_start 所在页的起始地址
356    ElfW(Addr) file_page_start = PAGE_START(file_start);
        // 需要映射的文件长度,file_length>=phdr->p_filesz
357    ElfW(Addr) file_length = file_end - file_page_start;
358
359    if (file_length != 0) {
        // 将文件中的段映射到内存
360      void* seg_addr = mmap64(reinterpret_cast<void*>(seg_page_start),
361                            file_length,
362                            PFLAGS_TO_PROT(phdr->p_flags),
363                            MAP_FIXED|MAP_PRIVATE,
364                            fd_,
365                            file_offset_ + file_page_start);
366      if (seg_addr == MAP_FAILED) {
367        DL_ERR("couldn't map \"%s\" segment %zd: %s", name_, i, strerror(errno));
368        return false;
369      }
370    }
371
372    // 将最后一页中,不是段内容的数据置 0 
374    if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) {
375      memset(reinterpret_cast<void*>(seg_file_end), 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end));
376    }
377
378    seg_file_end = PAGE_END(seg_file_end);
379
380    // seg_file_end is now the first page address after the file
381    // content. If seg_end is larger, we need to zero anything
382    // between them. This is done by using a private anonymous
383    // map for all extra pages.
384    if (seg_page_end > seg_file_end) {
385      void* zeromap = mmap(reinterpret_cast<void*>(seg_file_end),
386                           seg_page_end - seg_file_end,
387                           PFLAGS_TO_PROT(phdr->p_flags),
388                           MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,
389                           -1,
390                           0);
         // 额外的内容置 0
391      if (zeromap == MAP_FAILED) {
392        DL_ERR("couldn't zero fill \"%s\" gap: %s", name_, strerror(errno));
393        return false;
394      }
395    }
396  }
397  return true;
398}
399
LoadSegments()

加载完.so 文件后,Load()继续调用 FindPhdr()函数检查可加载段中是否包含 program header table。

728bool ElfReader::FindPhdr() {
729  const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
730
731  // 首先检查是否有类型是 PT_PHDR 的段,即 program header table
732  for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
        // load_bias_ + phdr->p_vaddr 是 phdr 在内存中的起始地址
733    if (phdr->p_type == PT_PHDR) {
          // 检查是否在内存中  
734      return CheckPhdr(load_bias_ + phdr->p_vaddr);
735    }
736  }
737
738  // 检查第一个可加载段。如果它在文件中的偏移是 0,那么该段以 ELF 头
739  // 开始,通过 ELF 头能计算 program header table 的地址
741  for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
742    if (phdr->p_type == PT_LOAD) {
743      if (phdr->p_offset == 0) {
744        ElfW(Addr)  elf_addr = load_bias_ + phdr->p_vaddr;
745        const ElfW(Ehdr)* ehdr = reinterpret_cast<const ElfW(Ehdr)*>(elf_addr);
           // ehdr->e_phoff 是 pht 在文件中的偏移
746        ElfW(Addr)  offset = ehdr->e_phoff;
           // 检查是否在内存中
747        return CheckPhdr((ElfW(Addr))ehdr + offset);
748      }
749      break;
750    }
751  }
752
753  DL_ERR("can't find loaded phdr for \"%s\"", name_);
754  return false;
755}
               FindPhdr()两种方式确定program header table是否在内存,调用CheckPhdr()实现
760bool ElfReader::CheckPhdr(ElfW(Addr) loaded) {
761  const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
    // loaded_end 是 pht 在内存中的结束地址
762  ElfW(Addr) loaded_end = loaded + (phdr_num_ * sizeof(ElfW(Phdr)));
763  for (ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
764    if (phdr->p_type != PT_LOAD) {
765      continue;
766    }
767    ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
768    ElfW(Addr) seg_end = phdr->p_filesz + seg_start;
769    if (seg_start <= loaded && loaded_end <= seg_end) {
        // 遍历每一个可加载段,检查 pht 的地址范围是否在可加载段中
770      loaded_phdr_ = reinterpret_cast<const ElfW(Phdr)*>(loaded);
771      return true;
772    }
773  }
774  DL_ERR("\"%s\" loaded phdr %p not in loadable segment", name_, reinterpret_cast<void*>(loaded));
775  return false;
776}
FindPhdr()
        ElfReader.Load()加载so的过程:
           1. ReadElfHeader():从.so 文件中读取 ELF 头;
           2.  VerifyElfHeader():校验 ELF 头;
           3.  ReadProgramHeader():将.so 文件的 program header table 映射到内存;
           4.  ReserveAddressSpace():开辟匿名内存空间;
           5.  LoadSegments():将可加载段加载到 ReserveAddressSpace 开辟的空间中;
           6.  FindPhdr():校验 program header table 是否在内存中。
 

        第三部分:创建soinfo对象,解析.dynmaic section,并将该.so文件的依赖库添加到待加载的队列中。

                                       Load_library()中PrelinkImage()解析so文件的dynamic setction

                                         dynamic section的定义

1631// Dynamic table entry for ELF64.
1632struct Elf64_Dyn
1633{
1634  Elf64_Sxword d_tag;           // Type of dynamic table entry.
1635  union
1636  {
1637      Elf64_Xword d_val;        // Integer value of entry.
1638      Elf64_Addr  d_ptr;        // Pointer value of entry.
1639  } d_un;
1640};
 dynamic section

                                   PrelinkImage()解析的源码

1858bool soinfo::PrelinkImage() {
1859  /* Extract dynamic section */
1860  ElfW(Word) dynamic_flags = 0;
      // 根据 program header table 找到.dynamic section
1861  phdr_table_get_dynamic_section(phdr, phnum, load_bias, &dynamic, &dynamic_flags);
1862
1863  /* We can't log anything until the linker is relocated */
1864  bool relocating_linker = (flags & FLAG_LINKER) != 0;
1865  if (!relocating_linker) {
1866    INFO("[ linking %s ]", name);
1867    DEBUG("si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags);
1868  }
1869
1870  if (dynamic == nullptr) {
1871    if (!relocating_linker) {
1872      DL_ERR("missing PT_DYNAMIC in \"%s\"", name);
1873    }
1874    return false;
1875  } else {
1876    if (!relocating_linker) {
1877      DEBUG("dynamic = %p", dynamic);
1878    }
1879  }
1880    // 找到.ARM.exidx sectioin 在内存中的地址
1881#if defined(__arm__)
1882  (void) phdr_table_get_arm_exidx(phdr, phnum, load_bias,
1883                                  &ARM_exidx, &ARM_exidx_count);
1884#endif
1885
1886  // 该so依赖库的个数
1887  uint32_t needed_count = 0;
        // 遍历.dynamic
1888  for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
1889    DEBUG("d = %p, d[0](tag) = %p d[1](val) = %p",
1890          d, reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
1891    switch (d->d_tag) {
1892      case DT_SONAME:
1893        // TODO: glibc dynamic linker uses this name for
1894        // initial library lookup; consider doing the same here.
1895        break;
1896       // hash 表相关信息
1897      case DT_HASH:  
1898        nbucket = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
1899        nchain = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
1900        bucket = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8);
1901        chain = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr + 8 + nbucket * 4);
1902        break;
1903      // 字符串表的偏移,与.dynstr section 对应,d_un.d_ptr 与 s_addr 相等
1904      case DT_STRTAB:  
1905        strtab = reinterpret_cast<const char*>(load_bias + d->d_un.d_ptr);
1906        break;
1907      // 字符串表的大小(字节)
1908      case DT_STRSZ:
1909        strtab_size = d->d_un.d_val;
1910        break;
1911      // 符号表的偏移
1912      case DT_SYMTAB:
1913        symtab = reinterpret_cast<ElfW(Sym)*>(load_bias + d->d_un.d_ptr);
1914        break;
1915     // 符号表项的大小(字节)
1916      case DT_SYMENT:
1917        if (d->d_un.d_val != sizeof(ElfW(Sym))) {
1918          DL_ERR("invalid DT_SYMENT: %zd", static_cast<size_t>(d->d_un.d_val));
1919          return false;
1920        }
1921        break;
1922
1923      case DT_PLTREL:
1924#if defined(USE_RELA)
1925        if (d->d_un.d_val != DT_RELA) {
1926          DL_ERR("unsupported DT_PLTREL in \"%s\"; expected DT_RELA", name);
1927          return false;
1928        }
1929#else
1930        if (d->d_un.d_val != DT_REL) {
1931          DL_ERR("unsupported DT_PLTREL in \"%s\"; expected DT_REL", name);
1932          return false;
1933        }
1934#endif
1935        break;
1936      // 与过程链接表相关的重定位表的偏移,与.rel.plt section 对应
1937      case DT_JMPREL:
1938#if defined(USE_RELA)
1939        plt_rela = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
1940#else
1941        plt_rel = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
1942#endif
1943        break;
1944
1945      case DT_PLTRELSZ:
1946#if defined(USE_RELA)
1947        plt_rela_count = d->d_un.d_val / sizeof(ElfW(Rela));
1948#else
1949        plt_rel_count = d->d_un.d_val / sizeof(ElfW(Rel));
1950#endif
1951        break;
1952      // 与过程链接表相关的重定位表的大小(字节)
1953      case DT_PLTGOT:
1954#if defined(__mips__)
1955        // Used by mips and mips64.
1956        plt_got = reinterpret_cast<ElfW(Addr)**>(load_bias + d->d_un.d_ptr);
1957#endif
1958        // Ignore for other platforms... (because RTLD_LAZY is not supported)
1959        break;
1960
1961      case DT_DEBUG:
1962        // Set the DT_DEBUG entry to the address of _r_debug for GDB
1963        // if the dynamic table is writable
1964// FIXME: not working currently for N64
1965// The flags for the LOAD and DYNAMIC program headers do not agree.
1966// The LOAD section containing the dynamic table has been mapped as
1967// read-only, but the DYNAMIC header claims it is writable.
1968#if !(defined(__mips__) && defined(__LP64__))
1969        if ((dynamic_flags & PF_W) != 0) {
1970          d->d_un.d_val = reinterpret_cast<uintptr_t>(&_r_debug);
1971        }
1972        break;
1973#endif
1974#if defined(USE_RELA)
1975      case DT_RELA:
1976        rela = reinterpret_cast<ElfW(Rela)*>(load_bias + d->d_un.d_ptr);
1977        break;
1978
1979      case DT_RELASZ:
1980        rela_count = d->d_un.d_val / sizeof(ElfW(Rela));
1981        break;
1982
1983      case DT_RELAENT:
1984        if (d->d_un.d_val != sizeof(ElfW(Rela))) {
1985          DL_ERR("invalid DT_RELAENT: %zd", static_cast<size_t>(d->d_un.d_val));
1986          return false;
1987        }
1988        break;
1989
1990      // ignored (see DT_RELCOUNT comments for details)
1991      case DT_RELACOUNT:
1992        break;
1993      
1994      case DT_REL:
1995        DL_ERR("unsupported DT_REL in \"%s\"", name);
1996        return false;
1997
1998      case DT_RELSZ:
1999        DL_ERR("unsupported DT_RELSZ in \"%s\"", name);
2000        return false;
2001#else
        // 重定位表的偏移,与.rel.dyn section 对应
2002      case DT_REL:
2003        rel = reinterpret_cast<ElfW(Rel)*>(load_bias + d->d_un.d_ptr);
2004        break;
2005      // 重定位表的总大小(字节)
2006      case DT_RELSZ:
2007        rel_count = d->d_un.d_val / sizeof(ElfW(Rel));
2008        break;
2009      // 重定位表项的大小(字节)
2010      case DT_RELENT:
2011        if (d->d_un.d_val != sizeof(ElfW(Rel))) {
2012          DL_ERR("invalid DT_RELENT: %zd", static_cast<size_t>(d->d_un.d_val));
2013          return false;
2014        }
2015        break;
2016
2017      // "Indicates that all RELATIVE relocations have been concatenated together,
2018      // and specifies the RELATIVE relocation count."
2019      //
2020      // TODO: Spec also mentions that this can be used to optimize relocation process;
2021      // Not currently used by bionic linker - ignored.
2022      case DT_RELCOUNT:
2023        break;
2024      case DT_RELA:
2025        DL_ERR("unsupported DT_RELA in \"%s\"", name);
2026        return false;
2027#endif
         // 初始化函数 init 的偏移
2028      case DT_INIT:
2029        init_func = reinterpret_cast<linker_function_t>(load_bias + d->d_un.d_ptr);
2030        DEBUG("%s constructors (DT_INIT) found at %p", name, init_func);
2031        break;
2032      // 结束函数的偏移    
2033      case DT_FINI:
2034        fini_func = reinterpret_cast<linker_function_t>(load_bias + d->d_un.d_ptr);
2035        DEBUG("%s destructors (DT_FINI) found at %p", name, fini_func);
2036        break;
2037      // 初始化函数数组 init_array 的偏移
2038      case DT_INIT_ARRAY:
2039        init_array = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
2040        DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", name, init_array);
2041        break;
2042      // init_array 的大小(字节)
2043      case DT_INIT_ARRAYSZ:
2044        init_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
2045        break;
2046
2047      case DT_FINI_ARRAY:
2048        fini_array = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
2049        DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", name, fini_array);
2050        break;
2051
2052      case DT_FINI_ARRAYSZ:
2053        fini_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
2054        break;
2055
2056      case DT_PREINIT_ARRAY:
2057        preinit_array = reinterpret_cast<linker_function_t*>(load_bias + d->d_un.d_ptr);
2058        DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", name, preinit_array);
2059        break;
2060
2061      case DT_PREINIT_ARRAYSZ:
2062        preinit_array_count = ((unsigned)d->d_un.d_val) / sizeof(ElfW(Addr));
2063        break;
2064
2065      case DT_TEXTREL:
2066#if defined(__LP64__)
2067        DL_ERR("text relocations (DT_TEXTREL) found in 64-bit ELF file \"%s\"", name);
2068        return false;
2069#else
2070        has_text_relocations = true;
2071        break;
2072#endif
2073
2074      case DT_SYMBOLIC:
2075        has_DT_SYMBOLIC = true;
2076        break;
2077      // d->d_un.d_val 是依赖库名字在字符串表中的索引
2078      case DT_NEEDED:
2079        ++needed_count;
2080        break;
2081
2082      case DT_FLAGS:
2083        if (d->d_un.d_val & DF_TEXTREL) {
2084#if defined(__LP64__)
2085          DL_ERR("text relocations (DF_TEXTREL) found in 64-bit ELF file \"%s\"", name);
2086          return false;
2087#else
2088          has_text_relocations = true;
2089#endif
2090        }
2091        if (d->d_un.d_val & DF_SYMBOLIC) {
2092          has_DT_SYMBOLIC = true;
2093        }
2094        break;
2095
2096      case DT_FLAGS_1:
2097        if ((d->d_un.d_val & DF_1_GLOBAL) != 0) {
2098          rtld_flags |= RTLD_GLOBAL;
2099        }
2100        // TODO: Implement other flags
2101
2102        if ((d->d_un.d_val & ~(DF_1_NOW | DF_1_GLOBAL)) != 0) {
2103          DL_WARN("Unsupported flags DT_FLAGS_1=%p", reinterpret_cast<void*>(d->d_un.d_val));
2104        }
2105        break;
2106#if defined(__mips__)
2107      case DT_MIPS_RLD_MAP:
2108        // Set the DT_MIPS_RLD_MAP entry to the address of _r_debug for GDB.
2109        {
2110          r_debug** dp = reinterpret_cast<r_debug**>(load_bias + d->d_un.d_ptr);
2111          *dp = &_r_debug;
2112        }
2113        break;
2114
2115      case DT_MIPS_RLD_VERSION:
2116      case DT_MIPS_FLAGS:
2117      case DT_MIPS_BASE_ADDRESS:
2118      case DT_MIPS_UNREFEXTNO:
2119        break;
2120
2121      case DT_MIPS_SYMTABNO:
2122        mips_symtabno = d->d_un.d_val;
2123        break;
2124
2125      case DT_MIPS_LOCAL_GOTNO:
2126        mips_local_gotno = d->d_un.d_val;
2127        break;
2128
2129      case DT_MIPS_GOTSYM:
2130        mips_gotsym = d->d_un.d_val;
2131        break;
2132#endif
2133      // Ignored: "Its use has been superseded by the DF_BIND_NOW flag"
2134      case DT_BIND_NOW:
2135        break;
2136
2137      // Ignore: bionic does not support symbol versioning...
2138      case DT_VERSYM:
2139      case DT_VERDEF:
2140      case DT_VERDEFNUM:
2141        break;
2142
2143      default:
2144        if (!relocating_linker) {
2145          DL_WARN("%s: unused DT entry: type %p arg %p", name,
2146              reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
2147        }
2148        break;
2149    }
2150  }
2151
2152  DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
2153        reinterpret_cast<void*>(base), strtab, symtab);
2154
2155  // Sanity checks.
2156  if (relocating_linker && needed_count != 0) {
2157    DL_ERR("linker cannot have DT_NEEDED dependencies on other libraries");
2158    return false;
2159  }
2160  if (nbucket == 0) {
2161    DL_ERR("empty/missing DT_HASH in \"%s\" (built with --hash-style=gnu?)", name);
2162    return false;
2163  }
2164  if (strtab == 0) {
2165    DL_ERR("empty/missing DT_STRTAB in \"%s\"", name);
2166    return false;
2167  }
2168  if (symtab == 0) {
2169    DL_ERR("empty/missing DT_SYMTAB in \"%s\"", name);
2170    return false;
2171  }
2172  return true;
2173}
PrelinkImage()

 

        至此, load_library()函数分析完了find_libraries()分析结束返回上一个函数find_libraries()函数

               find_libraries()第三步:

      第三步:对加载的so进行链接:调用LinkImage()

       LinkImage()源码:

2175bool soinfo::LinkImage(const android_dlextinfo* extinfo) {
2176
2177#if !defined(__LP64__)
2178  if (has_text_relocations) {
2179    // Make segments writable to allow text relocations to work properly. We will later call
2180    // phdr_table_protect_segments() after all of them are applied and all constructors are run.
2181    DL_WARN("%s has text relocations. This is wasting memory and prevents "
2182            "security hardening. Please fix.", name);
        // 使段可读写,通过系统调用 mprotect()来设置
2183    if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
2184      DL_ERR("can't unprotect loadable segments for \"%s\": %s",
2185             name, strerror(errno));
2186      return false;
2187    }
2188  }
2189#endif
2190
2191#if defined(USE_RELA)
2192  if (rela != nullptr) {
2193    DEBUG("[ relocating %s ]", name);
2194    if (Relocate(rela, rela_count)) {
2195      return false;
2196    }
2197  }
2198  if (plt_rela != nullptr) {
2199    DEBUG("[ relocating %s plt ]", name);
2200    if (Relocate(plt_rela, plt_rela_count)) {
2201      return false;
2202    }
2203  }
2204#else
2205  if (rel != nullptr) {
2206    DEBUG("[ relocating %s ]", name);
        // 对重定位表中所指的符号进行重定位
2207    if (Relocate(rel, rel_count)) {
2208      return false;
2209    }
2210  }
        // 与调用导入函数相关
2211  if (plt_rel != nullptr) {
2212    DEBUG("[ relocating %s plt ]", name);
        // 对重定位表中所指的符号进行重定位
2213    if (Relocate(plt_rel, plt_rel_count)) {
2214      return false;
2215    }
2216  }
2217#endif
2218
2219#if defined(__mips__)
2220  if (!mips_relocate_got(this)) {
2221    return false;
2222  }
2223#endif
2224
2225  DEBUG("[ finished linking %s ]", name);
2226
2227#if !defined(__LP64__)
2228  if (has_text_relocations) {
2229    // All relocations are done, we can protect our segments back to read-only.
2230    if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
2231      DL_ERR("can't protect segments for \"%s\": %s",
2232             name, strerror(errno));
2233      return false;
2234    }
2235  }
2236#endif
2237
2238  /* We can also turn on GNU RELRO protection */
2239  if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias) < 0) {
2240    DL_ERR("can't enable GNU RELRO protection for \"%s\": %s",
2241           name, strerror(errno));
2242    return false;
2243  }
2244
2245  /* Handle serializing/sharing the RELRO segment */
2246  if (extinfo && (extinfo->flags & ANDROID_DLEXT_WRITE_RELRO)) {
2247    if (phdr_table_serialize_gnu_relro(phdr, phnum, load_bias,
2248                                       extinfo->relro_fd) < 0) {
2249      DL_ERR("failed serializing GNU RELRO section for \"%s\": %s",
2250             name, strerror(errno));
2251      return false;
2252    }
2253  } else if (extinfo && (extinfo->flags & ANDROID_DLEXT_USE_RELRO)) {
2254    if (phdr_table_map_gnu_relro(phdr, phnum, load_bias,
2255                                 extinfo->relro_fd) < 0) {
2256      DL_ERR("failed mapping GNU RELRO section for \"%s\": %s",
2257             name, strerror(errno));
2258      return false;
2259    }
2260  }
2261
2262  notify_gdb_of_load(this);
2263  return true;
2264}
LinkImage()

对rel.dyn 和.rel.plt 两个重定位表都是调用Relocate()来进行重定位的。

159#define ELF32_R_SYM(x) ((x) >> 8)

160#define ELF32_R_TYPE(x) ((x) & 0xff)


164typedef struct elf32_rel {
165 Elf32_Addr r_offset;
166 Elf32_Word r_info;
167} Elf32_Rel;
重定位的数据结构

 

                     Relocate()源码

1359int soinfo::Relocate(ElfW(Rel)* rel, unsigned count) {
        //遍历重定位表
1360  for (size_t idx = 0; idx < count; ++idx, ++rel) {
        // 重定位类型
1361    unsigned type = ELFW(R_TYPE)(rel->r_info);
1362   // 符号表索引
        // 重定位的地址,即 reloc 处的值需要重新计算,对于导入函数来说,地址 reloc 在 got 表中,reloc 处应该是函数的实际地址,代码中函数的地址其实是其在 got 表中的偏移,再从 got 表中跳转到函数的实际地址。
1363    unsigned sym = ELFW(R_SYM)(rel->r_info);
1364    ElfW(Addr) reloc = static_cast<ElfW(Addr)>(rel->r_offset + load_bias);
        // 符号的地址
1365    ElfW(Addr) sym_addr = 0;
        // 符号的名称
1366    const char* sym_name = nullptr;
1367
1368    DEBUG("Processing '%s' relocation at index %zd", name, idx);
1369    if (type == 0) { // R_*_NONE
1370      continue;
1371    }
1372    // 该符号在其定义 so 中的记录
1373    ElfW(Sym)* s = nullptr;
        // 定义该符号的 so
1374    soinfo* lsi = nullptr;
1375
1376    if (sym != 0) {
         // 得到符号的名称
1377      sym_name = get_string(symtab[sym].st_name);
        // 查找 sym_name 定义在哪个 so
1378      s = soinfo_do_lookup(this, sym_name, &lsi);
1379      if (s == nullptr) {
           // 如果该符号没有定义,那么它的绑定类型必须是弱引用
1380        // We only allow an undefined symbol if this is a weak reference...
1381        s = &symtab[sym];
1382        if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
1383          DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, name);
1384          return -1;
1385        }
1386
1387        /* IHI0044C AAELF 4.5.1.1:
1388
1389           Libraries are not searched to resolve weak references.
1390           It is not an error for a weak reference to remain
1391           unsatisfied.
1392
1393           During linking, the value of an undefined weak reference is:
1394           - Zero if the relocation type is absolute
1395           - The address of the place if the relocation is pc-relative
1396           - The address of nominal base address if the relocation
1397             type is base-relative.
1398        */
1399
1400        switch (type) {
        // 没有定义的弱引用,它的 sym_addr 是 0,或者重定位的时候不关心 sym_addr 的值
1401#if defined(__arm__)
1402          case R_ARM_JUMP_SLOT:
1403          case R_ARM_GLOB_DAT:
1404          case R_ARM_ABS32:
1405          case R_ARM_RELATIVE:    /* Don't care. */
1406            // sym_addr was initialized to be zero above or relocation
1407            // code below does not care about value of sym_addr.
1408            // No need to do anything.
1409            break;
1410#elif defined(__i386__)
1411          case R_386_JMP_SLOT:
1412          case R_386_GLOB_DAT:
1413          case R_386_32:
1414          case R_386_RELATIVE:    /* Don't care. */
1415          case R_386_IRELATIVE:
1416            // sym_addr was initialized to be zero above or relocation
1417            // code below does not care about value of sym_addr.
1418            // No need to do anything.
1419            break;
1420          case R_386_PC32:
1421            sym_addr = reloc;
1422            break;
1423#endif
1424
1425#if defined(__arm__)
1426          case R_ARM_COPY:
1427            // Fall through. Can't really copy if weak symbol is not found at run-time.
1428#endif
1429          default:
1430            DL_ERR("unknown weak reloc type %d @ %p (%zu)", type, rel, idx);
1431            return -1;
1432        }
1433      } else {
1434        // 找到了符号的定义 so,计算该符号的地址
1435        sym_addr = lsi->resolve_symbol_address(s);
1436      }
1437      count_relocation(kRelocSymbol);
1438    }
1439
1440    switch (type) {
        // 根据重定位类型修改 reloc 处的值
1441#if defined(__arm__)
1442      case R_ARM_JUMP_SLOT:
1443        count_relocation(kRelocAbsolute);
1444        MARK(rel->r_offset);
1445        TRACE_TYPE(RELO, "RELO JMP_SLOT %08x <- %08x %s", reloc, sym_addr, sym_name);
1446        *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr;
1447        break;
1448      case R_ARM_GLOB_DAT:
1449        count_relocation(kRelocAbsolute);
1450        MARK(rel->r_offset);
1451        TRACE_TYPE(RELO, "RELO GLOB_DAT %08x <- %08x %s", reloc, sym_addr, sym_name);
1452        *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr;
1453        break;
1454      case R_ARM_ABS32:
1455        count_relocation(kRelocAbsolute);
1456        MARK(rel->r_offset);
1457        TRACE_TYPE(RELO, "RELO ABS %08x <- %08x %s", reloc, sym_addr, sym_name);
1458        *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
1459        break;
1460      case R_ARM_REL32:
1461        count_relocation(kRelocRelative);
1462        MARK(rel->r_offset);
1463        TRACE_TYPE(RELO, "RELO REL32 %08x <- %08x - %08x %s",
1464                   reloc, sym_addr, rel->r_offset, sym_name);
1465        *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset;
1466        break;
1467      case R_ARM_COPY:
1468        /*
1469         * ET_EXEC is not supported so this should not happen.
1470         *
1471         * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
1472         *
1473         * Section 4.7.1.10 "Dynamic relocations"
1474         * R_ARM_COPY may only appear in executable objects where e_type is
1475         * set to ET_EXEC.
1476         */
1477        DL_ERR("%s R_ARM_COPY relocations are not supported", name);
1478        return -1;
1479#elif defined(__i386__)
1480      case R_386_JMP_SLOT:
1481        count_relocation(kRelocAbsolute);
1482        MARK(rel->r_offset);
1483        TRACE_TYPE(RELO, "RELO JMP_SLOT %08x <- %08x %s", reloc, sym_addr, sym_name);
1484        *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr;
1485        break;
1486      case R_386_GLOB_DAT:
1487        count_relocation(kRelocAbsolute);
1488        MARK(rel->r_offset);
1489        TRACE_TYPE(RELO, "RELO GLOB_DAT %08x <- %08x %s", reloc, sym_addr, sym_name);
1490        *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr;
1491        break;
1492      case R_386_32:
1493        count_relocation(kRelocRelative);
1494        MARK(rel->r_offset);
1495        TRACE_TYPE(RELO, "RELO R_386_32 %08x <- +%08x %s", reloc, sym_addr, sym_name);
1496        *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
1497        break;
1498      case R_386_PC32:
1499        count_relocation(kRelocRelative);
1500        MARK(rel->r_offset);
1501        TRACE_TYPE(RELO, "RELO R_386_PC32 %08x <- +%08x (%08x - %08x) %s",
1502                   reloc, (sym_addr - reloc), sym_addr, reloc, sym_name);
1503        *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr - reloc);
1504        break;
1505#elif defined(__mips__)
1506      case R_MIPS_REL32:
1507#if defined(__LP64__)
1508        // MIPS Elf64_Rel entries contain compound relocations
1509        // We only handle the R_MIPS_NONE|R_MIPS_64|R_MIPS_REL32 case
1510        if (ELF64_R_TYPE2(rel->r_info) != R_MIPS_64 ||
1511            ELF64_R_TYPE3(rel->r_info) != R_MIPS_NONE) {
1512          DL_ERR("Unexpected compound relocation type:%d type2:%d type3:%d @ %p (%zu)",
1513                 type, (unsigned)ELF64_R_TYPE2(rel->r_info),
1514                 (unsigned)ELF64_R_TYPE3(rel->r_info), rel, idx);
1515          return -1;
1516        }
1517#endif
1518        count_relocation(kRelocAbsolute);
1519        MARK(rel->r_offset);
1520        TRACE_TYPE(RELO, "RELO REL32 %08zx <- %08zx %s", static_cast<size_t>(reloc),
1521                   static_cast<size_t>(sym_addr), sym_name ? sym_name : "*SECTIONHDR*");
1522        if (s) {
1523          *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
1524        } else {
1525          *reinterpret_cast<ElfW(Addr)*>(reloc) += base;
1526        }
1527        break;
1528#endif
1529
1530#if defined(__arm__)
1531      case R_ARM_RELATIVE:
1532#elif defined(__i386__)
1533      case R_386_RELATIVE:
1534#endif
1535        count_relocation(kRelocRelative);
1536        MARK(rel->r_offset);
1537        if (sym) {
1538          DL_ERR("odd RELATIVE form...");
1539          return -1;
1540        }
1541        TRACE_TYPE(RELO, "RELO RELATIVE %p <- +%p",
1542                   reinterpret_cast<void*>(reloc), reinterpret_cast<void*>(base));
1543        *reinterpret_cast<ElfW(Addr)*>(reloc) += base;
1544        break;
1545#if defined(__i386__)
1546      case R_386_IRELATIVE:
1547        count_relocation(kRelocRelative);
1548        MARK(rel->r_offset);
1549        TRACE_TYPE(RELO, "RELO IRELATIVE %p <- %p", reinterpret_cast<void*>(reloc), reinterpret_cast<void*>(base));
1550        *reinterpret_cast<ElfW(Addr)*>(reloc) = call_ifunc_resolver(base + *reinterpret_cast<ElfW(Addr)*>(reloc));
1551        break;
1552#endif
1553
1554      default:
1555        DL_ERR("unknown reloc type %d @ %p (%zu)", type, rel, idx);
1556        return -1;
1557    }
1558  }
1559  return 0;
1560}
Relocate()

 

                        soinfo_do_lookup()查找符号的定义 so

                        soinfo_do_lookup()源码:

482static ElfW(Sym)* soinfo_do_lookup(soinfo* si, const char* name, soinfo** lsi) {
      // 计算符号的哈希值
483  unsigned elf_hash = elfhash(name);
484  ElfW(Sym)* s = nullptr;
485
486  /* "This element's presence in a shared object library alters the dynamic linker's
487   * symbol resolution algorithm for references within the library. Instead of starting
488   * a symbol search with the executable file, the dynamic linker starts from the shared
489   * object itself. If the shared object fails to supply the referenced symbol, the
490   * dynamic linker then searches the executable file and other shared objects as usual."
491   *
492   * http://www.sco.com/developers/gabi/2012-12-31/ch5.dynamic.html
493   *
494   * Note that this is unlikely since static linker avoids generating
495   * relocations for -Bsymbolic linked dynamic executables.
496   */
497  if (si->has_DT_SYMBOLIC) {
498    DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si->name, name);
499    s = soinfo_elf_lookup(si, elf_hash, name);
500    if (s != nullptr) {
501      *lsi = si;
502    }
503  }
504
505  if (s == nullptr && somain != nullptr) {
506    // 1. Look for it in the main executable unless we already did.
507    if (si != somain || !si->has_DT_SYMBOLIC) {
508      DEBUG("%s: looking up %s in executable %s",
509            si->name, name, somain->name);
510      s = soinfo_elf_lookup(somain, elf_hash, name);
511      if (s != nullptr) {
512        *lsi = somain;
513      }
514    }
515
516    // 2. Look for it in the ld_preloads
517    if (s == nullptr) {
518      for (int i = 0; g_ld_preloads[i] != NULL; i++) {
519        s = soinfo_elf_lookup(g_ld_preloads[i], elf_hash, name);
520        if (s != nullptr) {
521          *lsi = g_ld_preloads[i];
522          break;
523        }
524      }
525    }
526  }
527
528  /* Look for symbols in the local scope (the object who is
529   * searching). This happens with C++ templates on x86 for some
530   * reason.
531   *
532   * Notes on weak symbols:
533   * The ELF specs are ambiguous about treatment of weak definitions in
534   * dynamic linking.  Some systems return the first definition found
535   * and some the first non-weak definition.   This is system dependent.
536   * Here we return the first definition found for simplicity.  */
537
538  if (s == nullptr && !si->has_DT_SYMBOLIC) {
        // 在其依赖库(子结点)中递归查找符号
539    DEBUG("%s: looking up %s in local scope", si->name, name);
540    s = soinfo_elf_lookup(si, elf_hash, name);
541    if (s != nullptr) {
542      *lsi = si;
543    }
544  }
545
546  if (s == nullptr) {
547    si->get_children().visit([&](soinfo* child) {
548      DEBUG("%s: looking up %s in %s", si->name, name, child->name);
549      s = soinfo_elf_lookup(child, elf_hash, name);
550      if (s != nullptr) {
551        *lsi = child;
552        return false;
553      }
554      return true;
555    });
556  }
557
558  if (s != nullptr) {
559    TRACE_TYPE(LOOKUP, "si %s sym %s s->st_value = %p, "
560               "found in %s, base = %p, load bias = %p",
561               si->name, name, reinterpret_cast<void*>(s->st_value),
562               (*lsi)->name, reinterpret_cast<void*>((*lsi)->base),
563               reinterpret_cast<void*>((*lsi)->load_bias));
564  }
565
566  return s;
567}
soinfo_do_lookup()

 

                            soinfo_do_look()分别在其自身、 预加载库和依赖库中查找符号的定义,具体的查找函数是 soinfo_elf_lookup()

                            soinfo_elf_lookup()源码:

418static ElfW(Sym)* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name) {

         // 符号表

419  ElfW(Sym)* symtab = si->symtab;
420
421  TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p %x %zd",
422             name, si->name, reinterpret_cast<void*>(si->base), hash, hash % si->nbucket);
423   // 通过哈希表在符号表中快速查找 name
424  for (unsigned n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]) {
425    ElfW(Sym)* s = symtab + n;
        // 符号名字需相同
426    if (strcmp(si->get_string(s->st_name), name)) continue;
427
428    // only concern ourselves with global and weak symbol definitions
429    switch (ELF_ST_BIND(s->st_info)) {
430      case STB_GLOBAL:
431      case STB_WEAK:
432        if (s->st_shndx == SHN_UNDEF) {
           // 符号未定义
433          continue;
434        }
435
436        TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
437                 name, si->name, reinterpret_cast<void*>(s->st_value),
438                 static_cast<size_t>(s->st_size));
           // 在 si 中找到符号的定义
439        return s;
440      case STB_LOCAL:
441        continue;
442      default:
443        __libc_fatal("ERROR: Unexpected ST_BIND value: %d for '%s' in '%s'",
444            ELF_ST_BIND(s->st_info), name, si->name);
445    }
446  }
447
448  TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
449             name, si->name, reinterpret_cast<void*>(si->base), hash, hash % si->nbucket);
450
451
452  return nullptr;
453}
soinfo_elf_lookup()

 

 

 

                            Relocate()函数,在找到符号后,调用resolve_symbol_address() 来计算符号的地址 。

                            resolve_symbol_address() 源码

如果符号的类型不是 STT_GNU_IFUNC(GNU indirect function),如STT_FUNC(可执行代码,如函数)、 STT_OBJECT(数据对象,如变量)等, 直接返回符号的地址,即 s->st_value  +  load_bias, 否者调用 call_ifunc_resolver()计算符号的地址

                       call_ifunc_resolver()源码:
1072static ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr) {
1073  typedef ElfW(Addr) (*ifunc_resolver_t)(void);
      // 将 resolver_addr 转为函数指针
1074  ifunc_resolver_t ifunc_resolver = reinterpret_cast<ifunc_resolver_t>(resolver_addr);
      // 执行 resoler_addr 处的函数
1075  ElfW(Addr) ifunc_addr = ifunc_resolver();
1076  TRACE_TYPE(RELO, "Called ifunc_resolver@%p. The result is %p", ifunc_resolver, reinterpret_cast<void*>(ifunc_addr));
1077
1078  return ifunc_addr;
1079}
call_ifunc_resolver()

 

重定位类型与重定位值的计算方式对应表

重定位类型

reloc 处的值

R_ARM_JUMP_SLOT

*reloc = sym_addr

R_ARM_GLOB_DAT

*reloc = sym_addr

R_ARM_ABS32

*reloc += sym_addr

R_ARM_REL32

*reloc+= sym_addr - rel->r_offset

R_ARM_RELATIVE

*reloc += base

                                   

至此,find_libraries()的第三部分分析完了。

总结:遍历重定位表,根据重定项的 r_info 获得重定位类型和重定位项对应的符号在符号表中的索引;然后利用 so 中的 hash 表,根据符号名快速地查找符号在哪个 so中定义; 当找到了符号的定义,计算符号的地址 sym_addr;最后根据符号的重定位类型,结合 sym_addr 计算重定位值。

                            so 文件加载到内存,并链接完成后,就开始调用 so 中的初始化函数。回到 do_dlopen()继续分析。

  do_dlopen()的第二部分:

                     CallConstructors()进行初始化操作

                     CallConstructors()源码

1656void soinfo::CallConstructors() {
1657  if (constructors_called) {
1658    return;
1659  }
1660
1661  // We set constructors_called before actually calling the constructors, otherwise it doesn't
1662  // protect against recursive constructor calls. One simple example of constructor recursion
1663  // is the libc debug malloc, which is implemented in libc_malloc_debug_leak.so:
1664  // 1. The program depends on libc, so libc's constructor is called here.
1665  // 2. The libc constructor calls dlopen() to load libc_malloc_debug_leak.so.
1666  // 3. dlopen() calls the constructors on the newly created
1667  //    soinfo for libc_malloc_debug_leak.so.
1668  // 4. The debug .so depends on libc, so CallConstructors is
1669  //    called again with the libc soinfo. If it doesn't trigger the early-
1670  //    out above, the libc constructor will be called again (recursively!).
1671  constructors_called = true;
1672
1673  if ((flags & FLAG_EXE) == 0 && preinit_array != nullptr) {
1674    // The GNU dynamic linker silently ignores these, but we warn the developer.
1675    PRINT("\"%s\": ignoring %zd-entry DT_PREINIT_ARRAY in shared library!",
1676          name, preinit_array_count);
1677  }
1678
1679  get_children().for_each([] (soinfo* si) {
1680    si->CallConstructors();
1681  });
1682
1683  TRACE("\"%s\": calling constructors", name);
1684
1685  // DT_INIT should be called before DT_INIT_ARRAY if both are present.
      // 调用 init_func 函数
1686  CallFunction("DT_INIT", init_func);
      // 调用 init_array 数组中的函数
1687  CallArray("DT_INIT_ARRAY", init_array, init_array_count, false);
1688}
CallConstructors()

 

init_func 和init_array,这两个变量是在 PrelinkImage()中解析 dynamic  section 时赋值的。 通常加壳逻辑就放在 init_func 或 init_array 中,它们先于 jni_onLoad 执行。

 

posted on 2019-06-07 11:48  黑箱  阅读(5058)  评论(1编辑  收藏  举报