Revert^3 "Boot image extension."
This reverts commit 02820f424714e711bbd4cb4b04a109416eb0c8b8.
Also reverts commit beb66b38dcce937d7eee9ef2d07b6402c720f8ee
that contained a follow-up fix.
Reason for revert: b/144001974
Bug: 119800099
Bug: 143492855
Bug: 144001974
Change-Id: I4da5330c3efa9f0c3508e85344c031d3b360ca0a
diff --git a/CleanSpec.mk b/CleanSpec.mk
index a094a24..671bdb2 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -99,6 +99,7 @@
# Remove dex2oat artifacts for boot image extensions (workaround for broken dependencies).
$(call add-clean-step, find $(OUT_DIR) -name "*.oat" -o -name "*.odex" -o -name "*.art" -o -name '*.vdex' | xargs rm -f)
+$(call add-clean-step, find $(OUT_DIR) -name "*.oat" -o -name "*.odex" -o -name "*.art" -o -name '*.vdex' | xargs rm -f)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index 7c3e791..c29cd29 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -63,7 +63,6 @@
$$(error found $(1) expected interpreter, interp-ac, or optimizing)
endif
- core_image_location := $(HOST_OUT_JAVA_LIBRARIES)/core$$(core_infix)$(CORE_IMG_SUFFIX)
core_image_name := $($(2)HOST_CORE_IMG_OUT_BASE)$$(core_infix)$(CORE_IMG_SUFFIX)
core_oat_name := $($(2)HOST_CORE_OAT_OUT_BASE)$$(core_infix)$(CORE_OAT_SUFFIX)
@@ -77,46 +76,18 @@
HOST_CORE_OAT_OUTS += $$(core_oat_name)
$$(core_image_name): PRIVATE_CORE_COMPILE_OPTIONS := $$(core_compile_options)
-$$(core_image_name): PRIVATE_CORE_IMAGE_LOCATION := $$(core_image_location)
$$(core_image_name): PRIVATE_CORE_IMG_NAME := $$(core_image_name)
$$(core_image_name): PRIVATE_CORE_OAT_NAME := $$(core_oat_name)
-# In addition to the primary core image containing HOST_CORE_IMG_DEX_FILES,
-# also build a boot image extension for the remaining HOST_CORE_DEX_FILES.
-$$(core_image_name): $$(HOST_CORE_DEX_LOCATIONS) $$(core_dex2oat_dependency)
+$$(core_image_name): $$(HOST_CORE_IMG_DEX_LOCATIONS) $$(core_dex2oat_dependency)
@echo "host dex2oat: $$@"
@mkdir -p $$(dir $$@)
- $$(hide) ANDROID_LOG_TAGS="*:e" $$(DEX2OAT) \
- --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
+ $$(hide) ANDROID_LOG_TAGS="*:e" $$(DEX2OAT) --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
--runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
$$(addprefix --dex-file=,$$(HOST_CORE_IMG_DEX_FILES)) \
$$(addprefix --dex-location=,$$(HOST_CORE_IMG_DEX_LOCATIONS)) \
--oat-file=$$(PRIVATE_CORE_OAT_NAME) \
- --oat-location=$$(PRIVATE_CORE_OAT_NAME) \
- --image=$$(PRIVATE_CORE_IMG_NAME) \
- --base=$$(LIBART_IMG_HOST_BASE_ADDRESS) \
- --instruction-set=$$($(2)ART_HOST_ARCH) \
- $$(LOCAL_$(2)DEX2OAT_HOST_INSTRUCTION_SET_FEATURES_OPTION) \
- --host --android-root=$$(HOST_OUT) \
- --generate-debug-info --generate-build-id \
- --runtime-arg -XX:SlowDebug=true \
- --no-inline-from=core-oj-hostdex.jar \
- $$(PRIVATE_CORE_COMPILE_OPTIONS) && \
- ANDROID_LOG_TAGS="*:e" $$(DEX2OAT) \
- --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
- --runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
- --runtime-arg -Xbootclasspath:$$(subst $$(space),:,$$(strip \
- $$(HOST_CORE_DEX_FILES))) \
- --runtime-arg -Xbootclasspath-locations:$$(subst $$(space),:,$$(strip \
- $$(HOST_CORE_DEX_LOCATIONS))) \
- $$(addprefix --dex-file=, \
- $$(filter-out $$(HOST_CORE_IMG_DEX_FILES),$$(HOST_CORE_DEX_FILES))) \
- $$(addprefix --dex-location=, \
- $$(filter-out $$(HOST_CORE_IMG_DEX_LOCATIONS),$$(HOST_CORE_DEX_LOCATIONS))) \
- --oat-file=$$(PRIVATE_CORE_OAT_NAME) \
- --oat-location=$$(PRIVATE_CORE_OAT_NAME) \
- --boot-image=$$(PRIVATE_CORE_IMAGE_LOCATION) \
- --image=$$(PRIVATE_CORE_IMG_NAME) \
- --instruction-set=$$($(2)ART_HOST_ARCH) \
+ --oat-location=$$(PRIVATE_CORE_OAT_NAME) --image=$$(PRIVATE_CORE_IMG_NAME) \
+ --base=$$(LIBART_IMG_HOST_BASE_ADDRESS) --instruction-set=$$($(2)ART_HOST_ARCH) \
$$(LOCAL_$(2)DEX2OAT_HOST_INSTRUCTION_SET_FEATURES_OPTION) \
--host --android-root=$$(HOST_OUT) \
--generate-debug-info --generate-build-id \
@@ -178,7 +149,6 @@
$$(error found $(1) expected interpreter, interp-ac, or optimizing)
endif
- core_image_location := $(ART_TARGET_TEST_OUT)/core$$(core_infix)$(CORE_IMG_SUFFIX)
core_image_name := $($(2)TARGET_CORE_IMG_OUT_BASE)$$(core_infix)$(CORE_IMG_SUFFIX)
core_oat_name := $($(2)TARGET_CORE_OAT_OUT_BASE)$$(core_infix)$(CORE_OAT_SUFFIX)
@@ -196,53 +166,24 @@
TARGET_CORE_OAT_OUTS += $$(core_oat_name)
$$(core_image_name): PRIVATE_CORE_COMPILE_OPTIONS := $$(core_compile_options)
-$$(core_image_name): PRIVATE_CORE_IMAGE_LOCATION := $$(core_image_location)
$$(core_image_name): PRIVATE_CORE_IMG_NAME := $$(core_image_name)
$$(core_image_name): PRIVATE_CORE_OAT_NAME := $$(core_oat_name)
-# In addition to the primary core image containing TARGET_CORE_IMG_DEX_FILES,
-# also build a boot image extension for the remaining TARGET_CORE_DEX_FILES.
-$$(core_image_name): $$(TARGET_CORE_DEX_FILES) $$(core_dex2oat_dependency)
+$$(core_image_name): $$(TARGET_CORE_IMG_DEX_FILES) $$(core_dex2oat_dependency)
@echo "target dex2oat: $$@"
@mkdir -p $$(dir $$@)
- $$(hide) $$(DEX2OAT) \
- --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
+ $$(hide) $$(DEX2OAT) --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
--runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
$$(addprefix --dex-file=,$$(TARGET_CORE_IMG_DEX_FILES)) \
$$(addprefix --dex-location=,$$(TARGET_CORE_IMG_DEX_LOCATIONS)) \
--oat-file=$$(PRIVATE_CORE_OAT_NAME) \
- --oat-location=$$(PRIVATE_CORE_OAT_NAME) \
- --image=$$(PRIVATE_CORE_IMG_NAME) \
- --base=$$(LIBART_IMG_TARGET_BASE_ADDRESS) \
- --instruction-set=$$($(2)TARGET_ARCH) \
+ --oat-location=$$(PRIVATE_CORE_OAT_NAME) --image=$$(PRIVATE_CORE_IMG_NAME) \
+ --base=$$(LIBART_IMG_TARGET_BASE_ADDRESS) --instruction-set=$$($(2)TARGET_ARCH) \
--instruction-set-variant=$$($(2)DEX2OAT_TARGET_CPU_VARIANT) \
--instruction-set-features=$$($(2)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) \
--android-root=$$(PRODUCT_OUT)/system \
--generate-debug-info --generate-build-id \
--runtime-arg -XX:SlowDebug=true \
- $$(PRIVATE_CORE_COMPILE_OPTIONS) && \
- $$(DEX2OAT) \
- --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
- --runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
- --runtime-arg -Xbootclasspath:$$(subst $$(space),:,$$(strip \
- $$(TARGET_CORE_DEX_FILES))) \
- --runtime-arg -Xbootclasspath-locations:$$(subst $$(space),:,$$(strip \
- $$(TARGET_CORE_DEX_LOCATIONS))) \
- $$(addprefix --dex-file=, \
- $$(filter-out $$(TARGET_CORE_IMG_DEX_FILES),$$(TARGET_CORE_DEX_FILES))) \
- $$(addprefix --dex-location=, \
- $$(filter-out $$(TARGET_CORE_IMG_DEX_LOCATIONS),$$(TARGET_CORE_DEX_LOCATIONS))) \
- --oat-file=$$(PRIVATE_CORE_OAT_NAME) \
- --oat-location=$$(PRIVATE_CORE_OAT_NAME) \
- --boot-image=$$(PRIVATE_CORE_IMAGE_LOCATION) \
- --image=$$(PRIVATE_CORE_IMG_NAME) \
- --instruction-set=$$($(2)TARGET_ARCH) \
- --instruction-set-variant=$$($(2)DEX2OAT_TARGET_CPU_VARIANT) \
- --instruction-set-features=$$($(2)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) \
- --android-root=$$(PRODUCT_OUT)/system \
- --generate-debug-info --generate-build-id \
- --runtime-arg -XX:SlowDebug=true \
- $$(PRIVATE_CORE_COMPILE_OPTIONS) || \
- (rm $$(PRIVATE_CORE_OAT_NAME); exit 1)
+ $$(PRIVATE_CORE_COMPILE_OPTIONS) || (rm $$(PRIVATE_CORE_OAT_NAME); exit 1)
$$(core_oat_name): $$(core_image_name)
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index feda8ba..8e642e5 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -63,7 +63,6 @@
#include "debug/method_debug_info.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
-#include "dex/dex_file_loader.h"
#include "dex/quick_compiler_callbacks.h"
#include "dex/verification_results.h"
#include "dex2oat_options.h"
@@ -281,14 +280,6 @@
UsageError(" Do not include the arch as part of the name, it is added automatically.");
UsageError(" Example: --boot-image=/system/framework/boot.art");
UsageError(" (specifies /system/framework/<arch>/boot.art as the image file)");
- UsageError(" Example: --boot-image=boot.art:boot-framework.art");
- UsageError(" (specifies <bcp-path1>/<arch>/boot.art as the image file and");
- UsageError(" <bcp-path2>/<arch>/boot-framework.art as the image extension file");
- UsageError(" with paths taken from corresponding boot class path components)");
- UsageError(" Example: --boot-image=/apex/com.android.art/boot.art:/system/framework/*:*");
- UsageError(" (specifies /apex/com.android.art/<arch>/boot.art as the image");
- UsageError(" file and search for extensions in /framework/system and boot");
- UsageError(" class path components' paths)");
UsageError(" Default: $ANDROID_ROOT/system/framework/boot.art");
UsageError("");
UsageError(" --android-root=<path>: used to locate libraries for portable linking.");
@@ -761,31 +752,16 @@
void ProcessOptions(ParserOptions* parser_options) {
compiler_options_->compile_pic_ = true; // All AOT compilation is PIC.
-
- if (android_root_.empty()) {
- const char* android_root_env_var = getenv("ANDROID_ROOT");
- if (android_root_env_var == nullptr) {
- Usage("--android-root unspecified and ANDROID_ROOT not set");
- }
- android_root_ += android_root_env_var;
- }
-
- if (!parser_options->boot_image_filename.empty()) {
- boot_image_filename_ = parser_options->boot_image_filename;
- }
-
DCHECK(compiler_options_->image_type_ == CompilerOptions::ImageType::kNone);
if (!image_filenames_.empty()) {
- if (!boot_image_filename_.empty()) {
- compiler_options_->image_type_ = CompilerOptions::ImageType::kBootImageExtension;
- } else if (android::base::EndsWith(image_filenames_[0], "apex.art")) {
+ if (android::base::EndsWith(image_filenames_[0], "apex.art")) {
compiler_options_->image_type_ = CompilerOptions::ImageType::kApexBootImage;
} else {
compiler_options_->image_type_ = CompilerOptions::ImageType::kBootImage;
}
}
if (app_image_fd_ != -1 || !app_image_file_name_.empty()) {
- if (compiler_options_->IsBootImage() || compiler_options_->IsBootImageExtension()) {
+ if (compiler_options_->IsBootImage()) {
Usage("Can't have both --image and (--app-image-fd or --app-image-file)");
}
compiler_options_->image_type_ = CompilerOptions::ImageType::kAppImage;
@@ -842,9 +818,19 @@
Usage("--oat-file arguments do not match --image arguments");
}
- if (!IsBootImage() && boot_image_filename_.empty()) {
- DCHECK(!IsBootImageExtension());
- boot_image_filename_ = GetDefaultBootImageLocation(android_root_);
+ if (android_root_.empty()) {
+ const char* android_root_env_var = getenv("ANDROID_ROOT");
+ if (android_root_env_var == nullptr) {
+ Usage("--android-root unspecified and ANDROID_ROOT not set");
+ }
+ android_root_ += android_root_env_var;
+ }
+
+ if (!IsBootImage() && parser_options->boot_image_filename.empty()) {
+ parser_options->boot_image_filename = GetDefaultBootImageLocation(android_root_);
+ }
+ if (!parser_options->boot_image_filename.empty()) {
+ boot_image_filename_ = parser_options->boot_image_filename;
}
if (dex_filenames_.empty() && zip_fd_ == -1) {
@@ -951,8 +937,8 @@
// Fill some values into the key-value store for the oat header.
key_value_store_.reset(new SafeMap<std::string, std::string>());
- // Automatically force determinism for the boot image and boot image extensions in a host build.
- if (!kIsTargetBuild && (IsBootImage() || IsBootImageExtension())) {
+ // Automatically force determinism for the boot image in a host build.
+ if (!kIsTargetBuild && IsBootImage()) {
force_determinism_ = true;
}
compiler_options_->force_determinism_ = force_determinism_;
@@ -975,21 +961,18 @@
if (image_filenames_[0].rfind('/') == std::string::npos) {
Usage("Unusable boot image filename %s", image_filenames_[0].c_str());
}
- image_filenames_ = ImageSpace::ExpandMultiImageLocations(
- ArrayRef<const std::string>(dex_locations_), image_filenames_[0], IsBootImageExtension());
+ image_filenames_ = ImageSpace::ExpandMultiImageLocations(dex_locations_, image_filenames_[0]);
if (oat_filenames_[0].rfind('/') == std::string::npos) {
Usage("Unusable boot image oat filename %s", oat_filenames_[0].c_str());
}
- oat_filenames_ = ImageSpace::ExpandMultiImageLocations(
- ArrayRef<const std::string>(dex_locations_), oat_filenames_[0], IsBootImageExtension());
+ oat_filenames_ = ImageSpace::ExpandMultiImageLocations(dex_locations_, oat_filenames_[0]);
if (!oat_unstripped_.empty()) {
if (oat_unstripped_[0].rfind('/') == std::string::npos) {
Usage("Unusable boot image symbol filename %s", oat_unstripped_[0].c_str());
}
- oat_unstripped_ = ImageSpace::ExpandMultiImageLocations(
- ArrayRef<const std::string>(dex_locations_), oat_unstripped_[0], IsBootImageExtension());
+ oat_unstripped_ = ImageSpace::ExpandMultiImageLocations(dex_locations_, oat_unstripped_[0]);
}
}
@@ -1221,13 +1204,9 @@
bool OpenFile() {
// Prune non-existent dex files now so that we don't create empty oat files for multi-image.
PruneNonExistentDexFiles();
- if (dex_locations_.empty()) {
- LOG(ERROR) << "Nothing to compile after pruning non-existent dex files.";
- return false;
- }
// Expand oat and image filenames for multi image.
- if ((IsBootImage() || IsBootImageExtension()) && image_filenames_.size() == 1) {
+ if (IsBootImage() && image_filenames_.size() == 1) {
ExpandOatAndImageFilenames();
}
@@ -1452,13 +1431,12 @@
return dex2oat::ReturnCode::kOther;
}
- // Verification results are null since we don't know if we will need them yet as the compiler
+ // Verification results are null since we don't know if we will need them yet as the compler
// filter may change.
callbacks_.reset(new QuickCompilerCallbacks(
- // For class verification purposes, boot image extension is the same as boot image.
- (IsBootImage() || IsBootImageExtension())
- ? CompilerCallbacks::CallbackMode::kCompileBootImage
- : CompilerCallbacks::CallbackMode::kCompileApp));
+ IsBootImage() ?
+ CompilerCallbacks::CallbackMode::kCompileBootImage :
+ CompilerCallbacks::CallbackMode::kCompileApp));
RuntimeArgumentMap runtime_options;
if (!PrepareRuntimeOptions(&runtime_options, callbacks_.get())) {
@@ -1511,7 +1489,7 @@
// store which is used for determining whether the oat file is up to date,
// together with the boot class path locations and checksums stored below.
CompilerFilter::Filter original_compiler_filter = compiler_options_->GetCompilerFilter();
- if (!IsBootImage() && !IsBootImageExtension() && IsVeryLarge(dex_files)) {
+ if (!IsBootImage() && IsVeryLarge(dex_files)) {
// Disable app image to make sure dex2oat unloading is enabled.
compiler_options_->image_type_ = CompilerOptions::ImageType::kNone;
@@ -1534,64 +1512,14 @@
callbacks_->SetVerificationResults(verification_results_.get());
}
- if (IsBootImage() || IsBootImageExtension()) {
- // For boot image or boot image extension, pass opened dex files to the Runtime::Create().
+ if (IsBootImage()) {
+ // For boot image, pass opened dex files to the Runtime::Create().
// Note: Runtime acquires ownership of these dex files.
runtime_options.Set(RuntimeArgumentMap::BootClassPathDexList, &opened_dex_files_);
}
if (!CreateRuntime(std::move(runtime_options))) {
return dex2oat::ReturnCode::kCreateRuntime;
}
- 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.
- if ((IsBootImage() && bcp_dex_files.size() != dex_files.size()) ||
- (IsBootImageExtension() && bcp_dex_files.size() <= dex_files.size())) {
- LOG(ERROR) << "Unexpected number of boot class path dex files for boot image or extension, "
- << bcp_dex_files.size() << (IsBootImage() ? " != " : " <= ") << dex_files.size();
- return dex2oat::ReturnCode::kOther;
- }
- if (!std::equal(dex_files.begin(), dex_files.end(), bcp_dex_files.end() - dex_files.size())) {
- LOG(ERROR) << "Boot class path dex files do not end with the compiled dex files.";
- return dex2oat::ReturnCode::kOther;
- }
- size_t bcp_df_pos = 0u;
- size_t bcp_df_end = bcp_dex_files.size();
- for (const std::string& bcp_location : runtime_->GetBootClassPathLocations()) {
- if (bcp_df_pos == bcp_df_end || bcp_dex_files[bcp_df_pos]->GetLocation() != bcp_location) {
- LOG(ERROR) << "Missing dex file for boot class component " << bcp_location;
- return dex2oat::ReturnCode::kOther;
- }
- CHECK(!DexFileLoader::IsMultiDexLocation(bcp_dex_files[bcp_df_pos]->GetLocation().c_str()));
- ++bcp_df_pos;
- while (bcp_df_pos != bcp_df_end &&
- DexFileLoader::IsMultiDexLocation(bcp_dex_files[bcp_df_pos]->GetLocation().c_str())) {
- ++bcp_df_pos;
- }
- }
- if (bcp_df_pos != bcp_df_end) {
- LOG(ERROR) << "Unexpected dex file in boot class path "
- << bcp_dex_files[bcp_df_pos]->GetLocation();
- return dex2oat::ReturnCode::kOther;
- }
- auto lacks_image = [](const DexFile* df) {
- if (kIsDebugBuild && df->GetOatDexFile() != nullptr) {
- const OatFile* oat_file = df->GetOatDexFile()->GetOatFile();
- CHECK(oat_file != nullptr);
- const auto& image_spaces = Runtime::Current()->GetHeap()->GetBootImageSpaces();
- CHECK(std::any_of(image_spaces.begin(),
- image_spaces.end(),
- [=](const ImageSpace* space) {
- return oat_file == space->GetOatFile();
- }));
- }
- return df->GetOatDexFile() == nullptr;
- };
- if (std::any_of(bcp_dex_files.begin(), bcp_dex_files.end() - dex_files.size(), lacks_image)) {
- LOG(ERROR) << "Missing required boot image(s) for boot image extension.";
- return dex2oat::ReturnCode::kOther;
- }
- }
if (!compilation_reason_.empty()) {
key_value_store_->Put(OatHeader::kCompilationReasonKey, compilation_reason_);
@@ -1601,32 +1529,17 @@
// If we're compiling the boot image, store the boot classpath into the Key-Value store.
// We use this when loading the boot image.
key_value_store_->Put(OatHeader::kBootClassPathKey, android::base::Join(dex_locations_, ':'));
- } else if (IsBootImageExtension()) {
- // Validate the boot class path and record the dependency on the loaded boot images.
- TimingLogger::ScopedTiming t3("Loading image checksum", timings_);
- Runtime* runtime = Runtime::Current();
- std::string full_bcp = android::base::Join(runtime->GetBootClassPathLocations(), ':');
- std::string extension_part = ":" + android::base::Join(dex_locations_, ':');
- if (!android::base::EndsWith(full_bcp, extension_part)) {
- LOG(ERROR) << "Full boot class path does not end with extension parts, full: " << full_bcp
- << ", extension: " << extension_part.substr(1u);
- return dex2oat::ReturnCode::kOther;
- }
- std::string bcp_dependency = full_bcp.substr(0u, full_bcp.size() - extension_part.size());
- key_value_store_->Put(OatHeader::kBootClassPathKey, bcp_dependency);
- ArrayRef<const DexFile* const> bcp_dex_files_dependency =
- bcp_dex_files.SubArray(/*pos=*/ 0u, bcp_dex_files.size() - dex_files.size());
- ArrayRef<ImageSpace* const> image_spaces(runtime->GetHeap()->GetBootImageSpaces());
- key_value_store_->Put(
- OatHeader::kBootClassPathChecksumsKey,
- gc::space::ImageSpace::GetBootClassPathChecksums(image_spaces, bcp_dex_files_dependency));
- } else {
+ }
+
+ if (!IsBootImage()) {
if (CompilerFilter::DependsOnImageChecksum(original_compiler_filter)) {
TimingLogger::ScopedTiming t3("Loading image checksum", timings_);
Runtime* runtime = Runtime::Current();
key_value_store_->Put(OatHeader::kBootClassPathKey,
android::base::Join(runtime->GetBootClassPathLocations(), ':'));
ArrayRef<ImageSpace* const> image_spaces(runtime->GetHeap()->GetBootImageSpaces());
+ ArrayRef<const DexFile* const> bcp_dex_files(
+ runtime->GetClassLinker()->GetBootClassPath());
key_value_store_->Put(
OatHeader::kBootClassPathChecksumsKey,
gc::space::ImageSpace::GetBootClassPathChecksums(image_spaces, bcp_dex_files));
@@ -1694,7 +1607,7 @@
CHECK(driver_ == nullptr);
// If we use a swap file, ensure we are above the threshold to make it necessary.
if (swap_fd_ != -1) {
- if (!UseSwap(IsBootImage() || IsBootImageExtension(), dex_files)) {
+ if (!UseSwap(IsBootImage(), dex_files)) {
close(swap_fd_);
swap_fd_ = -1;
VLOG(compiler) << "Decided to run without swap.";
@@ -1711,7 +1624,7 @@
Thread* self = Thread::Current();
WellKnownClasses::Init(self->GetJniEnv());
- if (!IsBootImage() && !IsBootImageExtension()) {
+ if (!IsBootImage()) {
constexpr bool kSaveDexInput = false;
if (kSaveDexInput) {
SaveDexInput();
@@ -1800,7 +1713,7 @@
if (!no_inline_filters.empty()) {
std::vector<const DexFile*> class_path_files;
- if (!IsBootImage() && !IsBootImageExtension()) {
+ if (!IsBootImage()) {
// The class loader context is used only for apps.
class_path_files = class_loader_context_->FlattenOpenedDexFiles();
}
@@ -1845,7 +1758,7 @@
compiler_kind_,
thread_count_,
swap_fd_));
- if (!IsBootImage() && !IsBootImageExtension()) {
+ if (!IsBootImage()) {
driver_->SetClasspathDexFiles(class_loader_context_->FlattenOpenedDexFiles());
}
@@ -1893,7 +1806,7 @@
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
jobject class_loader = nullptr;
- if (!IsBootImage() && !IsBootImageExtension()) {
+ if (!IsBootImage()) {
class_loader =
class_loader_context_->CreateClassLoader(compiler_options_->dex_files_for_oat_file_);
callbacks_->SetDexFiles(&dex_files);
@@ -2037,7 +1950,7 @@
{
TimingLogger::ScopedTiming t2("dex2oat Write VDEX", timings_);
- DCHECK(IsBootImage() || IsBootImageExtension() || oat_files_.size() == 1u);
+ DCHECK(IsBootImage() || oat_files_.size() == 1u);
verifier::VerifierDeps* verifier_deps = callbacks_->GetVerifierDeps();
for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
File* vdex_file = vdex_files_[i].get();
@@ -2261,7 +2174,7 @@
}
bool IsImage() const {
- return IsAppImage() || IsBootImage() || IsBootImageExtension();
+ return IsAppImage() || IsBootImage();
}
bool IsAppImage() const {
@@ -2272,10 +2185,6 @@
return compiler_options_->IsBootImage();
}
- bool IsBootImageExtension() const {
- return compiler_options_->IsBootImageExtension();
- }
-
bool IsHost() const {
return is_host_;
}
@@ -2480,7 +2389,7 @@
bool PrepareRuntimeOptions(RuntimeArgumentMap* runtime_options,
QuickCompilerCallbacks* callbacks) {
RuntimeOptions raw_options;
- if (IsBootImage()) {
+ if (boot_image_filename_.empty()) {
std::string boot_class_path = "-Xbootclasspath:";
boot_class_path += android::base::Join(dex_filenames_, ':');
raw_options.push_back(std::make_pair(boot_class_path, nullptr));
@@ -2570,7 +2479,7 @@
bool CreateImageFile()
REQUIRES(!Locks::mutator_lock_) {
CHECK(image_writer_ != nullptr);
- if (!IsBootImage() && !IsBootImageExtension()) {
+ if (!IsBootImage()) {
CHECK(image_filenames_.empty());
image_filenames_.push_back(app_image_file_name_);
}
@@ -2953,10 +2862,7 @@
// 3) Compiling with --host
// 4) Compiling on the host (not a target build)
// Otherwise, print a stripped command line.
- if (kIsDebugBuild ||
- dex2oat->IsBootImage() || dex2oat->IsBootImageExtension() ||
- dex2oat->IsHost() ||
- !kIsTargetBuild) {
+ if (kIsDebugBuild || dex2oat->IsBootImage() || dex2oat->IsHost() || !kIsTargetBuild) {
LOG(INFO) << CommandLine();
} else {
LOG(INFO) << StrippedCommandLine();
diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index fc824c1..d0d5081 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -14,44 +14,31 @@
* limitations under the License.
*/
-#include <fstream>
#include <regex>
#include <sstream>
#include <string>
#include <vector>
-#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
#include "common_runtime_test.h"
-#include "base/array_ref.h"
#include "base/file_utils.h"
#include "base/macros.h"
-#include "base/mem_map.h"
-#include "base/string_view_cpp20.h"
#include "base/unix_file/fd_file.h"
#include "base/utils.h"
#include "dex/art_dex_file_loader.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_loader.h"
#include "dex/method_reference.h"
-#include "gc/space/image_space.h"
#include "profile/profile_compilation_info.h"
#include "runtime.h"
-#include "scoped_thread_state_change-inl.h"
-#include "thread-current-inl.h"
namespace art {
-// A suitable address for loading the core images.
-constexpr uint32_t kBaseAddress = 0x60000000;
-
struct ImageSizes {
size_t art_size = 0;
size_t oat_size = 0;
@@ -145,12 +132,8 @@
scratch_dir.pop_back();
}
CHECK(!scratch_dir.empty()) << "No directory " << scratch.GetFilename();
- std::vector<std::string> libcore_dex_files = GetLibCoreDexFileNames();
- ArrayRef<const std::string> dex_files(libcore_dex_files);
- std::vector<std::string> local_extra_args = extra_args;
- local_extra_args.push_back(android::base::StringPrintf("--base=0x%08x", kBaseAddress));
std::string error_msg;
- if (!CompileBootImage(local_extra_args, scratch.GetFilename(), dex_files, &error_msg)) {
+ if (!CompileBootImage(extra_args, scratch.GetFilename(), &error_msg)) {
LOG(ERROR) << "Failed to compile image " << scratch.GetFilename() << error_msg;
}
std::string art_file = scratch.GetFilename() + ".art";
@@ -168,19 +151,19 @@
scratch.Close();
// Clear image files since we compile the image multiple times and don't want to leave any
// artifacts behind.
- ClearDirectory(scratch_dir.c_str(), /*recursive=*/ false);
+ ClearDirectory(scratch_dir.c_str(), /*recursive*/ false);
return ret;
}
bool CompileBootImage(const std::vector<std::string>& extra_args,
const std::string& image_file_name_prefix,
- ArrayRef<const std::string> dex_files,
std::string* error_msg) {
Runtime* const runtime = Runtime::Current();
std::vector<std::string> argv;
argv.push_back(runtime->GetCompilerExecutable());
AddRuntimeArg(argv, "-Xms64m");
AddRuntimeArg(argv, "-Xmx64m");
+ std::vector<std::string> dex_files = GetLibCoreDexFileNames();
for (const std::string& dex_file : dex_files) {
argv.push_back("--dex-file=" + dex_file);
argv.push_back("--dex-location=" + dex_file);
@@ -199,6 +182,7 @@
argv.push_back("--image=" + image_file_name_prefix + ".art");
argv.push_back("--oat-file=" + image_file_name_prefix + ".oat");
argv.push_back("--oat-location=" + image_file_name_prefix + ".oat");
+ argv.push_back("--base=0x60000000");
std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
@@ -281,266 +265,4 @@
}
}
-TEST_F(Dex2oatImageTest, TestExtension) {
- constexpr size_t kReservationSize = 256 * MB; // This should be enough for the compiled images.
- // Extend to both directions for maximum relocation difference.
- static_assert(ART_BASE_ADDRESS_MIN_DELTA < 0);
- static_assert(ART_BASE_ADDRESS_MAX_DELTA > 0);
- static_assert(IsAligned<kPageSize>(ART_BASE_ADDRESS_MIN_DELTA));
- static_assert(IsAligned<kPageSize>(ART_BASE_ADDRESS_MAX_DELTA));
- constexpr size_t kExtra = ART_BASE_ADDRESS_MAX_DELTA - ART_BASE_ADDRESS_MIN_DELTA;
- uint32_t min_relocated_address = kBaseAddress + ART_BASE_ADDRESS_MIN_DELTA;
- std::string error_msg;
- MemMap reservation = MemMap::MapAnonymous("Reservation",
- reinterpret_cast<uint8_t*>(min_relocated_address),
- kReservationSize + kExtra,
- PROT_NONE,
- /*low_4gb=*/ true,
- /*reuse=*/ false,
- /*reservation=*/ nullptr,
- &error_msg);
- ASSERT_TRUE(reservation.IsValid());
-
- ScratchFile scratch;
- std::string scratch_dir = scratch.GetFilename() + "-d";
- int mkdir_result = mkdir(scratch_dir.c_str(), 0700);
- ASSERT_EQ(0, mkdir_result);
- scratch_dir += '/';
- std::string image_dir = scratch_dir + GetInstructionSetString(kRuntimeISA);
- mkdir_result = mkdir(image_dir.c_str(), 0700);
- ASSERT_EQ(0, mkdir_result);
- std::string filename_prefix = image_dir + "/core";
-
- // Copy the libcore dex files to a custom dir inside `scratch_dir` so that we do not
- // accidentally load pre-compiled core images from their original directory based on BCP paths.
- std::string jar_dir = scratch_dir + "jars";
- mkdir_result = mkdir(jar_dir.c_str(), 0700);
- ASSERT_EQ(0, mkdir_result);
- jar_dir += '/';
- std::vector<std::string> libcore_dex_files = GetLibCoreDexFileNames();
- for (std::string& dex_file : libcore_dex_files) {
- size_t slash_pos = dex_file.rfind('/');
- ASSERT_NE(std::string::npos, slash_pos);
- std::string new_location = jar_dir + dex_file.substr(slash_pos + 1u);
- std::ifstream src_stream(dex_file, std::ios::binary);
- std::ofstream dst_stream(new_location, std::ios::binary);
- dst_stream << src_stream.rdbuf();
- dex_file = new_location;
- }
-
- ArrayRef<const std::string> full_bcp(libcore_dex_files);
- size_t total_dex_files = full_bcp.size();
- ASSERT_GE(total_dex_files, 4u); // 2 for "head", 1 for "tail", at least one for "mid", see below.
-
- // The primary image must contain at least core-oj and core-libart to initialize the runtime.
- ASSERT_NE(std::string::npos, full_bcp[0].find("core-oj"));
- ASSERT_NE(std::string::npos, full_bcp[1].find("core-libart"));
- ArrayRef<const std::string> head_dex_files = full_bcp.SubArray(/*pos=*/ 0u, /*length=*/ 2u);
- // Middle part is everything else except for conscrypt.
- ASSERT_NE(std::string::npos, full_bcp[full_bcp.size() - 1u].find("conscrypt"));
- ArrayRef<const std::string> mid_bcp =
- full_bcp.SubArray(/*pos=*/ 0u, /*length=*/ total_dex_files - 1u);
- ArrayRef<const std::string> mid_dex_files = mid_bcp.SubArray(/*pos=*/ 2u);
- // Tail is just the conscrypt.
- ArrayRef<const std::string> tail_dex_files =
- full_bcp.SubArray(/*pos=*/ total_dex_files - 1u, /*length=*/ 1u);
-
- // Prepare the "head", "mid" and "tail" names and locations.
- std::string base_name = "core.art";
- std::string base_location = scratch_dir + base_name;
- std::vector<std::string> expanded_mid = gc::space::ImageSpace::ExpandMultiImageLocations(
- mid_dex_files.SubArray(/*pos=*/ 0u, /*length=*/ 1u),
- base_location,
- /*boot_image_extension=*/ true);
- CHECK_EQ(1u, expanded_mid.size());
- std::string mid_location = expanded_mid[0];
- size_t mid_slash_pos = mid_location.rfind('/');
- ASSERT_NE(std::string::npos, mid_slash_pos);
- std::string mid_name = mid_location.substr(mid_slash_pos + 1u);
- CHECK_EQ(1u, tail_dex_files.size());
- std::vector<std::string> expanded_tail = gc::space::ImageSpace::ExpandMultiImageLocations(
- tail_dex_files, base_location, /*boot_image_extension=*/ true);
- CHECK_EQ(1u, expanded_tail.size());
- std::string tail_location = expanded_tail[0];
- size_t tail_slash_pos = tail_location.rfind('/');
- ASSERT_NE(std::string::npos, tail_slash_pos);
- std::string tail_name = tail_location.substr(tail_slash_pos + 1u);
-
- // Compile the "head", i.e. the primary boot image.
- std::string base = android::base::StringPrintf("--base=0x%08x", kBaseAddress);
- bool head_ok = CompileBootImage({base}, filename_prefix, head_dex_files, &error_msg);
- ASSERT_TRUE(head_ok) << error_msg;
-
- // Compile the "mid", i.e. the first extension.
- std::string mid_bcp_string = android::base::Join(mid_bcp, ':');
- std::vector<std::string> extra_args;
- AddRuntimeArg(extra_args, "-Xbootclasspath:" + mid_bcp_string);
- AddRuntimeArg(extra_args, "-Xbootclasspath-locations:" + mid_bcp_string);
- extra_args.push_back("--boot-image=" + base_location);
- bool mid_ok = CompileBootImage(extra_args, filename_prefix, mid_dex_files, &error_msg);
- ASSERT_TRUE(mid_ok) << error_msg;
-
- // Try to compile the "tail" without specifying the "mid" extension. This shall fail.
- std::string full_bcp_string = android::base::Join(full_bcp, ':');
- extra_args.clear();
- AddRuntimeArg(extra_args, "-Xbootclasspath:" + full_bcp_string);
- AddRuntimeArg(extra_args, "-Xbootclasspath-locations:" + full_bcp_string);
- extra_args.push_back("--boot-image=" + base_location);
- bool tail_ok = CompileBootImage(extra_args, filename_prefix, tail_dex_files, &error_msg);
- ASSERT_FALSE(tail_ok) << error_msg;
-
- // Now compile the tail against both "head" and "mid".
- CHECK(StartsWith(extra_args.back(), "--boot-image="));
- extra_args.back() = "--boot-image=" + base_location + ':' + mid_location;
- tail_ok = CompileBootImage(extra_args, filename_prefix, tail_dex_files, &error_msg);
- ASSERT_TRUE(tail_ok) << error_msg;
-
- reservation = MemMap::Invalid(); // Free the reserved memory for loading images.
-
- // Try to load the boot image with different image locations.
- std::vector<std::string> boot_class_path = libcore_dex_files;
- std::vector<std::unique_ptr<gc::space::ImageSpace>> boot_image_spaces;
- bool relocate = false;
- MemMap extra_reservation;
- auto load = [&](const std::string& image_location) {
- boot_image_spaces.clear();
- extra_reservation = MemMap::Invalid();
- ScopedObjectAccess soa(Thread::Current());
- return gc::space::ImageSpace::LoadBootImage(/*boot_class_path=*/ boot_class_path,
- /*boot_class_path_locations=*/ libcore_dex_files,
- image_location,
- kRuntimeISA,
- gc::space::ImageSpaceLoadingOrder::kSystemFirst,
- relocate,
- /*executable=*/ true,
- /*is_zygote=*/ false,
- /*extra_reservation_size=*/ 0u,
- &boot_image_spaces,
- &extra_reservation);
- };
-
- for (bool r : { false, true}) {
- relocate = r;
-
- // Load primary image with full path.
- bool load_ok = load(base_location);
- ASSERT_TRUE(load_ok) << error_msg;
- ASSERT_FALSE(extra_reservation.IsValid());
- ASSERT_EQ(head_dex_files.size(), boot_image_spaces.size());
-
- // Fail to load primary image with just the name.
- load_ok = load(base_name);
- ASSERT_FALSE(load_ok);
-
- // Fail to load primary image with a search path.
- load_ok = load("*");
- ASSERT_FALSE(load_ok);
- load_ok = load(scratch_dir + "*");
- ASSERT_FALSE(load_ok);
-
- // Load the primary and first extension with full path.
- load_ok = load(base_location + ':' + mid_location);
- ASSERT_TRUE(load_ok) << error_msg;
- ASSERT_EQ(mid_bcp.size(), boot_image_spaces.size());
-
- // Load the primary with full path and fail to load first extension without full path.
- load_ok = load(base_location + ':' + mid_name);
- ASSERT_TRUE(load_ok) << error_msg; // Primary image loaded successfully.
- ASSERT_EQ(head_dex_files.size(), boot_image_spaces.size()); // But only the primary image.
-
- // Load all the libcore images with full paths.
- load_ok = load(base_location + ':' + mid_location + ':' + tail_location);
- ASSERT_TRUE(load_ok) << error_msg;
- ASSERT_EQ(full_bcp.size(), boot_image_spaces.size());
-
- // Load the primary and first extension with full paths, fail to load second extension by name.
- load_ok = load(base_location + ':' + mid_location + ':' + tail_name);
- ASSERT_TRUE(load_ok) << error_msg;
- ASSERT_EQ(mid_bcp.size(), boot_image_spaces.size());
-
- // Load the primary with full path and fail to load first extension without full path,
- // fail to load second extension because it depends on the first.
- load_ok = load(base_location + ':' + mid_name + ':' + tail_location);
- ASSERT_TRUE(load_ok) << error_msg; // Primary image loaded successfully.
- ASSERT_EQ(head_dex_files.size(), boot_image_spaces.size()); // But only the primary image.
-
- // Load the primary with full path and extensions with a specified search path.
- load_ok = load(base_location + ':' + scratch_dir + '*');
- ASSERT_TRUE(load_ok) << error_msg;
- ASSERT_EQ(full_bcp.size(), boot_image_spaces.size());
-
- // Load the primary with full path and fail to find extensions in BCP path.
- load_ok = load(base_location + ":*");
- ASSERT_TRUE(load_ok) << error_msg;
- ASSERT_EQ(head_dex_files.size(), boot_image_spaces.size());
- }
-
- // Now copy the libcore dex files to the `scratch_dir` and retry loading the boot image
- // with BCP in the scratch_dir so that the images can be found based on BCP paths.
- for (std::string& bcp_component : boot_class_path) {
- size_t slash_pos = bcp_component.rfind('/');
- ASSERT_NE(std::string::npos, slash_pos);
- std::string new_location = scratch_dir + bcp_component.substr(slash_pos + 1u);
- std::ifstream src_stream(bcp_component, std::ios::binary);
- std::ofstream dst_stream(new_location, std::ios::binary);
- dst_stream << src_stream.rdbuf();
- bcp_component = new_location;
- }
-
- for (bool r : { false, true}) {
- relocate = r;
-
- // Loading the primary image with just the name now succeeds.
- bool load_ok = load(base_name);
- ASSERT_TRUE(load_ok) << error_msg;
-
- // Loading the primary image with a search path still fails.
- load_ok = load("*");
- ASSERT_FALSE(load_ok);
- load_ok = load(scratch_dir + "*");
- ASSERT_FALSE(load_ok);
-
- // Load the primary and first extension without paths.
- load_ok = load(base_name + ':' + mid_name);
- ASSERT_TRUE(load_ok) << error_msg;
- ASSERT_EQ(mid_bcp.size(), boot_image_spaces.size());
-
- // Load the primary with full path and the first extension without full path.
- load_ok = load(base_location + ':' + mid_name);
- ASSERT_TRUE(load_ok) << error_msg; // Loaded successfully.
- ASSERT_EQ(mid_bcp.size(), boot_image_spaces.size()); // Including the extension.
-
- // Load all the libcore images without paths.
- load_ok = load(base_name + ':' + mid_name + ':' + tail_name);
- ASSERT_TRUE(load_ok) << error_msg;
- ASSERT_EQ(full_bcp.size(), boot_image_spaces.size());
-
- // Load the primary and first extension with full paths and second extension by name.
- load_ok = load(base_location + ':' + mid_location + ':' + tail_name);
- ASSERT_TRUE(load_ok) << error_msg;
- ASSERT_EQ(full_bcp.size(), boot_image_spaces.size());
-
- // Load the primary with full path, first extension without path,
- // and second extension with full path.
- load_ok = load(base_location + ':' + mid_name + ':' + tail_location);
- ASSERT_TRUE(load_ok) << error_msg; // Loaded successfully.
- ASSERT_EQ(full_bcp.size(), boot_image_spaces.size()); // Including both extensions.
-
- // Load the primary with full path and find both extensions in BCP path.
- load_ok = load(base_location + ":*");
- ASSERT_TRUE(load_ok) << error_msg;
- ASSERT_EQ(full_bcp.size(), boot_image_spaces.size());
-
- // Fail to load any images with invalid image locations (named component after search paths).
- load_ok = load(base_location + ":*:" + tail_location);
- ASSERT_FALSE(load_ok);
- load_ok = load(base_location + ':' + scratch_dir + "*:" + tail_location);
- ASSERT_FALSE(load_ok);
- }
-
- ClearDirectory(scratch_dir.c_str());
- int rmdir_result = rmdir(scratch_dir.c_str());
- ASSERT_EQ(0, rmdir_result);
-}
-
} // namespace art
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index fa08627..9e5da27 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -171,9 +171,8 @@
// Create a generic tmp file, to be the base of the .art and .oat temporary files.
ScratchFile location;
std::vector<std::string> image_locations =
- gc::space::ImageSpace::ExpandMultiImageLocations(
- ArrayRef<const std::string>(out_helper.dex_file_locations),
- location.GetFilename() + ".art");
+ gc::space::ImageSpace::ExpandMultiImageLocations(out_helper.dex_file_locations,
+ location.GetFilename() + ".art");
for (size_t i = 0u; i != class_path.size(); ++i) {
out_helper.image_locations.push_back(ScratchFile(image_locations[i]));
}
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 51bc6a8..760acc7 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -65,10 +65,6 @@
using android::base::StringAppendF;
using android::base::StringPrintf;
-// We do not allow the boot image and extensions to take more than 1GiB. They are
-// supposed to be much smaller and allocating more that this would likely fail anyway.
-static constexpr size_t kMaxTotalImageReservationSize = 1 * GB;
-
Atomic<uint32_t> ImageSpace::bitmap_index_(0);
ImageSpace::ImageSpace(const std::string& image_filename,
@@ -1375,531 +1371,6 @@
}
};
-static void AppendImageChecksum(uint32_t component_count,
- uint32_t checksum,
- /*inout*/std::string* checksums) {
- static_assert(ImageSpace::kImageChecksumPrefix == 'i', "Format prefix check.");
- StringAppendF(checksums, "i;%u/%08x", component_count, checksum);
-}
-
-static bool CheckAndRemoveImageChecksum(uint32_t component_count,
- uint32_t checksum,
- /*inout*/std::string_view* oat_checksums,
- /*out*/std::string* error_msg) {
- std::string image_checksum;
- AppendImageChecksum(component_count, checksum, &image_checksum);
- if (!StartsWith(*oat_checksums, image_checksum)) {
- *error_msg = StringPrintf("Image checksum mismatch, expected %s to start with %s",
- std::string(*oat_checksums).c_str(),
- image_checksum.c_str());
- return false;
- }
- oat_checksums->remove_prefix(image_checksum.size());
- return true;
-}
-
-// Helper class to find the primary boot image and boot image extensions
-// and determine the boot image layout.
-class ImageSpace::BootImageLayout {
- public:
- // Description of a "chunk" of the boot image, i.e. either primary boot image
- // or a boot image extension, used in conjunction with the boot class path to
- // load boot image components.
- struct ImageChunk {
- std::string base_location;
- std::string base_filename;
- size_t start_index;
- size_t component_count;
- size_t reservation_size;
- uint32_t checksum;
- };
-
- BootImageLayout(const std::string& image_location, ArrayRef<const std::string> boot_class_path)
- : image_location_(image_location),
- boot_class_path_(boot_class_path) {}
-
- std::string GetPrimaryImageLocation();
-
- bool LoadFromSystem(InstructionSet image_isa, /*out*/std::string* error_msg) {
- return LoadOrValidateFromSystem(image_isa, /*oat_checksums=*/ nullptr, error_msg);
- }
-
- bool ValidateFromSystem(InstructionSet image_isa,
- /*inout*/std::string_view* oat_checksums,
- /*out*/std::string* error_msg) {
- DCHECK(oat_checksums != nullptr);
- return LoadOrValidateFromSystem(image_isa, oat_checksums, error_msg);
- }
-
- bool LoadFromDalvikCache(const std::string& dalvik_cache, /*out*/std::string* error_msg) {
- return LoadOrValidateFromDalvikCache(dalvik_cache, /*oat_checksums=*/ nullptr, error_msg);
- }
-
- bool ValidateFromDalvikCache(const std::string& dalvik_cache,
- /*inout*/std::string_view* oat_checksums,
- /*out*/std::string* error_msg) {
- DCHECK(oat_checksums != nullptr);
- return LoadOrValidateFromDalvikCache(dalvik_cache, oat_checksums, error_msg);
- }
-
- ArrayRef<const ImageChunk> GetChunks() const {
- return ArrayRef<const ImageChunk>(chunks_);
- }
-
- uint32_t GetBaseAddress() const {
- return base_address_;
- }
-
- size_t GetNextBcpIndex() const {
- return next_bcp_index_;
- }
-
- size_t GetTotalComponentCount() const {
- return total_component_count_;
- }
-
- size_t GetTotalReservationSize() const {
- return total_reservation_size_;
- }
-
- private:
- std::string ExpandLocationImpl(const std::string& location,
- size_t bcp_index,
- bool boot_image_extension) {
- std::vector<std::string> expanded = ExpandMultiImageLocations(
- ArrayRef<const std::string>(boot_class_path_).SubArray(bcp_index, 1u),
- location,
- boot_image_extension);
- DCHECK_EQ(expanded.size(), 1u);
- return expanded[0];
- }
-
- std::string ExpandLocation(const std::string& location, size_t bcp_index) {
- if (bcp_index == 0u) {
- DCHECK_EQ(location, ExpandLocationImpl(location, bcp_index, /*boot_image_extension=*/ false));
- return location;
- } else {
- return ExpandLocationImpl(location, bcp_index, /*boot_image_extension=*/ true);
- }
- }
-
- bool VerifyImageLocation(const std::vector<std::string>& components,
- /*out*/size_t* named_components_count,
- /*out*/std::string* error_msg);
-
- bool MatchNamedComponents(
- ArrayRef<const std::string> named_components,
- /*out*/std::vector<std::pair<std::string, size_t>>* base_locations_and_bcp_indexes,
- /*out*/std::string* error_msg);
-
- bool ReadHeader(const std::string& base_location,
- const std::string& base_filename,
- size_t bcp_index,
- size_t bcp_component_count,
- /*out*/std::string* error_msg);
-
- bool CheckAndRemoveLastChunkChecksum(/*inout*/std::string_view* oat_checksums,
- /*out*/std::string* error_msg);
-
- template <typename FilenameFn>
- bool LoadOrValidate(FilenameFn&& filename_fn,
- /*inout*/std::string_view* oat_checksums,
- /*out*/std::string* error_msg);
-
- bool LoadOrValidateFromSystem(InstructionSet image_isa,
- /*inout*/std::string_view* oat_checksums,
- /*out*/std::string* error_msg);
-
- bool LoadOrValidateFromDalvikCache(const std::string& dalvik_cache,
- /*inout*/std::string_view* oat_checksums,
- /*out*/std::string* error_msg);
-
- const std::string& image_location_;
- ArrayRef<const std::string> boot_class_path_;
-
- std::vector<ImageChunk> chunks_;
- uint32_t base_address_ = 0u;
- size_t next_bcp_index_ = 0u;
- size_t total_component_count_ = 0u;
- size_t total_reservation_size_ = 0u;
-};
-
-std::string ImageSpace::BootImageLayout::GetPrimaryImageLocation() {
- size_t location_start = 0u;
- size_t location_end = image_location_.find(':');
- while (location_end == location_start) {
- ++location_start;
- location_end = image_location_.find(location_start, ':');
- }
- std::string location = (location_end == std::string::npos)
- ? image_location_.substr(location_start)
- : image_location_.substr(location_start, location_end - location_start);
- if (image_location_.find('/') == std::string::npos) {
- // No path, so use the path from the first boot class path component.
- size_t slash_pos = boot_class_path_.empty()
- ? std::string::npos
- : boot_class_path_[0].rfind('/');
- if (slash_pos == std::string::npos) {
- return std::string();
- }
- location.insert(0u, boot_class_path_[0].substr(0u, slash_pos + 1u));
- }
- return location;
-}
-
-bool ImageSpace::BootImageLayout::VerifyImageLocation(
- const std::vector<std::string>& components,
- /*out*/size_t* named_components_count,
- /*out*/std::string* error_msg) {
- DCHECK(named_components_count != nullptr);
-
- // Validate boot class path. Require a path and non-empty name in each component.
- for (const std::string& bcp_component : boot_class_path_) {
- size_t bcp_slash_pos = bcp_component.rfind('/');
- if (bcp_slash_pos == std::string::npos || bcp_slash_pos == bcp_component.size() - 1u) {
- *error_msg = StringPrintf("Invalid boot class path component: %s", bcp_component.c_str());
- return false;
- }
- }
-
- // Validate the format of image location components.
- size_t components_size = components.size();
- if (components_size == 0u) {
- *error_msg = "Empty image location.";
- return false;
- }
- size_t wildcards_start = components_size; // No wildcards.
- for (size_t i = 0; i != components_size; ++i) {
- const std::string& component = components[i];
- DCHECK(!component.empty()); // Guaranteed by Split().
- size_t wildcard_pos = component.find('*');
- if (wildcard_pos == std::string::npos) {
- if (wildcards_start != components.size()) {
- *error_msg =
- StringPrintf("Image component without wildcard after component with wildcard: %s",
- component.c_str());
- return false;
- }
- if (component.back() == '/') {
- *error_msg = StringPrintf("Image component ends with path separator: %s",
- component.c_str());
- return false;
- }
- } else {
- if (wildcards_start == components_size) {
- wildcards_start = i;
- }
- // Wildcard must be the last character.
- if (wildcard_pos != component.size() - 1u) {
- *error_msg = StringPrintf("Unsupported wildcard (*) position in %s", component.c_str());
- return false;
- }
- // And it must be either plain wildcard or preceded by a path separator.
- if (component.size() != 1u && component[wildcard_pos - 1u] != '/') {
- *error_msg = StringPrintf("Non-plain wildcard (*) not preceded by path separator '/': %s",
- component.c_str());
- return false;
- }
- if (i == 0) {
- *error_msg = StringPrintf("Primary component contains wildcard (*): %s", component.c_str());
- return false;
- }
- }
- }
-
- *named_components_count = wildcards_start;
- return true;
-}
-
-bool ImageSpace::BootImageLayout::MatchNamedComponents(
- ArrayRef<const std::string> named_components,
- /*out*/std::vector<std::pair<std::string, size_t>>* base_locations_and_bcp_indexes,
- /*out*/std::string* error_msg) {
- DCHECK(!named_components.empty());
- DCHECK(base_locations_and_bcp_indexes->empty());
- base_locations_and_bcp_indexes->reserve(named_components.size());
- size_t bcp_component_count = boot_class_path_.size();
- size_t bcp_pos = 0;
- std::string base_name;
- for (size_t i = 0, size = named_components.size(); i != size; ++i) {
- const std::string& component = named_components[i];
- size_t slash_pos = component.rfind('/');
- std::string base_location;
- if (i == 0u) {
- // The primary boot image name is taken as provided. It forms the base
- // for expanding the extension filenames.
- if (slash_pos != std::string::npos) {
- base_name = component.substr(slash_pos + 1u);
- base_location = component;
- } else {
- base_name = component;
- size_t bcp_slash_pos = boot_class_path_[0u].rfind('/');
- DCHECK_NE(bcp_slash_pos, std::string::npos);
- base_location = boot_class_path_[0u].substr(0u, bcp_slash_pos + 1u) + component;
- }
- } else {
- std::string to_match;
- if (slash_pos != std::string::npos) {
- // If we have the full path, we just need to match the filename to the BCP component.
- base_location = component.substr(0u, slash_pos + 1u) + base_name;
- to_match = component;
- }
- while (true) {
- if (slash_pos == std::string::npos) {
- // If we do not have a full path, we need to update the path based on the BCP location.
- size_t bcp_slash_pos = boot_class_path_[bcp_pos].rfind('/');
- DCHECK_NE(bcp_slash_pos, std::string::npos);
- std::string path = boot_class_path_[bcp_pos].substr(0u, bcp_slash_pos + 1u);
- to_match = path + component;
- base_location = path + base_name;
- }
- if (ExpandLocation(base_location, bcp_pos) == to_match) {
- break;
- }
- ++bcp_pos;
- if (bcp_pos == bcp_component_count) {
- *error_msg = StringPrintf("Image component %s does not match a boot class path component",
- component.c_str());
- return false;
- }
- }
- }
- base_locations_and_bcp_indexes->emplace_back(base_location, bcp_pos);
- ++bcp_pos;
- }
- return true;
-}
-
-bool ImageSpace::BootImageLayout::ReadHeader(const std::string& base_location,
- const std::string& base_filename,
- size_t bcp_index,
- size_t bcp_component_count,
- /*out*/std::string* error_msg) {
- DCHECK_LE(next_bcp_index_, bcp_index);
- DCHECK_LT(bcp_index, bcp_component_count);
- size_t allowed_component_count = bcp_component_count - bcp_index;
- DCHECK_LE(total_reservation_size_, kMaxTotalImageReservationSize);
- size_t allowed_reservation_size = kMaxTotalImageReservationSize - total_reservation_size_;
-
- std::string actual_filename = ExpandLocation(base_filename, bcp_index);
- ImageHeader header;
- if (!ReadSpecificImageHeader(actual_filename.c_str(), &header, error_msg)) {
- return false;
- }
- if (header.GetComponentCount() == 0u ||
- header.GetComponentCount() > allowed_component_count) {
- *error_msg = StringPrintf("Unexpected component count in %s, received %u, "
- "expected non-zero and <= %zu",
- actual_filename.c_str(),
- header.GetComponentCount(),
- allowed_component_count);
- return false;
- }
- if (header.GetImageReservationSize() > allowed_reservation_size) {
- *error_msg = StringPrintf("Reservation size too big in %s: %u > %zu",
- actual_filename.c_str(),
- header.GetImageReservationSize(),
- allowed_reservation_size);
- return false;
- }
-
- if (chunks_.empty()) {
- base_address_ = reinterpret_cast32<uint32_t>(header.GetImageBegin());
- }
- ImageChunk chunk;
- chunk.base_location = base_location;
- chunk.base_filename = base_filename;
- chunk.start_index = bcp_index;
- chunk.component_count = header.GetComponentCount();
- chunk.reservation_size = header.GetImageReservationSize();
- chunk.checksum = header.GetImageChecksum();
- chunks_.push_back(std::move(chunk));
- next_bcp_index_ = bcp_index + header.GetComponentCount();
- total_component_count_ += header.GetComponentCount();
- total_reservation_size_ += header.GetImageReservationSize();
- return true;
-}
-
-bool ImageSpace::BootImageLayout::CheckAndRemoveLastChunkChecksum(
- /*inout*/std::string_view* oat_checksums,
- /*out*/std::string* error_msg) {
- DCHECK(oat_checksums != nullptr);
- DCHECK(!chunks_.empty());
- const ImageChunk& chunk = chunks_.back();
- size_t component_count = chunk.component_count;
- size_t checksum = chunk.checksum;
- if (!CheckAndRemoveImageChecksum(component_count, checksum, oat_checksums, error_msg)) {
- DCHECK(!error_msg->empty());
- return false;
- }
- if (oat_checksums->empty()) {
- if (next_bcp_index_ != boot_class_path_.size()) {
- *error_msg = StringPrintf("Checksum too short, missing %zu components.",
- boot_class_path_.size() - next_bcp_index_);
- return false;
- }
- return true;
- }
- if (!StartsWith(*oat_checksums, ":")) {
- *error_msg = StringPrintf("Missing ':' separator at start of %s",
- std::string(*oat_checksums).c_str());
- return false;
- }
- oat_checksums->remove_prefix(1u);
- if (oat_checksums->empty()) {
- *error_msg = "Missing checksums after the ':' separator.";
- return false;
- }
- return true;
-}
-
-template <typename FilenameFn>
-bool ImageSpace::BootImageLayout::LoadOrValidate(FilenameFn&& filename_fn,
- /*inout*/std::string_view* oat_checksums,
- /*out*/std::string* error_msg) {
- DCHECK(GetChunks().empty());
- DCHECK_EQ(GetBaseAddress(), 0u);
- bool validate = (oat_checksums != nullptr);
- static_assert(ImageSpace::kImageChecksumPrefix == 'i', "Format prefix check.");
- DCHECK(!validate || StartsWith(*oat_checksums, "i"));
-
- std::vector<std::string> components;
- Split(image_location_, ':', &components);
- size_t named_components_count = 0u;
- if (!VerifyImageLocation(components, &named_components_count, error_msg)) {
- return false;
- }
-
- ArrayRef<const std::string> named_components =
- ArrayRef<const std::string>(components).SubArray(/*pos=*/ 0u, named_components_count);
-
- std::vector<std::pair<std::string, size_t>> base_locations_and_bcp_indexes;
- if (!MatchNamedComponents(named_components, &base_locations_and_bcp_indexes, error_msg)) {
- return false;
- }
-
- // Load the image headers of named components.
- DCHECK_EQ(base_locations_and_bcp_indexes.size(), named_components.size());
- const size_t bcp_component_count = boot_class_path_.size();
- size_t bcp_pos = 0u;
- for (size_t i = 0, size = named_components.size(); i != size; ++i) {
- const std::string& base_location = base_locations_and_bcp_indexes[i].first;
- size_t bcp_index = base_locations_and_bcp_indexes[i].second;
- if (bcp_index < bcp_pos) {
- DCHECK_NE(i, 0u);
- LOG(ERROR) << "Named image component already covered by previous image: " << base_location;
- continue;
- }
- if (validate && bcp_index > bcp_pos) {
- *error_msg = StringPrintf("End of contiguous boot class path images, remaining checksum: %s",
- std::string(*oat_checksums).c_str());
- return false;
- }
- std::string local_error_msg;
- std::string* err_msg = (i == 0 || validate) ? error_msg : &local_error_msg;
- std::string base_filename;
- if (!filename_fn(base_location, &base_filename, err_msg) ||
- !ReadHeader(base_location, base_filename, bcp_index, bcp_component_count, err_msg)) {
- if (i == 0u || validate) {
- return false;
- }
- VLOG(image) << "Error reading named image component header for " << base_location
- << ", error: " << local_error_msg;
- bcp_pos = bcp_index + 1u; // Skip at least this component.
- DCHECK_GT(bcp_pos, GetNextBcpIndex());
- continue;
- }
- if (validate) {
- if (!CheckAndRemoveLastChunkChecksum(oat_checksums, error_msg)) {
- return false;
- }
- if (oat_checksums->empty() || !StartsWith(*oat_checksums, "i")) {
- return true; // Let the caller deal with the dex file checksums if any.
- }
- }
- bcp_pos = GetNextBcpIndex();
- }
-
- // Look for remaining components if there are any wildcard specifications.
- ArrayRef<const std::string> search_paths =
- ArrayRef<const std::string>(components).SubArray(/*pos=*/ named_components_count);
- if (!search_paths.empty()) {
- const std::string& primary_base_location = base_locations_and_bcp_indexes[0].first;
- size_t base_slash_pos = primary_base_location.rfind('/');
- DCHECK_NE(base_slash_pos, std::string::npos);
- std::string base_name = primary_base_location.substr(base_slash_pos + 1u);
- DCHECK(!base_name.empty());
- while (bcp_pos != bcp_component_count) {
- const std::string& bcp_component = boot_class_path_[bcp_pos];
- bool found = false;
- for (const std::string& path : search_paths) {
- std::string base_location;
- if (path.size() == 1u) {
- DCHECK_EQ(path, "*");
- size_t slash_pos = bcp_component.rfind('/');
- DCHECK_NE(slash_pos, std::string::npos);
- base_location = bcp_component.substr(0u, slash_pos + 1u) + base_name;
- } else {
- DCHECK(EndsWith(path, "/*"));
- base_location = path.substr(0u, path.size() - 1u) + base_name;
- }
- std::string err_msg; // Ignored.
- std::string base_filename;
- if (filename_fn(base_location, &base_filename, &err_msg) &&
- ReadHeader(base_location, base_filename, bcp_pos, bcp_component_count, &err_msg)) {
- VLOG(image) << "Found image extension for " << ExpandLocation(base_location, bcp_pos);
- bcp_pos = GetNextBcpIndex();
- found = true;
- if (validate) {
- if (!CheckAndRemoveLastChunkChecksum(oat_checksums, error_msg)) {
- return false;
- }
- if (oat_checksums->empty() || !StartsWith(*oat_checksums, "i")) {
- return true; // Let the caller deal with the dex file checksums if any.
- }
- }
- break;
- }
- }
- if (!found) {
- if (validate) {
- *error_msg = StringPrintf("Missing extension for %s, remaining checksum: %s",
- bcp_component.c_str(),
- std::string(*oat_checksums).c_str());
- return false;
- }
- ++bcp_pos;
- }
- }
- }
-
- return true;
-}
-
-bool ImageSpace::BootImageLayout::LoadOrValidateFromSystem(InstructionSet image_isa,
- /*inout*/std::string_view* oat_checksums,
- /*out*/std::string* error_msg) {
- auto filename_fn = [image_isa](const std::string& location,
- /*out*/std::string* filename,
- /*out*/std::string* err_msg ATTRIBUTE_UNUSED) {
- *filename = GetSystemImageFilename(location.c_str(), image_isa);
- return true;
- };
- return LoadOrValidate(filename_fn, oat_checksums, error_msg);
-}
-
-bool ImageSpace::BootImageLayout::LoadOrValidateFromDalvikCache(
- const std::string& dalvik_cache,
- /*inout*/std::string_view* oat_checksums,
- /*out*/std::string* error_msg) {
- auto filename_fn = [&dalvik_cache](const std::string& location,
- /*out*/std::string* filename,
- /*out*/std::string* err_msg) {
- return GetDalvikCacheFilename(location.c_str(), dalvik_cache.c_str(), filename, err_msg);
- };
- return LoadOrValidate(filename_fn, oat_checksums, error_msg);
-}
-
class ImageSpace::BootImageLoader {
public:
BootImageLoader(const std::vector<std::string>& boot_class_path,
@@ -1927,10 +1398,8 @@
bool IsZygote() const { return is_zygote_; }
void FindImageFiles() {
- BootImageLayout layout(image_location_, boot_class_path_);
- std::string image_location = layout.GetPrimaryImageLocation();
std::string system_filename;
- bool found_image = FindImageFilenameImpl(image_location.c_str(),
+ bool found_image = FindImageFilenameImpl(image_location_.c_str(),
image_isa_,
&has_system_,
&system_filename,
@@ -1959,115 +1428,124 @@
bool LoadFromSystem(bool validate_oat_file,
size_t extra_reservation_size,
- /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
+ /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
/*out*/MemMap* extra_reservation,
- /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_);
+ /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
+ TimingLogger logger(__PRETTY_FUNCTION__, /*precise=*/ true, VLOG_IS_ON(image));
+ std::string filename = GetSystemImageFilename(image_location_.c_str(), image_isa_);
+
+ if (!LoadFromFile(filename,
+ validate_oat_file,
+ extra_reservation_size,
+ &logger,
+ boot_image_spaces,
+ extra_reservation,
+ error_msg)) {
+ return false;
+ }
+
+ if (VLOG_IS_ON(image)) {
+ LOG(INFO) << "ImageSpace::BootImageLoader::LoadFromSystem exiting "
+ << boot_image_spaces->front();
+ logger.Dump(LOG_STREAM(INFO));
+ }
+ return true;
+ }
bool LoadFromDalvikCache(
bool validate_oat_file,
size_t extra_reservation_size,
- /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
+ /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
/*out*/MemMap* extra_reservation,
- /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_);
+ /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
+ TimingLogger logger(__PRETTY_FUNCTION__, /*precise=*/ true, VLOG_IS_ON(image));
+ DCHECK(DalvikCacheExists());
+
+ if (!LoadFromFile(cache_filename_,
+ validate_oat_file,
+ extra_reservation_size,
+ &logger,
+ boot_image_spaces,
+ extra_reservation,
+ error_msg)) {
+ return false;
+ }
+
+ if (VLOG_IS_ON(image)) {
+ LOG(INFO) << "ImageSpace::BootImageLoader::LoadFromDalvikCache exiting "
+ << boot_image_spaces->front();
+ logger.Dump(LOG_STREAM(INFO));
+ }
+ return true;
+ }
private:
- bool LoadImage(
- const BootImageLayout& layout,
+ bool LoadFromFile(
+ const std::string& filename,
bool validate_oat_file,
size_t extra_reservation_size,
TimingLogger* logger,
- /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
+ /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
/*out*/MemMap* extra_reservation,
/*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
- ArrayRef<const BootImageLayout::ImageChunk> chunks = layout.GetChunks();
- DCHECK(!chunks.empty());
- const uint32_t base_address = layout.GetBaseAddress();
- const size_t image_component_count = layout.GetTotalComponentCount();
- const size_t image_reservation_size = layout.GetTotalReservationSize();
-
- DCHECK_LE(image_reservation_size, kMaxTotalImageReservationSize);
- static_assert(kMaxTotalImageReservationSize < std::numeric_limits<uint32_t>::max());
- if (extra_reservation_size > std::numeric_limits<uint32_t>::max() - image_reservation_size) {
- // Since the `image_reservation_size` is limited to kMaxTotalImageReservationSize,
- // the `extra_reservation_size` would have to be really excessive to fail this check.
- *error_msg = StringPrintf("Excessive extra reservation size: %zu", extra_reservation_size);
+ ImageHeader system_hdr;
+ if (!ReadSpecificImageHeader(filename.c_str(), &system_hdr, error_msg)) {
return false;
}
-
- // Reserve address space. If relocating, choose a random address for ALSR.
- uint8_t* addr = reinterpret_cast<uint8_t*>(
- relocate_ ? ART_BASE_ADDRESS + ChooseRelocationOffsetDelta() : base_address);
- MemMap image_reservation =
- ReserveBootImageMemory(addr, image_reservation_size + extra_reservation_size, error_msg);
- if (!image_reservation.IsValid()) {
+ if (system_hdr.GetComponentCount() == 0u ||
+ system_hdr.GetComponentCount() > boot_class_path_.size()) {
+ *error_msg = StringPrintf("Unexpected component count in %s, received %u, "
+ "expected non-zero and <= %zu",
+ filename.c_str(),
+ system_hdr.GetComponentCount(),
+ boot_class_path_.size());
return false;
}
-
- // Load components.
- std::vector<std::unique_ptr<ImageSpace>> spaces;
- spaces.reserve(image_component_count);
- size_t max_image_space_dependencies = 0u;
- for (size_t i = 0, num_chunks = chunks.size(); i != num_chunks; ++i) {
- const BootImageLayout::ImageChunk& chunk = chunks[i];
- std::string extension_error_msg;
- uint8_t* old_reservation_begin = image_reservation.Begin();
- size_t old_reservation_size = image_reservation.Size();
- DCHECK_LE(chunk.reservation_size, old_reservation_size);
- if (!LoadComponents(chunk,
- validate_oat_file,
- max_image_space_dependencies,
- logger,
- &spaces,
- &image_reservation,
- (i == 0) ? error_msg : &extension_error_msg)) {
- // Failed to load the chunk. If this is the primary boot image, report the error.
- if (i == 0) {
- return false;
- }
- // For extension, shrink the reservation (and remap if needed, see below).
- size_t new_reservation_size = old_reservation_size - chunk.reservation_size;
- if (new_reservation_size == 0u) {
- DCHECK_EQ(extra_reservation_size, 0u);
- DCHECK_EQ(i + 1u, num_chunks);
- image_reservation.Reset();
- } else if (old_reservation_begin != image_reservation.Begin()) {
- // Part of the image reservation has been used and then unmapped when
- // rollling back the partial boot image extension load. Try to remap
- // the image reservation. As this should be running single-threaded,
- // the address range should still be available to mmap().
- image_reservation.Reset();
- std::string remap_error_msg;
- image_reservation = ReserveBootImageMemory(old_reservation_begin,
- new_reservation_size,
- &remap_error_msg);
- if (!image_reservation.IsValid()) {
- *error_msg = StringPrintf("Failed to remap boot image reservation after failing "
- "to load boot image extension (%s: %s): %s",
- boot_class_path_locations_[chunk.start_index].c_str(),
- extension_error_msg.c_str(),
- remap_error_msg.c_str());
- return false;
- }
- } else {
- DCHECK_EQ(old_reservation_size, image_reservation.Size());
- image_reservation.SetSize(new_reservation_size);
- }
- LOG(ERROR) << "Failed to load boot image extension "
- << boot_class_path_locations_[chunk.start_index] << ": " << extension_error_msg;
- }
- // Update `max_image_space_dependencies` if all previous BCP components
- // were covered and loading the current chunk succeeded.
- if (max_image_space_dependencies == chunk.start_index &&
- spaces.size() == chunk.start_index + chunk.component_count) {
- max_image_space_dependencies = chunk.start_index + chunk.component_count;
- }
- }
-
+ MemMap image_reservation;
MemMap local_extra_reservation;
- if (!RemapExtraReservation(extra_reservation_size,
- &image_reservation,
- &local_extra_reservation,
- error_msg)) {
+ if (!ReserveBootImageMemory(system_hdr.GetImageReservationSize(),
+ reinterpret_cast32<uint32_t>(system_hdr.GetImageBegin()),
+ extra_reservation_size,
+ &image_reservation,
+ &local_extra_reservation,
+ error_msg)) {
+ return false;
+ }
+
+ ArrayRef<const std::string> provided_locations(boot_class_path_locations_.data(),
+ system_hdr.GetComponentCount());
+ std::vector<std::string> locations =
+ ExpandMultiImageLocations(provided_locations, image_location_);
+ std::vector<std::string> filenames =
+ ExpandMultiImageLocations(provided_locations, filename);
+ DCHECK_EQ(locations.size(), filenames.size());
+ std::vector<std::unique_ptr<ImageSpace>> spaces;
+ spaces.reserve(locations.size());
+ for (std::size_t i = 0u, size = locations.size(); i != size; ++i) {
+ spaces.push_back(Load(locations[i], filenames[i], logger, &image_reservation, error_msg));
+ const ImageSpace* space = spaces.back().get();
+ if (space == nullptr) {
+ return false;
+ }
+ uint32_t expected_component_count = (i == 0u) ? system_hdr.GetComponentCount() : 0u;
+ uint32_t expected_reservation_size = (i == 0u) ? system_hdr.GetImageReservationSize() : 0u;
+ if (!Loader::CheckImageReservationSize(*space, expected_reservation_size, error_msg) ||
+ !Loader::CheckImageComponentCount(*space, expected_component_count, error_msg)) {
+ return false;
+ }
+ }
+ for (size_t i = 0u, size = spaces.size(); i != size; ++i) {
+ if (!OpenOatFile(spaces[i].get(),
+ boot_class_path_[i],
+ validate_oat_file,
+ /*available_dependencies=*/ ArrayRef<const std::unique_ptr<ImageSpace>>(),
+ logger,
+ &image_reservation,
+ error_msg)) {
+ return false;
+ }
+ }
+ if (!CheckReservationExhausted(image_reservation, error_msg)) {
return false;
}
@@ -2227,7 +1705,6 @@
simple_relocate_visitor);
// Retrieve the Class.class, Method.class and Constructor.class needed in the loops below.
- ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots;
ObjPtr<mirror::Class> class_class;
ObjPtr<mirror::Class> method_class;
ObjPtr<mirror::Class> constructor_class;
@@ -2242,8 +1719,9 @@
kExtension ? source_size - image_size : image_size);
int32_t class_roots_index = enum_cast<int32_t>(ImageHeader::kClassRoots);
DCHECK_LT(class_roots_index, image_roots->GetLength<kVerifyNone>());
- class_roots = ObjPtr<mirror::ObjectArray<mirror::Class>>::DownCast(base_relocate_visitor(
- image_roots->GetWithoutChecks<kVerifyNone>(class_roots_index).Ptr()));
+ ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+ ObjPtr<mirror::ObjectArray<mirror::Class>>::DownCast(base_relocate_visitor(
+ image_roots->GetWithoutChecks<kVerifyNone>(class_roots_index).Ptr()));
if (kExtension) {
DCHECK(patched_objects->Test(class_roots.Ptr()));
class_class = GetClassRoot<mirror::Class, kWithoutReadBarrier>(class_roots);
@@ -2375,12 +1853,6 @@
pos += RoundUp(object->SizeOf<kVerifyNone>(), kObjectAlignment);
}
}
- if (kIsDebugBuild && !kExtension) {
- // We used just Test() instead of Set() above but we need to use Set()
- // for class roots to satisfy a DCHECK() for extensions.
- DCHECK(!patched_objects->Test(class_roots.Ptr()));
- patched_objects->Set(class_roots.Ptr());
- }
}
void MaybeRelocateSpaces(const std::vector<std::unique_ptr<ImageSpace>>& spaces,
@@ -2561,117 +2033,37 @@
return true;
}
- bool LoadComponents(const BootImageLayout::ImageChunk& chunk,
- bool validate_oat_file,
- size_t max_image_space_dependencies,
- TimingLogger* logger,
- /*inout*/std::vector<std::unique_ptr<ImageSpace>>* spaces,
- /*inout*/MemMap* image_reservation,
- /*out*/std::string* error_msg)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- // Make sure we destroy the spaces we created if we're returning an error.
- // Note that this can unmap part of the original `image_reservation`.
- class Guard {
- public:
- explicit Guard(std::vector<std::unique_ptr<ImageSpace>>* spaces_in)
- : spaces_(spaces_in), committed_(spaces_->size()) {}
- void Commit() {
- DCHECK_LT(committed_, spaces_->size());
- committed_ = spaces_->size();
- }
- ~Guard() {
- DCHECK_LE(committed_, spaces_->size());
- spaces_->resize(committed_);
- }
- private:
- std::vector<std::unique_ptr<ImageSpace>>* const spaces_;
- size_t committed_;
- };
- Guard guard(spaces);
-
- bool is_extension = (chunk.start_index != 0u);
- DCHECK_NE(spaces->empty(), is_extension);
- ArrayRef<const std::string> requested_bcp_locations =
- ArrayRef<const std::string>(boot_class_path_locations_).SubArray(
- chunk.start_index, chunk.component_count);
- std::vector<std::string> locations =
- ExpandMultiImageLocations(requested_bcp_locations, chunk.base_location, is_extension);
- std::vector<std::string> filenames =
- ExpandMultiImageLocations(requested_bcp_locations, chunk.base_filename, is_extension);
- DCHECK_EQ(locations.size(), filenames.size());
- for (std::size_t i = 0u, size = locations.size(); i != size; ++i) {
- spaces->push_back(Load(locations[i], filenames[i], logger, image_reservation, error_msg));
- const ImageSpace* space = spaces->back().get();
- if (space == nullptr) {
- return false;
- }
- uint32_t expected_component_count = (i == 0u) ? chunk.component_count : 0u;
- uint32_t expected_reservation_size = (i == 0u) ? chunk.reservation_size : 0u;
- if (!Loader::CheckImageReservationSize(*space, expected_reservation_size, error_msg) ||
- !Loader::CheckImageComponentCount(*space, expected_component_count, error_msg)) {
- return false;
- }
- if (i == 0 && chunk.checksum != space->GetImageHeader().GetImageChecksum()) {
- *error_msg = StringPrintf("Image checksum modified since previously read from %s, "
- "received %u, expected %u",
- space->GetImageFilename().c_str(),
- space->GetImageHeader().GetImageChecksum(),
- chunk.checksum);
- return false;
- }
- }
- ArrayRef<const std::unique_ptr<ImageSpace>> available_dependencies =
- ArrayRef<const std::unique_ptr<ImageSpace>>(*spaces).SubArray(/*pos=*/ 0u,
- max_image_space_dependencies);
- for (std::size_t i = 0u, size = locations.size(); i != size; ++i) {
- ImageSpace* space = (*spaces)[spaces->size() - chunk.component_count + i].get();
- if (!OpenOatFile(space,
- boot_class_path_[chunk.start_index + i],
- validate_oat_file,
- available_dependencies,
- logger,
- image_reservation,
- error_msg)) {
- return false;
- }
- }
-
- guard.Commit();
- return true;
- }
-
- MemMap ReserveBootImageMemory(uint8_t* addr,
- uint32_t reservation_size,
- /*out*/std::string* error_msg) {
+ bool ReserveBootImageMemory(uint32_t reservation_size,
+ uint32_t image_start,
+ size_t extra_reservation_size,
+ /*out*/MemMap* image_reservation,
+ /*out*/MemMap* extra_reservation,
+ /*out*/std::string* error_msg) {
DCHECK_ALIGNED(reservation_size, kPageSize);
- DCHECK_ALIGNED(addr, kPageSize);
- return MemMap::MapAnonymous("Boot image reservation",
- addr,
- reservation_size,
- PROT_NONE,
- /*low_4gb=*/ true,
- /*reuse=*/ false,
- /*reservation=*/ nullptr,
- error_msg);
- }
-
- bool RemapExtraReservation(size_t extra_reservation_size,
- /*inout*/MemMap* image_reservation,
- /*out*/MemMap* extra_reservation,
- /*out*/std::string* error_msg) {
- DCHECK_ALIGNED(extra_reservation_size, kPageSize);
- DCHECK(!extra_reservation->IsValid());
- size_t expected_size = image_reservation->IsValid() ? image_reservation->Size() : 0u;
- if (extra_reservation_size != expected_size) {
- *error_msg = StringPrintf("Image reservation mismatch after loading boot image: %zu != %zu",
- extra_reservation_size,
- expected_size);
+ DCHECK_ALIGNED(image_start, kPageSize);
+ DCHECK(!image_reservation->IsValid());
+ DCHECK_LT(extra_reservation_size, std::numeric_limits<uint32_t>::max() - reservation_size);
+ size_t total_size = reservation_size + extra_reservation_size;
+ // If relocating, choose a random address for ALSR.
+ uint32_t addr = relocate_ ? ART_BASE_ADDRESS + ChooseRelocationOffsetDelta() : image_start;
+ *image_reservation =
+ MemMap::MapAnonymous("Boot image reservation",
+ reinterpret_cast32<uint8_t*>(addr),
+ total_size,
+ PROT_NONE,
+ /*low_4gb=*/ true,
+ /*reuse=*/ false,
+ /*reservation=*/ nullptr,
+ error_msg);
+ if (!image_reservation->IsValid()) {
return false;
}
+ DCHECK(!extra_reservation->IsValid());
if (extra_reservation_size != 0u) {
- DCHECK(image_reservation->IsValid());
- DCHECK_EQ(extra_reservation_size, image_reservation->Size());
- *extra_reservation = image_reservation->RemapAtEnd(image_reservation->Begin(),
+ DCHECK_ALIGNED(extra_reservation_size, kPageSize);
+ DCHECK_LT(extra_reservation_size, image_reservation->Size());
+ uint8_t* split = image_reservation->End() - extra_reservation_size;
+ *extra_reservation = image_reservation->RemapAtEnd(split,
"Boot image extra reservation",
PROT_NONE,
error_msg);
@@ -2679,17 +2071,27 @@
return false;
}
}
- DCHECK(!image_reservation->IsValid());
+
return true;
}
- const ArrayRef<const std::string> boot_class_path_;
- const ArrayRef<const std::string> boot_class_path_locations_;
- const std::string image_location_;
- const InstructionSet image_isa_;
- const bool relocate_;
- const bool executable_;
- const bool is_zygote_;
+ bool CheckReservationExhausted(const MemMap& image_reservation, /*out*/std::string* error_msg) {
+ if (image_reservation.IsValid()) {
+ *error_msg = StringPrintf("Excessive image reservation after loading boot image: %p-%p",
+ image_reservation.Begin(),
+ image_reservation.End());
+ return false;
+ }
+ return true;
+ }
+
+ const std::vector<std::string>& boot_class_path_;
+ const std::vector<std::string>& boot_class_path_locations_;
+ const std::string& image_location_;
+ InstructionSet image_isa_;
+ bool relocate_;
+ bool executable_;
+ bool is_zygote_;
bool has_system_;
bool has_cache_;
bool is_global_cache_;
@@ -2698,68 +2100,6 @@
std::string cache_filename_;
};
-bool ImageSpace::BootImageLoader::LoadFromSystem(
- bool validate_oat_file,
- size_t extra_reservation_size,
- /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
- /*out*/MemMap* extra_reservation,
- /*out*/std::string* error_msg) {
- TimingLogger logger(__PRETTY_FUNCTION__, /*precise=*/ true, VLOG_IS_ON(image));
-
- BootImageLayout layout(image_location_, boot_class_path_);
- if (!layout.LoadFromSystem(image_isa_, error_msg)) {
- return false;
- }
-
- if (!LoadImage(layout,
- validate_oat_file,
- extra_reservation_size,
- &logger,
- boot_image_spaces,
- extra_reservation,
- error_msg)) {
- return false;
- }
-
- if (VLOG_IS_ON(image)) {
- LOG(INFO) << "ImageSpace::BootImageLoader::LoadFromSystem exiting "
- << boot_image_spaces->front();
- logger.Dump(LOG_STREAM(INFO));
- }
- return true;
-}
-
-bool ImageSpace::BootImageLoader::LoadFromDalvikCache(
- bool validate_oat_file,
- size_t extra_reservation_size,
- /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
- /*out*/MemMap* extra_reservation,
- /*out*/std::string* error_msg) {
- TimingLogger logger(__PRETTY_FUNCTION__, /*precise=*/ true, VLOG_IS_ON(image));
- DCHECK(DalvikCacheExists());
-
- BootImageLayout layout(image_location_, boot_class_path_);
- if (!layout.LoadFromDalvikCache(dalvik_cache_, error_msg)) {
- return false;
- }
- if (!LoadImage(layout,
- validate_oat_file,
- extra_reservation_size,
- &logger,
- boot_image_spaces,
- extra_reservation,
- error_msg)) {
- return false;
- }
-
- if (VLOG_IS_ON(image)) {
- LOG(INFO) << "ImageSpace::BootImageLoader::LoadFromDalvikCache exiting "
- << boot_image_spaces->front();
- logger.Dump(LOG_STREAM(INFO));
- }
- return true;
-}
-
static constexpr uint64_t kLowSpaceValue = 50 * MB;
static constexpr uint64_t kTmpFsSentinelValue = 384 * MB;
@@ -2805,7 +2145,7 @@
bool executable,
bool is_zygote,
size_t extra_reservation_size,
- /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
+ /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
/*out*/MemMap* extra_reservation) {
ScopedTrace trace(__FUNCTION__);
@@ -3048,6 +2388,11 @@
return true;
}
+static void AppendImageChecksum(const ImageHeader& header, /*inout*/std::string* checksums) {
+ static_assert(ImageSpace::kImageChecksumPrefix == 'i', "Format prefix check.");
+ StringAppendF(checksums, "i;%u/%08x", header.GetComponentCount(), header.GetImageChecksum());
+}
+
std::string ImageSpace::GetBootClassPathChecksums(
ArrayRef<ImageSpace* const> image_spaces,
ArrayRef<const DexFile* const> boot_class_path) {
@@ -3068,7 +2413,7 @@
if (image_pos != 0u) {
boot_image_checksum += ':';
}
- AppendImageChecksum(component_count, current_header.GetImageChecksum(), &boot_image_checksum);
+ AppendImageChecksum(current_header, &boot_image_checksum);
for (size_t component_index = 0; component_index != component_count; ++component_index) {
const ImageSpace* space = image_spaces[image_pos + component_index];
const OatFile* oat_file = space->oat_file_non_owned_;
@@ -3091,10 +2436,10 @@
DCHECK(boot_class_path_tail.empty() ||
!DexFileLoader::IsMultiDexLocation(boot_class_path_tail.front()->GetLocation().c_str()));
for (const DexFile* dex_file : boot_class_path_tail) {
+ if (!boot_image_checksum.empty()) {
+ boot_image_checksum += ':';
+ }
if (!DexFileLoader::IsMultiDexLocation(dex_file->GetLocation().c_str())) {
- if (!boot_image_checksum.empty()) {
- boot_image_checksum += ':';
- }
boot_image_checksum += kDexFileChecksumPrefix;
}
StringAppendF(&boot_image_checksum, "/%08x", dex_file->GetLocationChecksum());
@@ -3134,6 +2479,21 @@
return component_count;
}
+static bool CheckAndRemoveImageChecksum(const ImageHeader& header,
+ /*inout*/std::string_view* oat_checksums,
+ /*out*/std::string* error_msg) {
+ std::string image_checksum;
+ AppendImageChecksum(header, &image_checksum);
+ if (!StartsWith(*oat_checksums, image_checksum)) {
+ *error_msg = StringPrintf("Image checksum mismatch, expected %s to start with %s",
+ std::string(*oat_checksums).c_str(),
+ image_checksum.c_str());
+ return false;
+ }
+ oat_checksums->remove_prefix(image_checksum.size());
+ return true;
+}
+
bool ImageSpace::VerifyBootClassPathChecksums(std::string_view oat_checksums,
std::string_view oat_boot_class_path,
const std::string& image_location,
@@ -3155,39 +2515,75 @@
return false;
}
- size_t bcp_pos = 0u;
- if (StartsWith(oat_checksums, "i")) {
- BootImageLayout layout(image_location, boot_class_path);
- std::string primary_image_location = layout.GetPrimaryImageLocation();
- std::string system_filename;
- bool has_system = false;
- std::string cache_filename;
- bool has_cache = false;
- bool dalvik_cache_exists = false;
- bool is_global_cache = false;
- if (!FindImageFilename(primary_image_location.c_str(),
- image_isa,
- &system_filename,
- &has_system,
- &cache_filename,
- &dalvik_cache_exists,
- &has_cache,
- &is_global_cache)) {
- *error_msg = StringPrintf("Unable to find image file for %s and %s",
- image_location.c_str(),
- GetInstructionSetString(image_isa));
- return false;
- }
+ bool load_extensions = false; // TODO: Boot image extensions.
+ const std::string& actual_image_location = image_location; // TODO: Boot image extensions.
+ std::string system_filename;
+ bool has_system = false;
+ std::string cache_filename;
+ bool has_cache = false;
+ bool dalvik_cache_exists = false;
+ bool is_global_cache = false;
+ if (!FindImageFilename(actual_image_location.c_str(),
+ image_isa,
+ &system_filename,
+ &has_system,
+ &cache_filename,
+ &dalvik_cache_exists,
+ &has_cache,
+ &is_global_cache)) {
+ *error_msg = StringPrintf("Unable to find image file for %s and %s",
+ image_location.c_str(),
+ GetInstructionSetString(image_isa));
+ return false;
+ }
- DCHECK(has_system || has_cache);
- bool use_system = (order == ImageSpaceLoadingOrder::kSystemFirst) ? has_system : !has_cache;
- bool image_checksums_ok = use_system
- ? layout.ValidateFromSystem(image_isa, &oat_checksums, error_msg)
- : layout.ValidateFromDalvikCache(cache_filename, &oat_checksums, error_msg);
- if (!image_checksums_ok) {
+ DCHECK(has_system || has_cache);
+ const std::string& filename = (order == ImageSpaceLoadingOrder::kSystemFirst)
+ ? (has_system ? system_filename : cache_filename)
+ : (has_cache ? cache_filename : system_filename);
+
+ size_t bcp_pos = 0u;
+ while (StartsWith(oat_checksums, "i")) {
+ const std::string& current_filename = filename;
+ if (bcp_pos != 0u) {
+ if (!load_extensions) {
+ *error_msg = "Checksum specifies boot image extension but extensions are not used.";
+ return false;
+ }
+ UNREACHABLE(); // TODO: Boot image extensions.
+ }
+ ImageHeader header;
+ if (!ReadSpecificImageHeader(current_filename.c_str(), &header, error_msg)) {
return false;
}
- bcp_pos = layout.GetNextBcpIndex();
+ size_t component_count = header.GetComponentCount();
+ if (component_count == 0u || component_count > bcp_size - bcp_pos) {
+ *error_msg = StringPrintf("Unexpected component count in %s, received %u, "
+ "expected non-zero and <= %zu",
+ current_filename.c_str(),
+ header.GetComponentCount(),
+ bcp_size - bcp_pos);
+ return false;
+ }
+ if (!CheckAndRemoveImageChecksum(header, &oat_checksums, error_msg)) {
+ DCHECK(!error_msg->empty());
+ return false;
+ }
+ bcp_pos += component_count;
+ if (oat_checksums.empty()) {
+ if (bcp_pos != bcp_size) {
+ *error_msg = StringPrintf("Checksum too short, missing %zu components.",
+ bcp_size - bcp_pos);
+ return false;
+ }
+ return true;
+ }
+ if (!StartsWith(oat_checksums, ":")) {
+ *error_msg = StringPrintf("Missing ':' separator at start of %s",
+ std::string(oat_checksums).c_str());
+ return false;
+ }
+ oat_checksums.remove_prefix(1u);
}
for ( ; bcp_pos != bcp_size; ++bcp_pos) {
@@ -3266,8 +2662,7 @@
uint32_t component_count = current_header.GetComponentCount();
DCHECK_NE(component_count, 0u);
DCHECK_LE(component_count, image_spaces.size() - image_pos);
- uint32_t checksum = current_header.GetImageChecksum();
- if (!CheckAndRemoveImageChecksum(component_count, checksum, &oat_checksums, error_msg)) {
+ if (!CheckAndRemoveImageChecksum(current_header, &oat_checksums, error_msg)) {
DCHECK(!error_msg->empty());
return false;
}
@@ -3278,9 +2673,7 @@
size_t num_dex_files = oat_file->GetOatDexFiles().size();
CHECK_NE(num_dex_files, 0u);
const std::string main_location = oat_file->GetOatDexFiles()[0]->GetDexFileLocation();
- // TODO: Get rid of the weird ResolveRelativeEncodedDexLocation() stuff from oat_file.cc
- // and enable this check:
- // CHECK_EQ(main_location, boot_class_path_locations[image_pos + component_index]);
+ CHECK_EQ(main_location, boot_class_path[image_pos + component_index]);
CHECK(!DexFileLoader::IsMultiDexLocation(main_location.c_str()));
for (size_t i = 1u; i != num_dex_files; ++i) {
CHECK(DexFileLoader::IsMultiDexLocation(
@@ -3315,6 +2708,14 @@
}
std::vector<std::string> ImageSpace::ExpandMultiImageLocations(
+ const std::vector<std::string>& dex_locations,
+ const std::string& image_location,
+ bool boot_image_extension) {
+ return ExpandMultiImageLocations(
+ ArrayRef<const std::string>(dex_locations), image_location, boot_image_extension);
+}
+
+std::vector<std::string> ImageSpace::ExpandMultiImageLocations(
ArrayRef<const std::string> dex_locations,
const std::string& image_location,
bool boot_image_extension) {
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index f56b42b..837facc 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -39,61 +39,11 @@
return kSpaceTypeImageSpace;
}
- // Load boot image spaces for specified boot class path, image location, instruction set, etc.
+ // Load boot image spaces from a primary image file for a specified instruction set.
//
// On successful return, the loaded spaces are added to boot_image_spaces (which must be
// empty on entry) and `extra_reservation` is set to the requested reservation located
// after the end of the last loaded oat file.
- //
- // IMAGE LOCATION
- //
- // The "image location" is a colon-separated list that specifies one or more
- // components by name and may also specify search paths for extensions
- // corresponding to the remaining boot class path (BCP) extensions.
- //
- // The primary boot image can be specified as one of
- // <path>/<base-name>
- // <base-name>
- // and the path of the first BCP component is used for the second form.
- //
- // Named extension specifications must correspond to an expansion of the
- // <base-name> with a BCP component (for example boot.art with the BCP
- // component name <jar-path>/framework.jar expands to boot-framework.art).
- // They can be similarly specified as one of
- // <ext-path>/<ext-name>
- // <ext-name>
- // and must be listed in the order of their corresponding BCP components.
- //
- // Search paths for remaining extensions can be specified after named
- // components as one of
- // <search-path>/*
- // *
- // where the second form means that the path of a particular BCP component
- // should be used to search for that component's boot image extension. These
- // paths will be searched in the specifed order.
- //
- // The actual filename shall be derived from the specified locations using
- // `GetSystemImageFilename()` or `GetDalvikCacheFilename()`.
- //
- // Example image locations:
- // /system/framework/boot.art
- // - only primary boot image with full path.
- // boot.art:boot-framework.art
- // - primary and one extension, use BCP component paths.
- // /apex/com.android.art/boot.art:*
- // - primary with exact location, search for the rest based on BCP
- // component paths.
- // boot.art:/system/framework/*
- // - primary based on BCP component path, search for extensions in
- // /system/framework.
- // /apex/com.android.art/boot.art:/system/framework/*:*
- // - primary with exact location, search for extensions first in
- // /system/framework, then in the corresponding BCP component path.
- // /apex/com.android.art/boot.art:*:/system/framework/*
- // - primary with exact location, search for extensions first in the
- // corresponding BCP component path and then in /system/framework.
- // /apex/com.android.art/boot.art:*:boot-framework.jar
- // - invalid, named components may not follow search paths.
static bool LoadBootImage(
const std::vector<std::string>& boot_class_path,
const std::vector<std::string>& boot_class_path_locations,
@@ -104,7 +54,7 @@
bool executable,
bool is_zygote,
size_t extra_reservation_size,
- /*out*/std::vector<std::unique_ptr<ImageSpace>>* boot_image_spaces,
+ /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
/*out*/MemMap* extra_reservation) REQUIRES_SHARED(Locks::mutator_lock_);
// Try to open an existing app image space.
@@ -217,7 +167,7 @@
// Expand a single image location to multi-image locations based on the dex locations.
static std::vector<std::string> ExpandMultiImageLocations(
- ArrayRef<const std::string> dex_locations,
+ const std::vector<std::string>& dex_locations,
const std::string& image_location,
bool boot_image_extension = false);
@@ -283,7 +233,12 @@
friend class Space;
private:
- class BootImageLayout;
+ // Internal overload that takes ArrayRef<> instead of vector<>.
+ static std::vector<std::string> ExpandMultiImageLocations(
+ ArrayRef<const std::string> dex_locations,
+ const std::string& image_location,
+ bool boot_image_extension = false);
+
class BootImageLoader;
template <typename ReferenceVisitor>
class ClassTableVisitor;
diff --git a/runtime/image.cc b/runtime/image.cc
index 08b81c1..256b957 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -93,13 +93,6 @@
}
}
-bool ImageHeader::IsAppImage() const {
- // Unlike boot image and boot image extensions which include address space for
- // oat files in their reservation size, app images are loaded separately from oat
- // files and their reservation size is the image size rounded up to full page.
- return image_reservation_size_ == RoundUp(image_size_, kPageSize);
-}
-
bool ImageHeader::IsValid() const {
if (memcmp(magic_, kImageMagic, sizeof(kImageMagic)) != 0) {
return false;
diff --git a/runtime/image.h b/runtime/image.h
index a2d163a..13bf112 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -354,7 +354,11 @@
return data_size_;
}
- bool IsAppImage() const;
+ bool IsAppImage() const {
+ // App images currently require a boot image, if the size is non zero then it is an app image
+ // header.
+ return boot_image_size_ != 0u;
+ }
// Visit mirror::Objects in the section starting at base.
// TODO: Delete base parameter if it is always equal to GetImageBegin.
diff --git a/runtime/oat.h b/runtime/oat.h
index 7817bd3..20ea5d3 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@
class PACKED(4) OatHeader {
public:
static constexpr std::array<uint8_t, 4> kOatMagic { { 'o', 'a', 't', '\n' } };
- // Last oat version changed reason: Boot image extension.
- static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '7', '4', '\0' } };
+ // Last oat version changed reason: Revert^3 Boot image extension.
+ static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '7', '5', '\0' } };
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
static constexpr const char* kDebuggableKey = "debuggable";
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 9ef5fbb..4b5d5c3 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -855,18 +855,14 @@
CheckedCall(mprotect, "protect relocations", reloc_begin, DataBimgRelRoSize(), PROT_READ);
// Make sure the file lists a boot image dependency, otherwise the .data.bimg.rel.ro
// section is bogus. The full dependency is checked before the code is executed.
- // We cannot do this check if we do not have a key-value store, i.e. for secondary
- // oat files for boot image extensions.
- if (GetOatHeader().GetKeyValueStoreSize() != 0u) {
- const char* boot_class_path_checksum =
- GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey);
- if (boot_class_path_checksum == nullptr ||
- boot_class_path_checksum[0] != gc::space::ImageSpace::kImageChecksumPrefix) {
- *error_msg = StringPrintf("Oat file '%s' contains .data.bimg.rel.ro section "
- "without boot image dependency.",
- GetLocation().c_str());
- return false;
- }
+ const char* boot_class_path_checksum =
+ GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey);
+ if (boot_class_path_checksum == nullptr ||
+ boot_class_path_checksum[0] != gc::space::ImageSpace::kImageChecksumPrefix) {
+ *error_msg = StringPrintf("Oat file '%s' contains .data.bimg.rel.ro section "
+ "without boot image dependency.",
+ GetLocation().c_str());
+ return false;
}
}
diff --git a/test/run-test b/test/run-test
index 72e7562..eeeefbb 100755
--- a/test/run-test
+++ b/test/run-test
@@ -672,12 +672,12 @@
elif [ "$runtime" = "art" ]; then
if [ "$target_mode" = "no" ]; then
guess_host_arch_name
- run_args+=(--boot "${ANDROID_HOST_OUT}/framework/core${image_suffix}.art:*")
+ run_args+=(--boot "${ANDROID_HOST_OUT}/framework/core${image_suffix}.art")
run_args+=(--runtime-option "-Djava.library.path=${host_lib_root}/lib${suffix64}:${host_lib_root}/nativetest${suffix64}")
else
guess_target_arch_name
run_args+=(--runtime-option "-Djava.library.path=/data/nativetest${suffix64}/art/${target_arch_name}")
- run_args+=(--boot "/data/art-test/core${image_suffix}.art:/data/art-test/*")
+ run_args+=(--boot "/data/art-test/core${image_suffix}.art")
fi
if [ "$relocate" = "yes" ]; then
run_args+=(--relocate)