Skip to content

Commit

Permalink
Compile the entire bootclasspath on device.
Browse files Browse the repository at this point in the history
Most of the changes in this CL are renaming and comment changes. The
main behavior changes are:
1. Adding all bootclasspath jars (including the ones in the ART APEX) to
   `--dex-file` and `--dex-fd`.
2. Adding both the ART boot profile and the framework profile to
   `--profile-fd`.
3. Replacing the `--boot-image` flag with `--base` for compiling boot
   classpath jars.
4. Renaming the boot image on /data from `boot-framework.art` to
   `boot.art`.
5. Updating the `--boot-image` flag for compiling system_server jars.
6. Updating the default boot image location that the runtime uses.

Bug: 203492478
Test: atest art_standalone_odrefresh_tests
Test: atest art_standalone_artd_tests
Test: atest odsign_e2e_tests
Change-Id: If56bc96ec6f38335f3e8e1ad3085e231baacb6fc
  • Loading branch information
jiakaiz-g authored and Treehugger Robot committed Jan 12, 2022
1 parent 2041fda commit 884e22f
Show file tree
Hide file tree
Showing 16 changed files with 299 additions and 266 deletions.
2 changes: 1 addition & 1 deletion artd/binder/private/com/android/art/DexoptBcpExtArgs.aidl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ parcelable DexoptBcpExtArgs {
// manually.
String[] bootClasspaths;
int[] bootClasspathFds;
int profileFd = -1;
int[] profileFds;
int dirtyImageObjectsFd = -1;
// Output file descriptors
int oatFd = -1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ parcelable DexoptSystemServerArgs {
String dexPath;
String oatLocation;
String[] classloaderContext;
boolean isBootImageOnSystem;
String bootImage;
boolean classloaderContextAsParent;

// SECURITY: The server may accept the request to produce code for the specified architecture,
Expand Down
32 changes: 6 additions & 26 deletions artd/libdexopt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@ using aidl::com::android::art::Isa;
using android::base::Error;
using android::base::Result;

std::string GetBootImage() {
// Typically "/apex/com.android.art/javalib/boot.art".
return art::GetArtRoot() + "/javalib/boot.art";
}

std::string GetEnvironmentVariableOrDie(const char* name) {
const char* value = getenv(name);
LOG_ALWAYS_FATAL_IF(value == nullptr, "%s is not defined.", name);
Expand Down Expand Up @@ -206,8 +201,10 @@ Result<void> AddDex2oatArgsFromBcpExtensionArgs(const DexoptBcpExtArgs& args,

cmdline.emplace_back("--instruction-set=" + ToInstructionSetString(args.isa));

if (args.profileFd >= 0) {
cmdline.emplace_back(android::base::StringPrintf("--profile-file-fd=%d", args.profileFd));
if (!args.profileFds.empty()) {
for (int fd : args.profileFds) {
cmdline.emplace_back(android::base::StringPrintf("--profile-file-fd=%d", fd));
}
cmdline.emplace_back("--compiler-filter=speed-profile");
} else {
cmdline.emplace_back("--compiler-filter=speed");
Expand All @@ -216,8 +213,7 @@ Result<void> AddDex2oatArgsFromBcpExtensionArgs(const DexoptBcpExtArgs& args,
// Compile as a single image for fewer files and slightly less memory overhead.
cmdline.emplace_back("--single-image");

// Set boot-image and expectation of compiling boot classpath extensions.
cmdline.emplace_back("--boot-image=" + GetBootImage());
cmdline.emplace_back(android::base::StringPrintf("--base=0x%08x", ART_BASE_ADDRESS));

if (args.dirtyImageObjectsFd >= 0) {
cmdline.emplace_back(android::base::StringPrintf("--dirty-image-objects-fd=%d",
Expand Down Expand Up @@ -321,23 +317,7 @@ Result<void> AddDex2oatArgsFromSystemServerArgs(const DexoptSystemServerArgs& ar
android::base::Join(args.classloaderFds, ':'));
}

// Derive boot image
// b/197176583
// If the boot extension artifacts are not on /data, then boot extensions are not re-compiled
// and the artifacts must exist on /system.
std::vector<std::string> jar_paths = android::base::Split(GetDex2oatBootClasspath(), ":");
auto iter = std::find_if_not(jar_paths.begin(), jar_paths.end(), &LocationIsOnArtModule);
if (iter == jar_paths.end()) {
return Error() << "Missing BCP extension compatible JAR";
}
const std::string& first_boot_extension_compatible_jars = *iter;
// TODO(197176583): Support compiling against BCP extension in /system.
const std::string extension_image = GetBootImagePath(args.isBootImageOnSystem,
first_boot_extension_compatible_jars);
if (extension_image.empty()) {
return Error() << "Can't identify the first boot extension compatible jar";
}
cmdline.emplace_back("--boot-image=" + GetBootImage() + ":" + extension_image);
cmdline.emplace_back("--boot-image=" + args.bootImage);

AddDex2OatConcurrencyArguments(cmdline, args.threads, args.cpuSet);

Expand Down
97 changes: 51 additions & 46 deletions artd/libdexopt_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class LibDexoptTest : public CommonArtTest {
default_bcp_ext_args_.bootClasspaths = android::base::Split(
GetEnvironmentVariableOrDie("DEX2OATBOOTCLASSPATH"), ":"); // from art_artd_tests.xml
default_bcp_ext_args_.bootClasspathFds = {21, 22};
default_bcp_ext_args_.profileFd = 30;
default_bcp_ext_args_.profileFds = {30, 31};
default_bcp_ext_args_.dirtyImageObjectsFd = 31;
default_bcp_ext_args_.imageFd = 90;
default_bcp_ext_args_.vdexFd = 91;
Expand Down Expand Up @@ -90,7 +90,7 @@ class LibDexoptTest : public CommonArtTest {
default_system_server_args_.compilerFilter = CompilerFilter::SPEED_PROFILE;
default_system_server_args_.cpuSet = {0, 1};
default_system_server_args_.threads = 42;
default_system_server_args_.isBootImageOnSystem = true;
default_system_server_args_.bootImage = "/path/to/boot.art";
ASSERT_EQ(default_system_server_args_.bootClasspaths.size(),
default_system_server_args_.bootClasspathFds.size());
}
Expand Down Expand Up @@ -134,32 +134,35 @@ TEST_F(LibDexoptTest, AddDex2oatArgsFromBcpExtensionArgs) {
{
std::vector<std::string> cmdline = Dex2oatArgsFromBcpExtensionArgs(default_bcp_ext_args_);

EXPECT_THAT(cmdline, AllOf(
Contains("--dex-fd=10"),
Contains("--dex-fd=11"),
Contains("--dex-file=/path/to/foo.jar"),
Contains("--dex-file=/path/to/bar.jar"),
Contains(HasSubstr("-Xbootclasspath:")),
Contains("-Xbootclasspathfds:21:22"),

Contains("--profile-file-fd=30"),
Contains("--compiler-filter=speed-profile"),

Contains("--image-fd=90"),
Contains("--output-vdex-fd=91"),
Contains("--oat-fd=92"),
Contains("--oat-location=/oat/location/bar.odex"),

Contains("--dirty-image-objects-fd=31"),
Contains("--instruction-set=x86_64"),
Contains("--cpu-set=0,1"),
Contains("-j42")));
EXPECT_THAT(cmdline,
AllOf(Contains("--dex-fd=10"),
Contains("--dex-fd=11"),
Contains("--dex-file=/path/to/foo.jar"),
Contains("--dex-file=/path/to/bar.jar"),
Contains(HasSubstr("-Xbootclasspath:")),
Contains("-Xbootclasspathfds:21:22"),

Contains("--profile-file-fd=30"),
Contains("--profile-file-fd=31"),
Contains("--compiler-filter=speed-profile"),

Contains("--image-fd=90"),
Contains("--output-vdex-fd=91"),
Contains("--oat-fd=92"),
Contains("--oat-location=/oat/location/bar.odex"),

Contains("--dirty-image-objects-fd=31"),
Contains("--instruction-set=x86_64"),
Contains("--cpu-set=0,1"),
Contains("-j42"),

Contains(HasSubstr("--base="))));
}

// No profile
{
auto args = default_bcp_ext_args_;
args.profileFd = -1;
args.profileFds = {};
std::vector<std::string> cmdline = Dex2oatArgsFromBcpExtensionArgs(args);

EXPECT_THAT(cmdline, AllOf(
Expand Down Expand Up @@ -224,29 +227,31 @@ TEST_F(LibDexoptTest, AddDex2oatArgsFromSystemServerArgs) {
{
std::vector<std::string> cmdline = Dex2oatArgsFromSystemServerArgs(default_system_server_args_);

EXPECT_THAT(cmdline, AllOf(
Contains("--dex-fd=10"),
Contains("--dex-file=/path/to/foo.jar"),
Contains(HasSubstr("-Xbootclasspath:")),
Contains("-Xbootclasspathfds:21:22:23"),
Contains("-Xbootclasspathimagefds:-1:31:-1"),
Contains("-Xbootclasspathvdexfds:-1:32:-1"),
Contains("-Xbootclasspathoatfds:-1:33:-1"),

Contains("--profile-file-fd=11"),
Contains("--compiler-filter=speed-profile"),

Contains("--app-image-fd=90"),
Contains("--output-vdex-fd=91"),
Contains("--oat-fd=92"),
Contains("--oat-location=/oat/location/bar.odex"),

Contains("--class-loader-context-fds=40:41"),
Contains("--class-loader-context=PCL[/cl/abc.jar:/cl/def.jar]"),

Contains("--instruction-set=x86_64"),
Contains("--cpu-set=0,1"),
Contains("-j42")));
EXPECT_THAT(cmdline,
AllOf(Contains("--dex-fd=10"),
Contains("--dex-file=/path/to/foo.jar"),
Contains(HasSubstr("-Xbootclasspath:")),
Contains("-Xbootclasspathfds:21:22:23"),
Contains("-Xbootclasspathimagefds:-1:31:-1"),
Contains("-Xbootclasspathvdexfds:-1:32:-1"),
Contains("-Xbootclasspathoatfds:-1:33:-1"),

Contains("--profile-file-fd=11"),
Contains("--compiler-filter=speed-profile"),

Contains("--app-image-fd=90"),
Contains("--output-vdex-fd=91"),
Contains("--oat-fd=92"),
Contains("--oat-location=/oat/location/bar.odex"),

Contains("--class-loader-context-fds=40:41"),
Contains("--class-loader-context=PCL[/cl/abc.jar:/cl/def.jar]"),

Contains("--instruction-set=x86_64"),
Contains("--cpu-set=0,1"),
Contains("-j42"),

Contains("--boot-image=/path/to/boot.art")));
}

// Test different compiler filters
Expand Down
72 changes: 14 additions & 58 deletions libartbase/base/file_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -283,65 +283,33 @@ std::string GetArtApexData() {
return GetAndroidDir(kArtApexDataEnvVar, kArtApexDataDefaultPath, /*must_exist=*/false);
}

static std::string GetFirstBootClasspathExtensionJar(const std::string& android_root) {
DCHECK(kIsTargetBuild);

// This method finds the first non-APEX DEX file in the boot class path as defined by the
// DEX2OATBOOTCLASSPATH environment variable. This corresponds to the first boot classpath
// extension (see IMAGE SECTION documentation in image.h). When on-device signing is used the
// boot class extensions are compiled together as a single image with a name derived from the
// first extension. This first boot classpath extension is usually
// '/system/framework/framework.jar'.
//
// DEX2OATBOOTCLASSPATH is generated at build time by in the init.environ.rc.in:
// ${ANDROID_BUILD_TOP}/system/core/rootdir/Android.mk
// and initialized on Android by init in init.environ.rc:
// ${ANDROID_BUILD_TOP}/system/core/rootdir/init.environ.rc.in.
// It is used by installd too.
const char* bcp = getenv("DEX2OATBOOTCLASSPATH");
const std::string kDefaultBcpExtensionJar = android_root + "/framework/framework.jar";
if (bcp != nullptr) {
for (std::string_view component : SplitString(bcp, ':')) {
if (component.empty()) {
continue;
}
if (!LocationIsOnApex(component)) {
return std::string{component};
}
}
}
return kDefaultBcpExtensionJar;
}

std::string GetDefaultBootImageLocation(const std::string& android_root,
bool deny_art_apex_data_files) {
constexpr static const char* kJavalibBootArt = "javalib/boot.art";
constexpr static const char* kEtcBootImageProf = "etc/boot-image.prof";

// Boot image consists of two parts:
// - the primary boot image in the ART APEX (contains the Core Libraries)
// - the boot image extensions (contains framework libraries) on the system partition, or
// in the ART APEX data directory, if an update for the ART module has been been installed.
// If an update for the ART module has been been installed, a single boot image for the entire
// bootclasspath is in the ART APEX data directory.
if (kIsTargetBuild && !deny_art_apex_data_files) {
// If the ART APEX has been updated, the compiled boot image extension will be in the ART APEX
// data directory (assuming there is space and we trust the artifacts there). Otherwise, for a factory installed ART APEX it is
// under $ANDROID_ROOT/framework/.
const std::string first_extension_jar{GetFirstBootClasspathExtensionJar(android_root)};
const std::string boot_extension_image = GetApexDataBootImage(first_extension_jar);
const std::string boot_extension_filename =
GetSystemImageFilename(boot_extension_image.c_str(), kRuntimeISA);
if (OS::FileExists(boot_extension_filename.c_str(), /*check_file_type=*/true)) {
return StringPrintf("%s/%s:%s!%s/%s",
const std::string boot_image =
GetApexDataDalvikCacheDirectory(InstructionSet::kNone) + "/boot.art";
const std::string boot_image_filename = GetSystemImageFilename(boot_image.c_str(), kRuntimeISA);
if (OS::FileExists(boot_image_filename.c_str(), /*check_file_type=*/true)) {
return StringPrintf("%s!%s/%s!%s/%s",
boot_image.c_str(),
kAndroidArtApexDefaultPath,
kJavalibBootArt,
boot_extension_image.c_str(),
kEtcBootImageProf,
android_root.c_str(),
kEtcBootImageProf);
} else if (errno == EACCES) {
// Additional warning for potential SELinux misconfiguration.
PLOG(ERROR) << "Default boot image check failed, could not stat: " << boot_extension_image;
PLOG(ERROR) << "Default boot image check failed, could not stat: " << boot_image_filename;
}
}
// Boot image consists of two parts:
// - the primary boot image in the ART APEX (contains the Core Libraries)
// - the boot image extensions (contains framework libraries) on the system partition
// TODO(b/211973309): Update this once the primary boot image is moved.
return StringPrintf("%s/%s:%s/framework/boot-framework.art!%s/%s",
kAndroidArtApexDefaultPath,
kJavalibBootArt,
Expand All @@ -358,18 +326,6 @@ std::string GetDefaultBootImageLocation(std::string* error_msg) {
return GetDefaultBootImageLocation(android_root, /*deny_art_apex_data_files=*/false);
}

std::string GetBootImagePath(bool on_system, const std::string& jar_path) {
if (on_system) {
const std::string jar_name = android::base::Basename(jar_path);
const std::string image_name = ReplaceFileExtension(jar_name, "art");
// Typically "/system/framework/boot-framework.art".
return StringPrintf("%s/framework/boot-%s", GetAndroidRoot().c_str(), image_name.c_str());
} else {
// Typically "/data/misc/apexdata/com.android.art/dalvik-cache/boot-framework.art".
return GetApexDataBootImage(jar_path);
}
}

static /*constinit*/ std::string_view dalvik_cache_sub_dir = "dalvik-cache";

void OverrideDalvikCacheSubDirectory(std::string sub_dir) {
Expand Down
3 changes: 0 additions & 3 deletions libartbase/base/file_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,6 @@ std::string GetDefaultBootImageLocation(std::string* error_msg);
std::string GetDefaultBootImageLocation(const std::string& android_root,
bool deny_art_apex_data_files);

// Returns the boot image path of the provided jar, on /system or /data.
std::string GetBootImagePath(bool on_system, const std::string& jar_path);

// Allows the name to be used for the dalvik cache directory (normally "dalvik-cache") to be
// overridden with a new value.
void OverrideDalvikCacheSubDirectory(std::string sub_dir);
Expand Down
2 changes: 1 addition & 1 deletion odrefresh/odr_artifacts.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace odrefresh {
// A grouping of odrefresh generated artifacts.
class OdrArtifacts {
public:
static OdrArtifacts ForBootImageExtension(const std::string& image_path) {
static OdrArtifacts ForBootImage(const std::string& image_path) {
return OdrArtifacts(image_path, "oat");
}

Expand Down
4 changes: 2 additions & 2 deletions odrefresh/odr_artifacts_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace odrefresh {

static constexpr const char* kOdrefreshArtifactDirectory = "/test/dir";

TEST(OdrArtifactsTest, ForBootImageExtension) {
TEST(OdrArtifactsTest, ForBootImage) {
ScopedUnsetEnvironmentVariable no_env("ART_APEX_DATA");
setenv("ART_APEX_DATA", kOdrefreshArtifactDirectory, /* overwrite */ 1);

Expand All @@ -37,7 +37,7 @@ TEST(OdrArtifactsTest, ForBootImageExtension) {
const std::string image_filename =
GetSystemImageFilename(image_location.c_str(), InstructionSet::kArm64);

const auto artifacts = OdrArtifacts::ForBootImageExtension(image_filename);
const auto artifacts = OdrArtifacts::ForBootImage(image_filename);
CHECK_EQ(std::string(kOdrefreshArtifactDirectory) + "/dalvik-cache/arm64/boot-framework.art",
artifacts.ImagePath());
CHECK_EQ(std::string(kOdrefreshArtifactDirectory) + "/dalvik-cache/arm64/boot-framework.oat",
Expand Down
2 changes: 1 addition & 1 deletion odrefresh/odr_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class OdrConfig final {

const std::string& GetApexInfoListFile() const { return apex_info_list_file_; }

std::vector<InstructionSet> GetBootExtensionIsas() const {
std::vector<InstructionSet> GetBootClasspathIsas() const {
const auto [isa32, isa64] = GetPotentialInstructionSets();
switch (zygote_kind_) {
case ZygoteKind::kZygote32:
Expand Down
Loading

0 comments on commit 884e22f

Please sign in to comment.