summaryrefslogtreecommitdiff
path: root/runtime/oat_file_assistant.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/oat_file_assistant.cc')
-rw-r--r--runtime/oat_file_assistant.cc334
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;