diff options
author | Jiakai Zhang <jiakaiz@google.com> | 2023-06-09 11:34:59 +0100 |
---|---|---|
committer | Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> | 2023-06-12 09:43:51 +0000 |
commit | fff86f6dc8dff440ff8cf56cf87fad288a1b06f2 (patch) | |
tree | ad827e5c596a303165b5c6fbf4bbb96392e8895c | |
parent | bacf884bb31a67489a6fba24b1b2e98587707102 (diff) | |
download | art-fff86f6dc8dff440ff8cf56cf87fad288a1b06f2.tar.gz |
Pass the cache-info fd from odrefresh to dex2oat.
This allows dex2oat in CompOS to read the cache-info file. Otherwise,
CompOS will generate invalid artifacts that put the device into JIT
Zygote.
Bug: 286422732
Test: atest art_standalone_odrefresh_tests
Test: (on udc-dev) -
1. adb shell device_config set_sync_disabled_for_tests persistent
2. adb shell device_config put runtime_native_boot enable_uffd_gc true
3. atest odsign_e2e_tests_full:CompOsSigningHostTest
Change-Id: I4c6c5fb13a93b58ce53f46cd8d6d9c1e05ecd720
Merged-In: I4c6c5fb13a93b58ce53f46cd8d6d9c1e05ecd720
(cherry picked from commit d609d0762b9d8c473da4fa8de1122733b2a7a50c)
-rw-r--r-- | dex2oat/dex2oat_options.cc | 5 | ||||
-rw-r--r-- | odrefresh/odrefresh.cc | 19 | ||||
-rw-r--r-- | odrefresh/odrefresh_test.cc | 22 | ||||
-rw-r--r-- | runtime/gc/collector/mark_compact.cc | 61 |
4 files changed, 94 insertions, 13 deletions
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc index cf600087a3..4da219897b 100644 --- a/dex2oat/dex2oat_options.cc +++ b/dex2oat/dex2oat_options.cc @@ -462,7 +462,10 @@ Parser CreateDex2oatArgumentParser() { .Define("--force-palette-compilation-hooks") .WithHelp("Force PaletteNotify{Start,End}Dex2oatCompilation calls.") .IntoKey(M::ForcePaletteCompilationHooks) - .Ignore({"--comments=_"}); + .Ignore({ + "--comments=_", + "--cache-info-fd=_", // Handled in mark_compact.cc. + }); // clang-format on AddCompilerOptionsArgumentParserOptions<Dex2oatArgumentMap>(*parser_builder); diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc index cdec0a35af..7bbc922a8c 100644 --- a/odrefresh/odrefresh.cc +++ b/odrefresh/odrefresh.cc @@ -496,6 +496,19 @@ Result<void> AddBootClasspathFds(/*inout*/ std::vector<std::string>& args, return {}; } +Result<void> AddCacheInfoFd(/*inout*/ std::vector<std::string>& args, + /*inout*/ std::vector<std::unique_ptr<File>>& readonly_files_raii, + const std::string& cache_info_filename) { + std::unique_ptr<File> cache_info_file(OS::OpenFileForReading(cache_info_filename.c_str())); + if (cache_info_file == nullptr) { + return ErrnoErrorf("Failed to open a cache info file '{}'", cache_info_file); + } + + args.emplace_back("--cache-info-fd=" + std::to_string(cache_info_file->Fd())); + readonly_files_raii.push_back(std::move(cache_info_file)); + return {}; +} + std::string GetBootImageComponentBasename(const std::string& jar_path, bool is_first_jar) { if (is_first_jar) { return kFirstBootImageBasename; @@ -1653,6 +1666,12 @@ WARN_UNUSED CompilationResult OnDeviceRefresh::RunDex2oat( return CompilationResult::Error(OdrMetrics::Status::kUnknown, result.error().message()); } + // dex2oat reads some system properties from cache-info.xml generated by odrefresh. + result = AddCacheInfoFd(args, readonly_files_raii, cache_info_filename_); + if (!result.ok()) { + return CompilationResult::Error(OdrMetrics::Status::kUnknown, result.error().message()); + } + for (const std::string& dex_file : dex_files) { std::string actual_path = RewriteParentDirectoryIfNeeded(dex_file); args.emplace_back("--dex-file=" + dex_file); diff --git a/odrefresh/odrefresh_test.cc b/odrefresh/odrefresh_test.cc index 6c99cdda40..8ebeeab6bb 100644 --- a/odrefresh/odrefresh_test.cc +++ b/odrefresh/odrefresh_test.cc @@ -236,8 +236,9 @@ class OdRefreshTest : public CommonArtTest { mock_exec_utils_ = mock_exec_utils.get(); metrics_ = std::make_unique<OdrMetrics>(dalvik_cache_dir_); + cache_info_xml_ = dalvik_cache_dir_ + "/cache-info.xml"; odrefresh_ = std::make_unique<OnDeviceRefresh>( - config_, dalvik_cache_dir_ + "/cache-info.xml", std::move(mock_exec_utils)); + config_, cache_info_xml_, std::move(mock_exec_utils)); } void TearDown() override { @@ -273,6 +274,7 @@ class OdRefreshTest : public CommonArtTest { std::string services_jar_profile_; std::string dirty_image_objects_file_; std::string preloaded_classes_file_; + std::string cache_info_xml_; }; TEST_F(OdRefreshTest, PrimaryBootImage) { @@ -291,7 +293,8 @@ TEST_F(OdRefreshTest, PrimaryBootImage) { ElementsAre(FdOf(core_oj_jar_), FdOf(framework_jar_)))), Contains(Flag("--oat-location=", dalvik_cache_dir_ + "/x86_64/boot.oat")), Contains(Flag("--base=", _)), - Not(Contains(Flag("--boot-image=", _)))))) + Not(Contains(Flag("--boot-image=", _))), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) .WillOnce(Return(0)); // Ignore the invocation for the mainline extension. @@ -330,7 +333,8 @@ TEST_F(OdRefreshTest, BootImageMainlineExtension) { FdOf(framework_wifi_jar_)))), Contains(Flag("--oat-location=", dalvik_cache_dir_ + "/x86_64/boot-conscrypt.oat")), Not(Contains(Flag("--base=", _))), - Contains(Flag("--boot-image=", _))))) + Contains(Flag("--boot-image=", _)), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) .WillOnce(Return(0)); EXPECT_EQ(odrefresh_->Compile( @@ -429,14 +433,16 @@ TEST_F(OdRefreshTest, AllSystemServerJars) { EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", location_provider_jar_)), Contains("--class-loader-context=PCL[]"), - Not(Contains(Flag("--class-loader-context-fds=", _)))))) + Not(Contains(Flag("--class-loader-context-fds=", _))), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) .WillOnce(Return(0)); EXPECT_CALL( *mock_exec_utils_, DoExecAndReturnCode( AllOf(Contains(Flag("--dex-file=", services_jar_)), Contains(Flag("--class-loader-context=", "PCL[{}]"_format(location_provider_jar_))), - Contains(Flag("--class-loader-context-fds=", FdOf(location_provider_jar_)))))) + Contains(Flag("--class-loader-context-fds=", FdOf(location_provider_jar_))), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) .WillOnce(Return(0)); EXPECT_CALL( *mock_exec_utils_, @@ -445,7 +451,8 @@ TEST_F(OdRefreshTest, AllSystemServerJars) { Contains(Flag("--class-loader-context=", "PCL[];PCL[{}:{}]"_format(location_provider_jar_, services_jar_))), Contains(ListFlag("--class-loader-context-fds=", - ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_))))))) + ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) .WillOnce(Return(0)); EXPECT_CALL( *mock_exec_utils_, @@ -454,7 +461,8 @@ TEST_F(OdRefreshTest, AllSystemServerJars) { Contains(Flag("--class-loader-context=", "PCL[];PCL[{}:{}]"_format(location_provider_jar_, services_jar_))), Contains(ListFlag("--class-loader-context-fds=", - ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_))))))) + ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) .WillOnce(Return(0)); EXPECT_EQ( diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc index 82cd13e0da..bb34068fb1 100644 --- a/runtime/gc/collector/mark_compact.cc +++ b/runtime/gc/collector/mark_compact.cc @@ -29,10 +29,15 @@ #include <fstream> #include <numeric> +#include <string> +#include <string_view> +#include <vector> #include "android-base/file.h" #include "android-base/parsebool.h" +#include "android-base/parseint.h" #include "android-base/properties.h" +#include "android-base/strings.h" #include "base/file_utils.h" #include "base/memfd.h" #include "base/quasi_atomic.h" @@ -162,18 +167,64 @@ static gc::CollectorType FetchCmdlineGcType() { } #ifdef ART_TARGET_ANDROID +static int GetOverrideCacheInfoFd() { + std::string args_str; + if (!android::base::ReadFileToString("/proc/self/cmdline", &args_str)) { + LOG(WARNING) << "Failed to load /proc/self/cmdline"; + return -1; + } + std::vector<std::string_view> args; + Split(std::string_view(args_str), /*separator=*/'\0', &args); + for (std::string_view arg : args) { + if (android::base::ConsumePrefix(&arg, "--cache-info-fd=")) { // This is a dex2oat flag. + int fd; + if (!android::base::ParseInt(std::string(arg), &fd)) { + LOG(ERROR) << "Failed to parse --cache-info-fd (value: '" << arg << "')"; + return -1; + } + return fd; + } + } + return -1; +} + static bool GetCachedBoolProperty(const std::string& key, bool default_value) { - std::string path = GetApexDataDalvikCacheDirectory(InstructionSet::kNone) + "/cache-info.xml"; - std::optional<com::android::art::CacheInfo> cache_info = com::android::art::read(path.c_str()); + // For simplicity, we don't handle multiple calls because otherwise we would have to reset the fd. + static bool called = false; + CHECK(!called) << "GetCachedBoolProperty can be called only once"; + called = true; + + std::string cache_info_contents; + int fd = GetOverrideCacheInfoFd(); + if (fd >= 0) { + if (!android::base::ReadFdToString(fd, &cache_info_contents)) { + PLOG(ERROR) << "Failed to read cache-info from fd " << fd; + return default_value; + } + } else { + std::string path = GetApexDataDalvikCacheDirectory(InstructionSet::kNone) + "/cache-info.xml"; + if (!android::base::ReadFileToString(path, &cache_info_contents)) { + // If the file is not found, then we are in chroot or in a standalone runtime process (e.g., + // IncidentHelper), or odsign/odrefresh failed to generate and sign the cache info. There's + // nothing we can do. + if (errno != ENOENT) { + PLOG(ERROR) << "Failed to read cache-info from the default path"; + } + return default_value; + } + } + + std::optional<com::android::art::CacheInfo> cache_info = + com::android::art::parse(cache_info_contents.c_str()); if (!cache_info.has_value()) { - // We are in chroot or in a standalone runtime process (e.g., IncidentHelper), or - // odsign/odrefresh failed to generate and sign the cache info. There's nothing we can do. + // This should never happen. + LOG(ERROR) << "Failed to parse cache-info"; return default_value; } const com::android::art::KeyValuePairList* list = cache_info->getFirstSystemProperties(); if (list == nullptr) { // This should never happen. - LOG(ERROR) << "Missing system properties from cache-info."; + LOG(ERROR) << "Missing system properties from cache-info"; return default_value; } const std::vector<com::android::art::KeyValuePair>& properties = list->getItem(); |