diff options
Diffstat (limited to 'runtime/oat_file_assistant.cc')
-rw-r--r-- | runtime/oat_file_assistant.cc | 334 |
1 files changed, 0 insertions, 334 deletions
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index f7c74cc23b..e262ff7150 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -36,7 +36,6 @@ #include "exec_utils.h" #include "gc/heap.h" #include "gc/space/image_space.h" -#include "hidden_api.h" #include "image.h" #include "oat.h" #include "runtime.h" @@ -182,30 +181,6 @@ bool OatFileAssistant::IsInBootClassPath() { return false; } -bool OatFileAssistant::Lock(std::string* error_msg) { - CHECK(error_msg != nullptr); - CHECK(flock_.get() == nullptr) << "OatFileAssistant::Lock already acquired"; - - // Note the lock will only succeed for secondary dex files and in test - // environment. - // - // The lock *will fail* for all primary apks in a production environment. - // The app does not have permissions to create locks next to its dex location - // (be it system, data or vendor parition). We also cannot use the odex or - // oat location for the same reasoning. - // - // This is best effort and if it fails it's unlikely that we will be able - // to generate oat files anyway. - std::string lock_file_name = dex_location_ + "." + GetInstructionSetString(isa_) + ".flock"; - - flock_ = LockedFile::Open(lock_file_name.c_str(), error_msg); - if (flock_.get() == nullptr) { - unlink(lock_file_name.c_str()); - return false; - } - return true; -} - int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target, bool profile_changed, bool downgrade, @@ -221,72 +196,10 @@ int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target, return -dexopt_needed; } -// Figure out the currently specified compile filter option in the runtime. -// Returns true on success, false if the compiler filter is invalid, in which -// case error_msg describes the problem. -static bool GetRuntimeCompilerFilterOption(CompilerFilter::Filter* filter, - std::string* error_msg) { - CHECK(filter != nullptr); - CHECK(error_msg != nullptr); - - *filter = OatFileAssistant::kDefaultCompilerFilterForDexLoading; - for (StringPiece option : Runtime::Current()->GetCompilerOptions()) { - if (option.starts_with("--compiler-filter=")) { - const char* compiler_filter_string = option.substr(strlen("--compiler-filter=")).data(); - if (!CompilerFilter::ParseCompilerFilter(compiler_filter_string, filter)) { - *error_msg = std::string("Unknown --compiler-filter value: ") - + std::string(compiler_filter_string); - return false; - } - } - } - return true; -} - bool OatFileAssistant::IsUpToDate() { return GetBestInfo().Status() == kOatUpToDate; } -OatFileAssistant::ResultOfAttemptToUpdate -OatFileAssistant::MakeUpToDate(bool profile_changed, - ClassLoaderContext* class_loader_context, - std::string* error_msg) { - // The method doesn't use zip_fd_ and directly opens dex files at dex_locations_. - CHECK_EQ(-1, zip_fd_) << "MakeUpToDate should not be called with zip_fd"; - - CompilerFilter::Filter target; - if (!GetRuntimeCompilerFilterOption(&target, error_msg)) { - return kUpdateNotAttempted; - } - - OatFileInfo& info = GetBestInfo(); - // TODO(calin, jeffhao): the context should really be passed to GetDexOptNeeded: b/62269291. - // This is actually not trivial in the current logic as it will interact with the collision - // check: - // - currently, if the context does not match but we have no collisions we still accept the - // oat file. - // - if GetDexOptNeeded would return kDex2OatFromScratch for a context mismatch and we make - // the oat code up to date the collision check becomes useless. - // - however, MakeUpToDate will not always succeed (e.g. for primary apks, or for dex files - // loaded in other processes). So it boils down to how far do we want to complicate - // the logic in order to enable the use of oat files. Maybe its time to try simplify it. - switch (info.GetDexOptNeeded( - target, profile_changed, /*downgrade*/ false, class_loader_context)) { - case kNoDexOptNeeded: - return kUpdateSucceeded; - - // TODO: For now, don't bother with all the different ways we can call - // dex2oat to generate the oat file. Always generate the oat file as if it - // were kDex2OatFromScratch. - case kDex2OatFromScratch: - case kDex2OatForBootImage: - case kDex2OatForRelocation: - case kDex2OatForFilter: - return GenerateOatFileNoChecks(info, target, class_loader_context, error_msg); - } - UNREACHABLE(); -} - std::unique_ptr<OatFile> OatFileAssistant::GetBestOatFile() { return GetBestInfo().ReleaseFileForUse(); } @@ -615,243 +528,6 @@ static bool DexLocationToOdexNames(const std::string& location, return true; } -// Prepare a subcomponent of the odex directory. -// (i.e. create and set the expected permissions on the path `dir`). -static bool PrepareDirectory(const std::string& dir, std::string* error_msg) { - struct stat dir_stat; - if (TEMP_FAILURE_RETRY(stat(dir.c_str(), &dir_stat)) == 0) { - // The directory exists. Check if it is indeed a directory. - if (!S_ISDIR(dir_stat.st_mode)) { - *error_msg = dir + " is not a dir"; - return false; - } else { - // The dir is already on disk. - return true; - } - } - - // Failed to stat. We need to create the directory. - if (errno != ENOENT) { - *error_msg = "Could not stat isa dir " + dir + ":" + strerror(errno); - return false; - } - - mode_t mode = S_IRWXU | S_IXGRP | S_IXOTH; - if (mkdir(dir.c_str(), mode) != 0) { - *error_msg = "Could not create dir " + dir + ":" + strerror(errno); - return false; - } - if (chmod(dir.c_str(), mode) != 0) { - *error_msg = "Could not create the oat dir " + dir + ":" + strerror(errno); - return false; - } - return true; -} - -// Prepares the odex directory for the given dex location. -static bool PrepareOdexDirectories(const std::string& dex_location, - const std::string& expected_odex_location, - InstructionSet isa, - std::string* error_msg) { - std::string actual_odex_location; - std::string oat_dir; - std::string isa_dir; - if (!DexLocationToOdexNames( - dex_location, isa, &actual_odex_location, &oat_dir, &isa_dir, error_msg)) { - return false; - } - DCHECK_EQ(expected_odex_location, actual_odex_location); - - if (!PrepareDirectory(oat_dir, error_msg)) { - return false; - } - if (!PrepareDirectory(isa_dir, error_msg)) { - return false; - } - return true; -} - -class Dex2oatFileWrapper { - public: - explicit Dex2oatFileWrapper(File* file) - : file_(file), - unlink_file_at_destruction_(true) { - } - - ~Dex2oatFileWrapper() { - if (unlink_file_at_destruction_ && (file_ != nullptr)) { - file_->Erase(/*unlink*/ true); - } - } - - File* GetFile() { return file_.get(); } - - void DisableUnlinkAtDestruction() { - unlink_file_at_destruction_ = false; - } - - private: - std::unique_ptr<File> file_; - bool unlink_file_at_destruction_; -}; - -OatFileAssistant::ResultOfAttemptToUpdate OatFileAssistant::GenerateOatFileNoChecks( - OatFileAssistant::OatFileInfo& info, - CompilerFilter::Filter filter, - const ClassLoaderContext* class_loader_context, - std::string* error_msg) { - CHECK(error_msg != nullptr); - - Runtime* runtime = Runtime::Current(); - if (!runtime->IsDex2OatEnabled()) { - *error_msg = "Generation of oat file for dex location " + dex_location_ - + " not attempted because dex2oat is disabled."; - return kUpdateNotAttempted; - } - - if (info.Filename() == nullptr) { - *error_msg = "Generation of oat file for dex location " + dex_location_ - + " not attempted because the oat file name could not be determined."; - return kUpdateNotAttempted; - } - const std::string& oat_file_name = *info.Filename(); - const std::string& vdex_file_name = GetVdexFilename(oat_file_name); - - // dex2oat ignores missing dex files and doesn't report an error. - // Check explicitly here so we can detect the error properly. - // TODO: Why does dex2oat behave that way? - struct stat dex_path_stat; - if (TEMP_FAILURE_RETRY(stat(dex_location_.c_str(), &dex_path_stat)) != 0) { - *error_msg = "Could not access dex location " + dex_location_ + ":" + strerror(errno); - return kUpdateNotAttempted; - } - - // If this is the odex location, we need to create the odex file layout (../oat/isa/..) - if (!info.IsOatLocation()) { - if (!PrepareOdexDirectories(dex_location_, oat_file_name, isa_, error_msg)) { - return kUpdateNotAttempted; - } - } - - // Set the permissions for the oat and the vdex files. - // The user always gets read and write while the group and others propagate - // the reading access of the original dex file. - mode_t file_mode = S_IRUSR | S_IWUSR | - (dex_path_stat.st_mode & S_IRGRP) | - (dex_path_stat.st_mode & S_IROTH); - - Dex2oatFileWrapper vdex_file_wrapper(OS::CreateEmptyFile(vdex_file_name.c_str())); - File* vdex_file = vdex_file_wrapper.GetFile(); - if (vdex_file == nullptr) { - *error_msg = "Generation of oat file " + oat_file_name - + " not attempted because the vdex file " + vdex_file_name - + " could not be opened."; - return kUpdateNotAttempted; - } - - if (fchmod(vdex_file->Fd(), file_mode) != 0) { - *error_msg = "Generation of oat file " + oat_file_name - + " not attempted because the vdex file " + vdex_file_name - + " could not be made world readable."; - return kUpdateNotAttempted; - } - - Dex2oatFileWrapper oat_file_wrapper(OS::CreateEmptyFile(oat_file_name.c_str())); - File* oat_file = oat_file_wrapper.GetFile(); - if (oat_file == nullptr) { - *error_msg = "Generation of oat file " + oat_file_name - + " not attempted because the oat file could not be created."; - return kUpdateNotAttempted; - } - - if (fchmod(oat_file->Fd(), file_mode) != 0) { - *error_msg = "Generation of oat file " + oat_file_name - + " not attempted because the oat file could not be made world readable."; - return kUpdateNotAttempted; - } - - std::vector<std::string> args; - args.push_back("--dex-file=" + dex_location_); - args.push_back("--output-vdex-fd=" + std::to_string(vdex_file->Fd())); - args.push_back("--oat-fd=" + std::to_string(oat_file->Fd())); - args.push_back("--oat-location=" + oat_file_name); - args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter)); - const std::string dex2oat_context = class_loader_context == nullptr - ? OatFile::kSpecialSharedLibrary - : class_loader_context->EncodeContextForDex2oat(/*base_dir*/ ""); - args.push_back("--class-loader-context=" + dex2oat_context); - - if (!Dex2Oat(args, error_msg)) { - return kUpdateFailed; - } - - if (vdex_file->FlushCloseOrErase() != 0) { - *error_msg = "Unable to close vdex file " + vdex_file_name; - return kUpdateFailed; - } - - if (oat_file->FlushCloseOrErase() != 0) { - *error_msg = "Unable to close oat file " + oat_file_name; - return kUpdateFailed; - } - - // Mark that the odex file has changed and we should try to reload. - info.Reset(); - // We have compiled successfully. Disable the auto-unlink. - vdex_file_wrapper.DisableUnlinkAtDestruction(); - oat_file_wrapper.DisableUnlinkAtDestruction(); - - return kUpdateSucceeded; -} - -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()); - if (runtime->IsJavaDebuggable()) { - argv.push_back("--debuggable"); - } - runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv); - - if (!runtime->IsVerificationEnabled()) { - argv.push_back("--compiler-filter=verify-none"); - } - - if (runtime->GetHiddenApiEnforcementPolicy() != hiddenapi::EnforcementPolicy::kNoChecks) { - argv.push_back("--runtime-arg"); - argv.push_back("-Xhidden-api-checks"); - } - - 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); -} - bool OatFileAssistant::DexLocationToOdexFilename(const std::string& location, InstructionSet isa, std::string* odex_filename, @@ -885,16 +561,6 @@ bool OatFileAssistant::DexLocationToOatFilename(const std::string& location, return GetDalvikCacheFilename(location.c_str(), cache_dir.c_str(), oat_filename, error_msg); } -std::string OatFileAssistant::ImageLocation() { - Runtime* runtime = Runtime::Current(); - const std::vector<gc::space::ImageSpace*>& image_spaces = - runtime->GetHeap()->GetBootImageSpaces(); - if (image_spaces.empty()) { - return ""; - } - return image_spaces[0]->GetImageLocation(); -} - const std::vector<uint32_t>* OatFileAssistant::GetRequiredDexChecksums() { if (!required_dex_checksums_attempted_) { required_dex_checksums_attempted_ = true; |