2、oat_file_assistant.cc#Dex2Oat 源码分析
在 /art/runtime/oat_file_assistant.cc#Dex2Oat 函数中 , 调用了 /art/runtime/exec_utils.cc#Exec 函数 ;
bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args, std::string* error_msg) { Runtime* runtime = Runtime::Current(); std::string image_location = ImageLocation(); if (image_location.empty()) { *error_msg = "No image location found for Dex2Oat."; return false; } std::vector<std::string> argv; argv.push_back(runtime->GetCompilerExecutable()); argv.push_back("--runtime-arg"); argv.push_back("-classpath"); argv.push_back("--runtime-arg"); std::string class_path = runtime->GetClassPathString(); if (class_path == "") { class_path = OatFile::kSpecialSharedLibrary; } argv.push_back(class_path); if (runtime->IsJavaDebuggable()) { argv.push_back("--debuggable"); } runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv); if (!runtime->IsVerificationEnabled()) { argv.push_back("--compiler-filter=verify-none"); } if (runtime->MustRelocateIfPossible()) { argv.push_back("--runtime-arg"); argv.push_back("-Xrelocate"); } else { argv.push_back("--runtime-arg"); argv.push_back("-Xnorelocate"); } if (!kIsTargetBuild) { argv.push_back("--host"); } argv.push_back("--boot-image=" + image_location); std::vector<std::string> compiler_options = runtime->GetCompilerOptions(); argv.insert(argv.end(), compiler_options.begin(), compiler_options.end()); argv.insert(argv.end(), args.begin(), args.end()); std::string command_line(android::base::Join(argv, ' ')); // ★ 核心跳转 return Exec(argv, error_msg); }
源码路径 : /art/runtime/oat_file_assistant.cc#Dex2Oat
3、exec_utils.cc#Exec 源码分析
在 /art/runtime/exec_utils.cc#Exec 函数中 , 调用了 /art/runtime/exec_utils.cc#ExecAndReturnCode 函数 ;
bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) { // ★ 核心跳转 int status = ExecAndReturnCode(arg_vector, error_msg); if (status != 0) { const std::string command_line(android::base::Join(arg_vector, ' ')); *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status", command_line.c_str()); return false; } return true; }
源码路径 : /art/runtime/exec_utils.cc#Exec
4、exec_utils.cc#ExecAndReturnCode 源码分析
在 /art/runtime/exec_utils.cc#ExecAndReturnCode 函数中 , 调用了
execve(program, &args[0], envp);
函数 , 通过 hook 该 execve 函数 , 可以禁用 dex2oat ;
int ExecAndReturnCode(std::vector<std::string>& arg_vector, std::string* error_msg) { const std::string command_line(android::base::Join(arg_vector, ' ')); CHECK_GE(arg_vector.size(), 1U) << command_line; // 将参数转换为字符指针。 const char* program = arg_vector[0].c_str(); std::vector<char*> args; for (size_t i = 0; i < arg_vector.size(); ++i) { const std::string& arg = arg_vector[i]; char* arg_str = const_cast<char*>(arg.c_str()); CHECK(arg_str != nullptr) << i; args.push_back(arg_str); } args.push_back(nullptr); // fork and exec pid_t pid = fork(); if (pid == 0) { // fork和exec之间不允许分配 // 更改流程组,这样我们就不会被ProcessManager收获 setpgid(0, 0); // (b/30160149): 保护子进程不受对LD_LIBRARY_路径等的修改的影响。 // 使用从创建运行时开始的环境快照。 char** envp = (Runtime::Current() == nullptr) ? nullptr : Runtime::Current()->GetEnvSnapshot(); if (envp == nullptr) { execv(program, &args[0]); } else { execve(program, &args[0], envp); } PLOG(ERROR) << "Failed to execve(" << command_line << ")"; // _exit to avoid atexit handlers in child. _exit(1); } else { if (pid == -1) { *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s", command_line.c_str(), strerror(errno)); return -1; } // 等待子进程完成 int status = -1; pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); if (got_pid != pid) { *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: " "wanted %d, got %d: %s", command_line.c_str(), pid, got_pid, strerror(errno)); return -1; } if (WIFEXITED(status)) { return WEXITSTATUS(status); } return -1; } }
源码路径 : /art/runtime/exec_utils.cc#ExecAndReturnCode