Extract dex file if it is uncompressed but unaligned
A dex file would normally only be left in the zip file if it was both
uncompressed and unaligned, but explicitly setting CopyOptions::kNever
through --copy-dex-file=false would only check if the dex file was
uncompressed, not if it was aligned. Add a required alignment
argument to ZipEntry::MapDirectlyOrExtract so that the contents
will be extracted into memory if they don't meet the alignment
requirement.
Bug: 119412419
Test: m test-art-host-gtest-oat_writer_test
Change-Id: I4587e22165ee0a951ffca7db9a6f5c0d1ed2e56a
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 12a8354..904ed7f 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1400,7 +1400,8 @@
MemMap input_file = zip_entry->MapDirectlyOrExtract(
VdexFile::kVdexNameInDmFile,
kDexMetadata,
- &error_msg);
+ &error_msg,
+ alignof(VdexFile));
if (!input_file.IsValid()) {
LOG(WARNING) << "Could not open vdex file in DexMetadata archive: " << error_msg;
} else {
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 7f2877f..fd3b95a 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -3667,7 +3667,7 @@
for (OatDexFile& oat_dex_file : oat_dex_files_) {
std::string error_msg;
maps.emplace_back(oat_dex_file.source_.GetZipEntry()->MapDirectlyOrExtract(
- oat_dex_file.dex_file_location_data_, "zipped dex", &error_msg));
+ oat_dex_file.dex_file_location_data_, "zipped dex", &error_msg, alignof(DexFile)));
MemMap* map = &maps.back();
if (!map->IsValid()) {
LOG(ERROR) << error_msg;
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index af02bfc..89c8ec8 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -119,7 +119,8 @@
return false;
}
}
- return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
+ return DoWriteElf(
+ vdex_file, oat_file, oat_writer, key_value_store, verify, CopyOption::kOnlyIfCompressed);
}
bool WriteElf(File* vdex_file,
@@ -127,6 +128,7 @@
const std::vector<const char*>& dex_filenames,
SafeMap<std::string, std::string>& key_value_store,
bool verify,
+ CopyOption copy,
ProfileCompilationInfo* profile_compilation_info) {
TimingLogger timings("WriteElf", false, false);
ClearBootImageOption();
@@ -139,7 +141,7 @@
return false;
}
}
- return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
+ return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify, copy);
}
bool WriteElf(File* vdex_file,
@@ -147,7 +149,8 @@
File&& zip_fd,
const char* location,
SafeMap<std::string, std::string>& key_value_store,
- bool verify) {
+ bool verify,
+ CopyOption copy) {
TimingLogger timings("WriteElf", false, false);
ClearBootImageOption();
OatWriter oat_writer(*compiler_options_,
@@ -157,14 +160,15 @@
if (!oat_writer.AddZippedDexFilesSource(std::move(zip_fd), location)) {
return false;
}
- return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify);
+ return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify, copy);
}
bool DoWriteElf(File* vdex_file,
File* oat_file,
OatWriter& oat_writer,
SafeMap<std::string, std::string>& key_value_store,
- bool verify) {
+ bool verify,
+ CopyOption copy) {
std::unique_ptr<ElfWriter> elf_writer = CreateElfWriterQuick(
compiler_driver_->GetCompilerOptions(),
oat_file);
@@ -178,7 +182,7 @@
&key_value_store,
verify,
/*update_input_vdex=*/ false,
- CopyOption::kOnlyIfCompressed,
+ copy,
&opened_dex_files_maps,
&opened_dex_files)) {
return false;
@@ -258,7 +262,7 @@
}
void TestDexFileInput(bool verify, bool low_4gb, bool use_profile);
- void TestZipFileInput(bool verify);
+ void TestZipFileInput(bool verify, CopyOption copy);
void TestZipFileInputWithEmptyDex();
std::unique_ptr<QuickCompilerCallbacks> callbacks_;
@@ -588,6 +592,7 @@
input_filenames,
key_value_store,
verify,
+ CopyOption::kOnlyIfCompressed,
profile_compilation_info.get());
// In verify mode, we expect failure.
@@ -664,7 +669,7 @@
TestDexFileInput(/*verify*/true, /*low_4gb*/false, /*use_profile*/true);
}
-void OatTest::TestZipFileInput(bool verify) {
+void OatTest::TestZipFileInput(bool verify, CopyOption copy) {
TimingLogger timings("OatTest::DexFileInput", false, false);
ScratchFile zip_file;
@@ -720,6 +725,7 @@
input_filenames,
key_value_store,
verify,
+ copy,
/*profile_compilation_info=*/ nullptr);
if (verify) {
@@ -770,7 +776,8 @@
std::move(zip_fd),
zip_file.GetFilename().c_str(),
key_value_store,
- verify);
+ verify,
+ copy);
if (verify) {
ASSERT_FALSE(success);
} else {
@@ -810,11 +817,15 @@
}
TEST_F(OatTest, ZipFileInputCheckOutput) {
- TestZipFileInput(false);
+ TestZipFileInput(false, CopyOption::kOnlyIfCompressed);
+}
+
+TEST_F(OatTest, ZipFileInputCheckOutputWithoutCopy) {
+ TestZipFileInput(false, CopyOption::kNever);
}
TEST_F(OatTest, ZipFileInputCheckVerifier) {
- TestZipFileInput(true);
+ TestZipFileInput(true, CopyOption::kOnlyIfCompressed);
}
void OatTest::TestZipFileInputWithEmptyDex() {
@@ -834,6 +845,7 @@
input_filenames,
key_value_store,
/*verify=*/ false,
+ CopyOption::kOnlyIfCompressed,
profile_compilation_info.get());
ASSERT_FALSE(success);
}
diff --git a/libartbase/base/zip_archive.cc b/libartbase/base/zip_archive.cc
index 8ceea83..a7f4b28 100644
--- a/libartbase/base/zip_archive.cc
+++ b/libartbase/base/zip_archive.cc
@@ -189,8 +189,9 @@
MemMap ZipEntry::MapDirectlyOrExtract(const char* zip_filename,
const char* entry_filename,
- std::string* error_msg) {
- if (IsUncompressed() && GetFileDescriptor(handle_) >= 0) {
+ std::string* error_msg,
+ size_t alignment) {
+ if (IsUncompressed() && IsAlignedTo(alignment) && GetFileDescriptor(handle_) >= 0) {
std::string local_error_msg;
MemMap ret = MapDirectlyFromFile(zip_filename, &local_error_msg);
if (ret.IsValid()) {
diff --git a/libartbase/base/zip_archive.h b/libartbase/base/zip_archive.h
index d326a9e..fc04ec1 100644
--- a/libartbase/base/zip_archive.h
+++ b/libartbase/base/zip_archive.h
@@ -59,7 +59,8 @@
MemMap MapDirectlyOrExtract(const char* zip_filename,
const char* entry_filename,
- std::string* error_msg);
+ std::string* error_msg,
+ size_t alignment);
uint32_t GetUncompressedLength();
uint32_t GetCrc32();
diff --git a/libprofile/profile/profile_compilation_info.cc b/libprofile/profile/profile_compilation_info.cc
index 6bd49a4..02f6344 100644
--- a/libprofile/profile/profile_compilation_info.cc
+++ b/libprofile/profile/profile_compilation_info.cc
@@ -1197,7 +1197,8 @@
}
// TODO(calin) pass along file names to assist with debugging.
- MemMap map = zip_entry->MapDirectlyOrExtract(kDexMetadataProfileEntry, "profile file", error);
+ MemMap map = zip_entry->MapDirectlyOrExtract(
+ kDexMetadataProfileEntry, "profile file", error, alignof(ProfileSource));
if (map.IsValid()) {
source->reset(ProfileSource::Create(std::move(map)));