1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
| libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java public DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent)
libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java BaseDexClassLoader(String dexPath, File optimizedDirectory, String librarySearchPath, ClassLoader parent)
libcore/dalvik/src/main/java/dalvik/system/DexPathList.java DexPathList(ClassLoader definingContext, ByteBuffer[] dexFiles)
libcore/dalvik/src/main/java/dalvik/system/DexPathList.java private static Element[] makeDexElements(List<File> files, File optimizedDirectory, List<IOException> suppressedExceptions, ClassLoader loader) private static DexFile loadDexFile(File file, File optimizedDirectory, ClassLoader loader, Element[] elements) 其中return DexFile.loadDex(file.getPath(), optimizedPath, 0, loader, elements);
libcore/dalvik/src/main/java/dalvik/system/DexFile.java static DexFile loadDex(String sourcePathName, String outputPathName,int flags, ClassLoader loader, DexPathList.Element[] elements) 其中return new DexFile(sourcePathName, outputPathName, flags, loader, elements);
libcore/dalvik/src/main/java/dalvik/system/DexFile.java DexFile(String fileName, ClassLoader loader, DexPathList.Element[] elements) 其中mCookie = openDexFile(fileName, null, 0, loader, elements);
private static Object openDexFile(String sourceName, String outputName, int flags, ClassLoader loader, DexPathList.Element[] elements) 其中 return openDexFileNative(new File(sourceName).getAbsolutePath(), (outputName == null) ? null : new File(outputName).getAbsolutePath(), flags, loader, elements);
是个native函数 private static native Object openDexFileNative(String sourceName, String outputName, int flags, ClassLoader loader, DexPathList.Element[] elements) art/runtime/native/dalvik_system_DexFile.cc static jobject DexFile_openDexFileNative(JNIEnv* env, jclass, jstring javaSourceName, jstring javaOutputName ATTRIBUTE_UNUSED, jint flags ATTRIBUTE_UNUSED, jobject class_loader, jobjectArray dex_elements) 加载路径javaSourceName DexFile_openDexFileNative其中包含: const OatFile* oat_file = nullptr; dex_files = runtime->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(), class_loader, dex_elements, &oat_file, &error_msgs); 首次出现oat OpenDexFilesFromOat最终会编译生成OAT的关键地方 当我们第一次使用DexClassLoader去动态加载一个解密的dex文件时,还没有编译生成OAT
art/runtime/oat_file_manager.cc std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat( const char* dex_location, jobject class_loader, jobjectArray dex_elements, const OatFile** out_oat_file, std::vector<std::string>* error_msgs)
其中创建了oat_file_assistant对象 OatFileAssistant oat_file_assistant(dex_location, kRuntimeISA, !runtime->IsAotCompiler()); 第一次调用时是没有OAT的 if (!oat_file_assistant.IsUpToDate()) 这时会执行MakeUpToDate switch (oat_file_assistant.MakeUpToDate(false, &error_msg))
art/runtime/oat_file_assistant.cc OatFileAssistant::MakeUpToDate(bool profile_changed, std::string* error_msg) 最后返回return GenerateOatFileNoChecks(info, target, error_msg);
art/runtime/oat_file_assistant.cc OatFileAssistant::ResultOfAttemptToUpdate OatFileAssistant::GenerateOatFileNoChecks( OatFileAssistant::OatFileInfo& info, CompilerFilter::Filter filter, std::string* error_msg) 其中包含生成OAT文件的路径相关的函数 首先判断 if (!runtime->IsDex2OatEnabled()),Dex2Oat的状态可不可用,如果是false则直接返回,不会进行编译生成OAT的过程 编译, if (!Dex2Oat(args, error_msg))
art/runtime/oat_file_assistant.cc bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args, std::string* error_msg) 其中包括调用编译生成OAT的一些程序的相关参数 最终调用Exec来完成Dex2Oat的编译的过程,return Exec(argv, error_msg);
art/runtime/exec_utils.cc bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) 调用了ExecAndReturnCode
art/runtime/exec_utils.cc int ExecAndReturnCode(std::vector<std::string>& arg_vector, std::string* error_msg) 在这里首次进行了对进程的fork,pid_t pid = fork(); 在子进程中使用execve来实现对Dex2Oat的编译过程
在这整个流程过程中如果我们对某个函数,比如execve进行修改或hook,都会导致Dex2OAT的流程的结束
实际上,强制停止Dex2Oat的流程,会让DexClassLoader第一次加载动态的dex时的过程变得非常的快速,减少了Dex2Oat的编译的流程
与此同时,要想实现ART下的函数抽取技术,我们也要强制阻断Dex2Oat的流程
回到art/runtime/oat_file_manager.cc 当我们阻断Dex2Oat的编译的流程,std::unique_ptr<const OatFile> oat_file(oat_file_assistant.GetBestOatFile().release());将会是一个空的操作
最终我们会进入到 if (oat_file_assistant.HasOriginalDexFiles()),会尝试加载我们的dex文件 之后调用DexFile::Open,if (!DexFile::Open(dex_location, dex_location, kVerifyChecksum, &error_msg, &dex_files))
art/runtime/dex_file.cc bool DexFile::Open(const char* filename, const std::string& location, bool verify_checksum, std::string* error_msg, std::vector<std::unique_ptr<const DexFile>>* dex_files) 其中调用了File fd = OpenAndReadMagic(filename, &magic, error_msg);是一个脱壳点
又因为我们加载的是一个dex文件,之后我们又会进入到DexFile::OpenFile if (IsDexMagic(magic)) { std::unique_ptr<const DexFile> dex_file(DexFile::OpenFile(fd.Release(), location, true, verify_checksum, error_msg));
art/runtime/dex_file.cc std::unique_ptr<const DexFile> DexFile::OpenFile(int fd, const std::string& location, bool verify, bool verify_checksum, std::string* error_msg) 这其中又会调用并进入OpenCommon std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(), map->Size(), location, dex_header->checksum_, kNoOatDexFile, verify, verify_checksum, error_msg);
art/runtime/dex_file.cc std::unique_ptr<DexFile> DexFile::OpenCommon(const uint8_t* base, size_t size, const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, bool verify_checksum, std::string* error_msg, VerifyResult* verify_result) 其中DexFile的构造函数 std::unique_ptr<DexFile> dex_file(new DexFile(base, size, location, location_checksum, oat_dex_file)); art/runtime/dex_file.cc DexFile::DexFile(const uint8_t* base, size_t size, const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file)
和 InMemoryDexClassLoader一样
|