android 加载so的流程
Posted 寻步
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android 加载so的流程相关的知识,希望对你有一定的参考价值。
源码版本:android-4.4.4_r1
以 [java.lang.Runtime -> load()] 为例来说明(loadLiabrary() 最后和 load() 殊途同归,有兴趣的可以自行分析),对应的 Android 源码在 [srcAndroid/libcore/luni/src/main/java/java/lang/Runtime.java/home/shanyu/srcAndroid/libcore/luni/src/main/java/java/lang/Runtime.java],
从 320 行开始。
/** * Loads and links the dynamic library that is identified through the * specified path. This method is similar to {@link #loadLibrary(String)}, * but it accepts a full path specification whereas {@code loadLibrary} just * accepts the name of the library to load. * * @param pathName * the absolute (platform dependent) path to the library to load. * @throws UnsatisfiedLinkError * if the library can not be loaded. */ public void load(String pathName) { load(pathName, VMStack.getCallingClassLoader()); } /* * Loads and links the given library without security checks. */ void load(String pathName, ClassLoader loader) { if (pathName == null) { throw new NullPointerException("pathName == null"); } String error = doLoad(pathName, loader); if (error != null) { throw new UnsatisfiedLinkError(error); } }
最终调用了doLoad(String name, ClassLoader loader)函数,这个函数仍然在Runtime.java文件中:
private String doLoad(String name, ClassLoader loader) { // Android apps are forked from the zygote, so they can‘t have a custom LD_LIBRARY_PATH, // which means that by default an app‘s shared library directory isn‘t on LD_LIBRARY_PATH. // The PathClassLoader set up by frameworks/base knows the appropriate path, so we can load // libraries with no dependencies just fine, but an app that has multiple libraries that // depend on each other needed to load them in most-dependent-first order. // We added API to Android‘s dynamic linker so we can update the library path used for // the currently-running process. We pull the desired path out of the ClassLoader here // and pass it to nativeLoad so that it can call the private dynamic linker API. // We didn‘t just change frameworks/base to update the LD_LIBRARY_PATH once at the // beginning because multiple apks can run in the same process and third party code can // use its own BaseDexClassLoader. // We didn‘t just add a dlopen_with_custom_LD_LIBRARY_PATH call because we wanted any // dlopen(3) calls made from a .so‘s JNI_OnLoad to work too. // So, find out what the native library search path is for the ClassLoader in question... String ldLibraryPath = null; if (loader != null && loader instanceof BaseDexClassLoader) { ldLibraryPath = ((BaseDexClassLoader) loader).getLdLibraryPath(); } // nativeLoad should be synchronized so there‘s only one LD_LIBRARY_PATH in use regardless // of how many ClassLoaders are in the system, but dalvik doesn‘t support synchronized // internal natives. synchronized (this) { return nativeLoad(name, loader, ldLibraryPath); } } // TODO: should be synchronized, but dalvik doesn‘t support synchronized internal natives. private static native String nativeLoad(String filename, ClassLoader loader, String ldLibraryPath);
最终调用到了"String nativeLoad(String filename, ClassLoader loader, String ldLibraryPath)"函数,这个一个native函数,定义位于[srcAndroid/dalvik/vm/native/java_lang_Runtime.cpp]文件中。从64行开始:
/* * static String nativeLoad(String filename, ClassLoader loader, String ldLibraryPath) * * Load the specified full path as a dynamic library filled with * JNI-compatible methods. Returns null on success, or a failure * message on failure. */ static void Dalvik_java_lang_Runtime_nativeLoad(const u4* args, JValue* pResult) { StringObject* fileNameObj = (StringObject*) args[0]; Object* classLoader = (Object*) args[1]; StringObject* ldLibraryPathObj = (StringObject*) args[2]; assert(fileNameObj != NULL); char* fileName = dvmCreateCstrFromString(fileNameObj); if (ldLibraryPathObj != NULL) { char* ldLibraryPath = dvmCreateCstrFromString(ldLibraryPathObj); void* sym = dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH"); if (sym != NULL) { typedef void (*Fn)(const char*); Fn android_update_LD_LIBRARY_PATH = reinterpret_cast<Fn>(sym); (*android_update_LD_LIBRARY_PATH)(ldLibraryPath); } else { ALOGE("android_update_LD_LIBRARY_PATH not found; .so dependencies will not work!"); } free(ldLibraryPath); } StringObject* result = NULL; char* reason = NULL; bool success = dvmLoadNativeCode(fileName, classLoader, &reason); if (!success) { const char* msg = (reason != NULL) ? reason : "unknown failure"; result = dvmCreateStringFromCstr(msg); dvmReleaseTrackedAlloc((Object*) result, NULL); } free(reason); free(fileName); RETURN_PTR(result); }
还是传值 + 检查,然后执行 [bool success = dvmLoadNativeCode(fileName, classLoader, &reason);] ,看下 dvmLoadNativeCode(...) 的代码,位于 vm/Native.cpp # 301 行。
以上是关于android 加载so的流程的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )(代码片段