Do not execute OAT files that require app images that cannot be loaded
This change creates a new requires-image flag in the OAT header, which
is set when the file was created with an image (app image, etc.). If
this flag is set, we will not load the OAT file as executable if the
image could not be loaded.
Going forward, this allows the compiler to assume there will be an app
image when an app image is generated and in some cases generate better
code.
Note that we still must load the OAT file, because there will not always
be another way to access the underlying DEX files.
Revert submission 1298633-revert-155218105
Reason for revert: Fixing tests and relanding
Reverted Changes:
I701c91d5b:Revert "Disable ART run-test 2231-oat-require-app-...
Ic5cda4c75:Revert "Reject OAT file in speed-profile if app im...
Bug: 38313278
Test: m test-art-host-gtest-oat_file_assistant_test64
Test: atest android.server.wm.MultiDisplaySecurityTests#testDisplayHasAccess_UIDCanPresentOnPrivateDisplay android.classloaders.cts.UsesLibraryHostTest#testUsesLibrary_full
Change-Id: I52cca033fa8e2e6de86514c833798c3d99b99477
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index ed47ca3..7b1a5eb 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -1437,6 +1437,7 @@
TEST_F(OatFileAssistantTest, GetDexLocation) {
std::string dex_location = GetScratchDir() + "/TestDex.jar";
std::string oat_location = GetOdexDir() + "/TestDex.odex";
+ std::string art_location = GetOdexDir() + "/TestDex.art";
// Start the runtime to initialize the system's class loader.
Thread::Current()->TransitionFromSuspendedToRunnable();
@@ -1463,6 +1464,7 @@
args.push_back("--dex-file=" + dex_location);
args.push_back("--dex-location=TestDex.jar");
args.push_back("--oat-file=" + oat_location);
+ args.push_back("--app-image-file=" + art_location);
std::string error_msg;
ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
}
@@ -1490,6 +1492,7 @@
odex_dir = odex_dir + std::string(GetInstructionSetString(kRuntimeISA));
mkdir(odex_dir.c_str(), 0700);
std::string oat_location = odex_dir + "/" + filebase + ".odex";
+ std::string art_location = odex_dir + "/" + filebase + ".art";
// Clean up in case previous run crashed.
remove(oat_location.c_str());
@@ -1527,6 +1530,7 @@
args.push_back("--dex-file=" + dex_location);
args.push_back("--dex-location=" + filebase + ".jar");
args.push_back("--oat-file=" + oat_location);
+ args.push_back("--app-image-file=" + art_location);
std::string error_msg;
ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
}
@@ -1554,6 +1558,41 @@
EXPECT_EQ(0, remove(oat_location.c_str()));
}
+// Make sure OAT files that require app images are not loaded as executable.
+TEST_F(OatFileAssistantTest, LoadOatNoArt) {
+ std::string dex_location = GetScratchDir() + "/TestDex.jar";
+ std::string odex_location = GetOdexDir() + "/TestDex.odex";
+ std::string art_location = GetOdexDir() + "/TestDex.art";
+ Copy(GetDexSrc1(), dex_location);
+ GenerateOdexForTest(dex_location,
+ odex_location,
+ CompilerFilter::kSpeed,
+ "install",
+ {
+ "--app-image-file=" + art_location,
+ });
+
+ unlink(art_location.c_str());
+
+ std::vector<std::string> error_msgs;
+ const OatFile* oat_file = nullptr;
+
+ // Start the runtime to initialize the system's class loader.
+ Thread::Current()->TransitionFromSuspendedToRunnable();
+ runtime_->Start();
+
+ const auto dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
+ dex_location.c_str(),
+ Runtime::Current()->GetSystemClassLoader(),
+ /*dex_elements=*/nullptr,
+ &oat_file,
+ &error_msgs);
+
+ EXPECT_FALSE(dex_files.empty());
+ EXPECT_NE(oat_file, nullptr);
+ EXPECT_FALSE(oat_file->IsExecutable());
+}
+
// TODO: More Tests:
// * Test class linker falls back to unquickened dex for DexNoOat
// * Test class linker falls back to unquickened dex for MultiDexNoOat