Update boot image extension compilation args.
And in dex2oat check for boot image location with profile
specification. For app compilation, trim such boot image
location to the leading components without profile spec.
For boot image extension, such location is currently an
error because it expects all dependencies to be satisfied
from boot images; this may be relaxed in future.
Test: aosp_taimen-userdebug boots.
Test: adb root && \
adb shell stop && \
adb shell setprop dalvik.vm.boot-image \
'boot.art:/nonx/boot-framework.art!/system/etc/boot-image.prof' &&
adb shell start # Starts correctly.
# Check /proc/<zygote64-pid>/maps, see
# <large> rw-p ... [anon:dalvik-/nonx/boot-framework.art]
# <small> r--p ... /memfd:/nonx/arm64/boot-framework.oat (deleted)
# <small> r--p ... /memfd:/nonx/arm64/boot-framework.vdex (deleted)
# <small> r--p ... /memfd:/nonx/arm64/boot-framework.oat (deleted)
# <small> rw-p ... /memfd:/nonx/arm64/boot-framework.oat (deleted)
# (No r.xp as we did not compile anything.)
Bug: 119800099
Change-Id: Ie338a54d45967c790d08cbd1e53ecbcd2b217081
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index e8f160c..4ce5335 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1050,6 +1050,26 @@
Usage("Failed to read list of passes to run.");
}
}
+
+ // Trim the boot image location to the components that do not have any profile specified.
+ size_t profile_separator_pos = boot_image_filename_.find(ImageSpace::kProfileSeparator);
+ if (profile_separator_pos != std::string::npos) {
+ DCHECK(!IsBootImage()); // For primary boot image the boot_image_filename_ is empty.
+ if (IsBootImageExtension()) {
+ Usage("Unsupported profile specification in boot image location (%s) for extension.",
+ boot_image_filename_.c_str());
+ }
+ size_t component_separator_pos =
+ boot_image_filename_.rfind(ImageSpace::kComponentSeparator, profile_separator_pos);
+ if (component_separator_pos != std::string::npos && component_separator_pos != 0u) {
+ VLOG(compiler)
+ << "Truncating boot image location " << boot_image_filename_
+ << " because it contains profile specification. Truncated: "
+ << boot_image_filename_.substr(/*pos*/ 0u, /*length*/ component_separator_pos);
+ boot_image_filename_.resize(component_separator_pos);
+ } // else let the full validation in ImageSpace reject the invalid location.
+ }
+
compiler_options_->passes_to_run_ = passes_to_run_.get();
compiler_options_->compiling_with_core_image_ =
!boot_image_filename_.empty() &&
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index f3ce583..d762e31 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1669,10 +1669,10 @@
std::string ImageSpace::BootImageLayout::GetPrimaryImageLocation() {
size_t location_start = 0u;
- size_t location_end = image_location_.find(':');
+ size_t location_end = image_location_.find(kComponentSeparator);
while (location_end == location_start) {
++location_start;
- location_end = image_location_.find(location_start, ':');
+ location_end = image_location_.find(location_start, kComponentSeparator);
}
std::string location = (location_end == std::string::npos)
? image_location_.substr(location_start)
@@ -1715,7 +1715,7 @@
for (size_t i = 0; i != components_size; ++i) {
const std::string& component = components[i];
DCHECK(!component.empty()); // Guaranteed by Split().
- const size_t profile_delimiter_pos = component.find('!');
+ const size_t profile_separator_pos = component.find(kProfileSeparator);
size_t wildcard_pos = component.find('*');
if (wildcard_pos == std::string::npos) {
if (wildcards_start != components.size()) {
@@ -1724,12 +1724,12 @@
component.c_str());
return false;
}
- if (profile_delimiter_pos != std::string::npos) {
- if (component.find('!', profile_delimiter_pos + 1u) != std::string::npos) {
+ if (profile_separator_pos != std::string::npos) {
+ if (component.find(kProfileSeparator, profile_separator_pos + 1u) != std::string::npos) {
*error_msg = StringPrintf("Multiple profile delimiters in %s", component.c_str());
return false;
}
- if (profile_delimiter_pos == 0u || profile_delimiter_pos + 1u == component.size()) {
+ if (profile_separator_pos == 0u || profile_separator_pos + 1u == component.size()) {
*error_msg = StringPrintf("Missing component and/or profile name in %s",
component.c_str());
return false;
@@ -1741,14 +1741,14 @@
}
}
size_t component_name_length =
- profile_delimiter_pos != std::string::npos ? profile_delimiter_pos : component.size();
+ profile_separator_pos != std::string::npos ? profile_separator_pos : component.size();
if (component[component_name_length - 1u] == '/') {
*error_msg = StringPrintf("Image component ends with path separator: %s",
component.c_str());
return false;
}
} else {
- if (profile_delimiter_pos != std::string::npos) {
+ if (profile_separator_pos != std::string::npos) {
*error_msg = StringPrintf("Unsupproted wildcard (*) and profile delimiter (!) in %s",
component.c_str());
return false;
@@ -1791,11 +1791,11 @@
for (size_t i = 0, size = named_components.size(); i != size; ++i) {
std::string component = named_components[i];
std::string profile_filename; // Empty.
- const size_t profile_delimiter_pos = component.find('!');
- if (profile_delimiter_pos != std::string::npos) {
- profile_filename = component.substr(profile_delimiter_pos + 1u);
+ const size_t profile_separator_pos = component.find(kProfileSeparator);
+ if (profile_separator_pos != std::string::npos) {
+ profile_filename = component.substr(profile_separator_pos + 1u);
DCHECK(!profile_filename.empty()); // Checked by VerifyImageLocation()
- component.resize(profile_delimiter_pos);
+ component.resize(profile_separator_pos);
DCHECK(!component.empty()); // Checked by VerifyImageLocation()
}
size_t slash_pos = component.rfind('/');
@@ -2085,7 +2085,7 @@
args.push_back("-Xbootclasspath:" + boot_class_path);
args.push_back("--runtime-arg");
args.push_back("-Xbootclasspath-locations:" + boot_class_path_locations);
- args.push_back("--boot-image=" + Join(dependencies, ':'));
+ args.push_back("--boot-image=" + Join(dependencies, kComponentSeparator));
for (size_t i = bcp_index; i != bcp_end; ++i) {
args.push_back("--dex-file=" + boot_class_path_[i]);
args.push_back("--dex-location=" + boot_class_path_locations_[i]);
@@ -2097,6 +2097,13 @@
args.push_back("--single-image");
args.push_back("--image-format=uncompressed");
+ // We currently cannot guarantee that the boot class path has no verification failures.
+ // And we do not want to compile anything, compilation should be done by JIT in zygote.
+ args.push_back("--compiler-filter=verify");
+
+ // Pass the profile.
+ args.push_back("--profile-file=" + profile_filename);
+
// Do not let the file descriptor numbers change the compilation output.
args.push_back("--avoid-storing-invocation");
@@ -2106,6 +2113,7 @@
args.push_back("--host");
}
+ // Image compiler options go last to allow overriding above args, such as --compiler-filter.
for (const std::string& compiler_option : runtime->GetImageCompilerOptions()) {
args.push_back(compiler_option);
}
@@ -2198,7 +2206,7 @@
DCHECK(!validate || StartsWith(*oat_checksums, "i"));
std::vector<std::string> components;
- Split(image_location_, ':', &components);
+ Split(image_location_, kComponentSeparator, &components);
size_t named_components_count = 0u;
if (!VerifyImageLocation(components, &named_components_count, error_msg)) {
return false;
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index 2b42381..ab31be8 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -39,6 +39,11 @@
return kSpaceTypeImageSpace;
}
+ // The separator for boot image location components.
+ static constexpr char kComponentSeparator = ':';
+ // The separator for profile filename.
+ static constexpr char kProfileSeparator = '!';
+
// Load boot image spaces for specified boot class path, image location, instruction set, etc.
//
// On successful return, the loaded spaces are added to boot_image_spaces (which must be