Fail dex2oat when generating app image without boot image.
When the boot image is unavailable, an app image or a boot image
extension cannot be generated. Before this change, dex2oat crashes at
`CHECK_NE(image_begin, 0U)` in `ImageWriter`. After this change, dex2oat
returns early with a user friendly error message.
Bug: 211973309
Bug: 215665835
Test: atest art_standalone_dex2oat_tests
Change-Id: Ic6ca2cdade08b8f7c7ae4d06fc52aedafd71beab
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 2d78590..154b1ca 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1502,6 +1502,13 @@
if (!CreateRuntime(std::move(runtime_options))) {
return dex2oat::ReturnCode::kCreateRuntime;
}
+ if (runtime_->GetHeap()->GetBootImageSpaces().empty() &&
+ (IsBootImageExtension() || IsAppImage())) {
+ LOG(ERROR) << "Cannot create "
+ << (IsBootImageExtension() ? "boot image extension" : "app image")
+ << " without a primary boot image.";
+ return dex2oat::ReturnCode::kOther;
+ }
ArrayRef<const DexFile* const> bcp_dex_files(runtime_->GetClassLinker()->GetBootClassPath());
if (IsBootImage() || IsBootImageExtension()) {
// Check boot class path dex files and, if compiling an extension, the images it depends on.
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index b340c80..7b6440f 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -872,6 +872,21 @@
RunTest(/*app_image=*/ true);
}
+TEST_F(Dex2oatLayoutTest, TestLayoutAppImageMissingBootImage) {
+ std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
+ std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
+ std::string app_image_file = GetOdexDir() + "/DexOdexNoOat.art";
+ Copy(GetDexSrc2(), dex_location);
+
+ CompileProfileOdex(dex_location,
+ odex_location,
+ app_image_file,
+ /*use_fd=*/ false,
+ /*num_profile_classes=*/ 1,
+ /*extra_args=*/ {"--boot-image=/nonx/boot.art"},
+ /*expect_success=*/ false);
+}
+
TEST_F(Dex2oatLayoutTest, TestLayoutMultipleProfiles) {
std::string dex_location = GetScratchDir() + "/Dex.jar";
std::string odex_location = GetOdexDir() + "/Dex.odex";