summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/Android.gtest.mk19
-rw-r--r--compiler/driver/compiler_driver.cc6
-rw-r--r--compiler/driver/compiler_driver.h6
-rw-r--r--dex2oat/dex2oat.cc12
-rw-r--r--dex2oat/dex2oat_test.cc15
-rw-r--r--dex2oat/linker/image_test.h12
-rw-r--r--dex2oat/linker/oat_writer.cc68
-rw-r--r--dex2oat/linker/oat_writer.h6
-rw-r--r--dex2oat/linker/oat_writer_test.cc8
-rw-r--r--runtime/dex_file.h4
-rw-r--r--runtime/dex_file_loader.cc2
-rw-r--r--runtime/oat_file.cc50
-rw-r--r--runtime/oat_file.h9
-rw-r--r--runtime/zip_archive.cc7
-rw-r--r--runtime/zip_archive.h3
15 files changed, 176 insertions, 51 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 3c8eade773..9af6cf46b4 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -72,6 +72,11 @@ $(foreach dir,$(GTEST_DEX_DIRECTORIES), $(eval $(call build-art-test-dex,art-gte
ART_TEST_HOST_GTEST_MainStripped_DEX := $(basename $(ART_TEST_HOST_GTEST_Main_DEX))Stripped$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
ART_TEST_TARGET_GTEST_MainStripped_DEX := $(basename $(ART_TEST_TARGET_GTEST_Main_DEX))Stripped$(suffix $(ART_TEST_TARGET_GTEST_Main_DEX))
+# Create rules for MainUncompressed, a copy of Main with the classes.dex uncompressed
+# for the dex2oat tests.
+ART_TEST_HOST_GTEST_MainUncompressed_DEX := $(basename $(ART_TEST_HOST_GTEST_Main_DEX))Uncompressed$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
+ART_TEST_TARGET_GTEST_MainUncompressed_DEX := $(basename $(ART_TEST_TARGET_GTEST_Main_DEX))Uncompressed$(suffix $(ART_TEST_TARGET_GTEST_Main_DEX))
+
$(ART_TEST_HOST_GTEST_MainStripped_DEX): $(ART_TEST_HOST_GTEST_Main_DEX)
cp $< $@
$(call dexpreopt-remove-classes.dex,$@)
@@ -80,6 +85,16 @@ $(ART_TEST_TARGET_GTEST_MainStripped_DEX): $(ART_TEST_TARGET_GTEST_Main_DEX)
cp $< $@
$(call dexpreopt-remove-classes.dex,$@)
+$(ART_TEST_HOST_GTEST_MainUncompressed_DEX): $(ART_TEST_HOST_GTEST_Main_DEX) $(ZIPALIGN)
+ cp $< $@
+ $(call uncompress-dexs, $@)
+ $(call align-package, $@)
+
+$(ART_TEST_TARGET_GTEST_MainUncompressed_DEX): $(ART_TEST_TARGET_GTEST_Main_DEX) $(ZIPALIGN)
+ cp $< $@
+ $(call uncompress-dexs, $@)
+ $(call align-package, $@)
+
ART_TEST_GTEST_VerifierDeps_SRC := $(abspath $(wildcard $(LOCAL_PATH)/VerifierDeps/*.smali))
ART_TEST_GTEST_VerifierDepsMulti_SRC := $(abspath $(wildcard $(LOCAL_PATH)/VerifierDepsMulti/*.smali))
ART_TEST_HOST_GTEST_VerifierDeps_DEX := $(dir $(ART_TEST_HOST_GTEST_Main_DEX))$(subst Main,VerifierDeps,$(basename $(notdir $(ART_TEST_HOST_GTEST_Main_DEX))))$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
@@ -110,7 +125,7 @@ ART_GTEST_compiler_driver_test_DEX_DEPS := AbstractMethod StaticLeafMethods Prof
ART_GTEST_dex_cache_test_DEX_DEPS := Main Packages MethodTypes
ART_GTEST_dex_file_test_DEX_DEPS := GetMethodSignature Main Nested MultiDex
ART_GTEST_dexlayout_test_DEX_DEPS := ManyMethods
-ART_GTEST_dex2oat_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) ManyMethods Statics VerifierDeps
+ART_GTEST_dex2oat_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) ManyMethods Statics VerifierDeps MainUncompressed
ART_GTEST_dex2oat_image_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS) Statics VerifierDeps
ART_GTEST_exception_test_DEX_DEPS := ExceptionHandle
ART_GTEST_image_test_DEX_DEPS := ImageLayoutA ImageLayoutB DefaultMethods
@@ -696,6 +711,8 @@ $(foreach dir,$(GTEST_DEX_DIRECTORIES), $(eval ART_TEST_TARGET_GTEST_$(dir)_DEX
$(foreach dir,$(GTEST_DEX_DIRECTORIES), $(eval ART_TEST_HOST_GTEST_$(dir)_DEX :=))
ART_TEST_HOST_GTEST_MainStripped_DEX :=
ART_TEST_TARGET_GTEST_MainStripped_DEX :=
+ART_TEST_HOST_GTEST_MainUncompressed_DEX :=
+ART_TEST_TARGET_GTEST_MainUncompressed_DEX :=
ART_TEST_GTEST_VerifierDeps_SRC :=
ART_TEST_HOST_GTEST_VerifierDeps_DEX :=
ART_TEST_TARGET_GTEST_VerifierDeps_DEX :=
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 0ca3c8f613..d1cb175430 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -401,6 +401,12 @@ static optimizer::DexToDexCompilationLevel GetDexToDexCompilationLevel(
Thread* self, const CompilerDriver& driver, Handle<mirror::ClassLoader> class_loader,
const DexFile& dex_file, const DexFile::ClassDef& class_def)
REQUIRES_SHARED(Locks::mutator_lock_) {
+ // When the dex file is uncompressed in the APK, we do not generate a copy in the .vdex
+ // file. As a result, dex2oat will map the dex file read-only, and we only need to check
+ // that to know if we can do quickening.
+ if (dex_file.GetContainer() != nullptr && dex_file.GetContainer()->IsReadOnly()) {
+ return optimizer::DexToDexCompilationLevel::kDontDexToDexCompile;
+ }
auto* const runtime = Runtime::Current();
DCHECK(driver.GetCompilerOptions().IsQuickeningCompilationEnabled());
const char* descriptor = dex_file.GetClassDescriptor(class_def);
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index d2141e8bc7..eab15b9f49 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -102,13 +102,13 @@ class CompilerDriver {
~CompilerDriver();
- // Set dex files that will be stored in the oat file after being compiled.
+ // Set dex files associated with the oat file being compiled.
void SetDexFilesForOatFile(const std::vector<const DexFile*>& dex_files);
// Set dex files classpath.
void SetClasspathDexFiles(const std::vector<const DexFile*>& dex_files);
- // Get dex file that will be stored in the oat file after being compiled.
+ // Get dex files associated with the the oat file being compiled.
ArrayRef<const DexFile* const> GetDexFilesForOatFile() const {
return ArrayRef<const DexFile* const>(dex_files_for_oat_file_);
}
@@ -528,7 +528,7 @@ class CompilerDriver {
bool support_boot_image_fixup_;
- // List of dex files that will be stored in the oat file.
+ // List of dex files associates with the oat file.
std::vector<const DexFile*> dex_files_for_oat_file_;
CompiledMethodStorage compiled_method_storage_;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 27bec1d3e1..3f4904bb77 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1550,7 +1550,7 @@ class Dex2Oat FINAL {
for (size_t i = 0, size = oat_writers_.size(); i != size; ++i) {
rodata_.push_back(elf_writers_[i]->StartRoData());
// Unzip or copy dex files straight to the oat file.
- std::unique_ptr<MemMap> opened_dex_files_map;
+ std::vector<std::unique_ptr<MemMap>> opened_dex_files_map;
std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
// No need to verify the dex file for:
// 1) Dexlayout since it does the verification. It also may not pass the verification since
@@ -1570,14 +1570,16 @@ class Dex2Oat FINAL {
return dex2oat::ReturnCode::kOther;
}
dex_files_per_oat_file_.push_back(MakeNonOwningPointerVector(opened_dex_files));
- if (opened_dex_files_map != nullptr) {
- opened_dex_files_maps_.push_back(std::move(opened_dex_files_map));
+ if (opened_dex_files_map.empty()) {
+ DCHECK(opened_dex_files.empty());
+ } else {
+ for (std::unique_ptr<MemMap>& map : opened_dex_files_map) {
+ opened_dex_files_maps_.push_back(std::move(map));
+ }
for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
dex_file_oat_index_map_.emplace(dex_file.get(), i);
opened_dex_files_.push_back(std::move(dex_file));
}
- } else {
- DCHECK(opened_dex_files.empty());
}
}
}
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index ad287b0745..41f2c70267 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -1513,4 +1513,19 @@ TEST_F(Dex2oatDedupeCode, DedupeTest) {
EXPECT_LT(dedupe_size, no_dedupe_size);
}
+TEST_F(Dex2oatTest, UncompressedTest) {
+ std::unique_ptr<const DexFile> dex(OpenTestDexFile("MainUncompressed"));
+ std::string out_dir = GetScratchDir();
+ const std::string base_oat_name = out_dir + "/base.oat";
+ GenerateOdexForTest(dex->GetLocation(),
+ base_oat_name,
+ CompilerFilter::Filter::kQuicken,
+ { },
+ true, // expect_success
+ false, // use_fd
+ [](const OatFile& o) {
+ CHECK(!o.ContainsDexCode());
+ });
+}
+
} // namespace art
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index cedbccf7cc..208297b8f6 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -253,7 +253,7 @@ inline void CompilationHelper::Compile(CompilerDriver* driver,
}
std::vector<OutputStream*> rodata;
- std::vector<std::unique_ptr<MemMap>> opened_dex_files_map;
+ std::vector<std::unique_ptr<MemMap>> opened_dex_files_maps;
std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
// Now that we have finalized key_value_store_, start writing the oat file.
for (size_t i = 0, size = oat_writers.size(); i != size; ++i) {
@@ -266,7 +266,7 @@ inline void CompilationHelper::Compile(CompilerDriver* driver,
dex_file->GetLocation().c_str(),
dex_file->GetLocationChecksum());
- std::unique_ptr<MemMap> cur_opened_dex_files_map;
+ std::vector<std::unique_ptr<MemMap>> cur_opened_dex_files_maps;
std::vector<std::unique_ptr<const DexFile>> cur_opened_dex_files;
bool dex_files_ok = oat_writers[i]->WriteAndOpenDexFiles(
vdex_files[i].GetFile(),
@@ -276,12 +276,14 @@ inline void CompilationHelper::Compile(CompilerDriver* driver,
&key_value_store,
/* verify */ false, // Dex files may be dex-to-dex-ed, don't verify.
/* update_input_vdex */ false,
- &cur_opened_dex_files_map,
+ &cur_opened_dex_files_maps,
&cur_opened_dex_files);
ASSERT_TRUE(dex_files_ok);
- if (cur_opened_dex_files_map != nullptr) {
- opened_dex_files_map.push_back(std::move(cur_opened_dex_files_map));
+ if (!cur_opened_dex_files_maps.empty()) {
+ for (std::unique_ptr<MemMap>& cur_map : cur_opened_dex_files_maps) {
+ opened_dex_files_maps.push_back(std::move(cur_map));
+ }
for (std::unique_ptr<const DexFile>& cur_dex_file : cur_opened_dex_files) {
// dex_file_oat_index_map_.emplace(dex_file.get(), i);
opened_dex_files.push_back(std::move(cur_dex_file));
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 293078acee..9e61c42ff5 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -363,6 +363,7 @@ OatWriter::OatWriter(bool compiling_boot_image,
compiler_driver_(nullptr),
image_writer_(nullptr),
compiling_boot_image_(compiling_boot_image),
+ only_contains_uncompressed_zip_entries_(false),
dex_files_(nullptr),
vdex_size_(0u),
vdex_dex_files_offset_(0u),
@@ -636,7 +637,7 @@ bool OatWriter::WriteAndOpenDexFiles(
SafeMap<std::string, std::string>* key_value_store,
bool verify,
bool update_input_vdex,
- /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
+ /*out*/ std::vector<std::unique_ptr<MemMap>>* opened_dex_files_map,
/*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
CHECK(write_state_ == WriteState::kAddingDexFileSources);
@@ -645,7 +646,7 @@ bool OatWriter::WriteAndOpenDexFiles(
return false;
}
- std::unique_ptr<MemMap> dex_files_map;
+ std::vector<std::unique_ptr<MemMap>> dex_files_map;
std::vector<std::unique_ptr<const DexFile>> dex_files;
// Initialize VDEX and OAT headers.
@@ -3287,14 +3288,28 @@ bool OatWriter::WriteDexFiles(OutputStream* out, File* file, bool update_input_v
vdex_dex_files_offset_ = vdex_size_;
- // Write dex files.
+ only_contains_uncompressed_zip_entries_ = true;
for (OatDexFile& oat_dex_file : oat_dex_files_) {
- if (!WriteDexFile(out, file, &oat_dex_file, update_input_vdex)) {
- return false;
+ if (!oat_dex_file.source_.IsZipEntry()) {
+ only_contains_uncompressed_zip_entries_ = false;
+ break;
+ }
+ ZipEntry* entry = oat_dex_file.source_.GetZipEntry();
+ if (!entry->IsUncompressed() || !entry->IsAlignedToDexHeader()) {
+ only_contains_uncompressed_zip_entries_ = false;
+ break;
+ }
+ }
+
+ if (!only_contains_uncompressed_zip_entries_) {
+ // Write dex files.
+ for (OatDexFile& oat_dex_file : oat_dex_files_) {
+ if (!WriteDexFile(out, file, &oat_dex_file, update_input_vdex)) {
+ return false;
+ }
}
}
- CloseSources();
return true;
}
@@ -3616,7 +3631,7 @@ bool OatWriter::WriteDexFile(OutputStream* out,
bool OatWriter::OpenDexFiles(
File* file,
bool verify,
- /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
+ /*out*/ std::vector<std::unique_ptr<MemMap>>* opened_dex_files_map,
/*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
TimingLogger::ScopedTiming split("OpenDexFiles", timings_);
@@ -3625,6 +3640,43 @@ bool OatWriter::OpenDexFiles(
return true;
}
+ if (only_contains_uncompressed_zip_entries_) {
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::vector<std::unique_ptr<MemMap>> maps;
+ for (OatDexFile& oat_dex_file : oat_dex_files_) {
+ std::string error_msg;
+ MemMap* map = oat_dex_file.source_.GetZipEntry()->MapDirectlyFromFile(
+ oat_dex_file.dex_file_location_data_, &error_msg);
+ if (map == nullptr) {
+ LOG(ERROR) << error_msg;
+ return false;
+ }
+ maps.emplace_back(map);
+ // Now, open the dex file.
+ dex_files.emplace_back(DexFileLoader::Open(map->Begin(),
+ map->Size(),
+ oat_dex_file.GetLocation(),
+ oat_dex_file.dex_file_location_checksum_,
+ /* oat_dex_file */ nullptr,
+ verify,
+ verify,
+ &error_msg));
+ if (dex_files.back() == nullptr) {
+ LOG(ERROR) << "Failed to open dex file from oat file. File: " << oat_dex_file.GetLocation()
+ << " Error: " << error_msg;
+ return false;
+ }
+ oat_dex_file.class_offsets_.resize(dex_files.back()->GetHeader().class_defs_size_);
+ }
+ *opened_dex_files_map = std::move(maps);
+ *opened_dex_files = std::move(dex_files);
+ CloseSources();
+ return true;
+ }
+ // We could have closed the sources at the point of writing the dex files, but to
+ // make it consistent with the case we're not writing the dex files, we close them now.
+ CloseSources();
+
size_t map_offset = oat_dex_files_[0].dex_file_offset_;
size_t length = vdex_size_ - map_offset;
@@ -3683,7 +3735,7 @@ bool OatWriter::OpenDexFiles(
oat_dex_file.class_offsets_.resize(dex_files.back()->GetHeader().class_defs_size_);
}
- *opened_dex_files_map = std::move(dex_files_map);
+ opened_dex_files_map->push_back(std::move(dex_files_map));
*opened_dex_files = std::move(dex_files);
return true;
}
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
index 4055878b55..3e9f4636fb 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -173,7 +173,7 @@ class OatWriter {
SafeMap<std::string, std::string>* key_value_store,
bool verify,
bool update_input_vdex,
- /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
+ /*out*/ std::vector<std::unique_ptr<MemMap>>* opened_dex_files_map,
/*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
bool WriteQuickeningInfo(OutputStream* vdex_out);
bool WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps);
@@ -300,7 +300,7 @@ class OatWriter {
bool update_input_vdex);
bool OpenDexFiles(File* file,
bool verify,
- /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
+ /*out*/ std::vector<std::unique_ptr<MemMap>>* opened_dex_files_map,
/*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
size_t InitOatHeader(InstructionSet instruction_set,
@@ -367,6 +367,8 @@ class OatWriter {
const CompilerDriver* compiler_driver_;
ImageWriter* image_writer_;
const bool compiling_boot_image_;
+ // Whether the dex files being compiled are all uncompressed in the APK.
+ bool only_contains_uncompressed_zip_entries_;
// note OatFile does not take ownership of the DexFiles
const std::vector<const DexFile*>* dex_files_;
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index fec05cc393..f4dfcd6a0d 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -186,7 +186,7 @@ class OatTest : public CommonCompilerTest {
oat_file);
elf_writer->Start();
OutputStream* oat_rodata = elf_writer->StartRoData();
- std::unique_ptr<MemMap> opened_dex_files_map;
+ std::vector<std::unique_ptr<MemMap>> opened_dex_files_maps;
std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
if (!oat_writer.WriteAndOpenDexFiles(vdex_file,
oat_rodata,
@@ -195,7 +195,7 @@ class OatTest : public CommonCompilerTest {
&key_value_store,
verify,
/* update_input_vdex */ false,
- &opened_dex_files_map,
+ &opened_dex_files_maps,
&opened_dex_files)) {
return false;
}
@@ -251,7 +251,9 @@ class OatTest : public CommonCompilerTest {
return false;
}
- opened_dex_files_maps_.emplace_back(std::move(opened_dex_files_map));
+ for (std::unique_ptr<MemMap>& map : opened_dex_files_maps) {
+ opened_dex_files_maps_.emplace_back(std::move(map));
+ }
for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
opened_dex_files_.emplace_back(dex_file.release());
}
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 944a30849f..73b8c30d96 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -1032,6 +1032,10 @@ class DexFile {
ALWAYS_INLINE const StandardDexFile* AsStandardDexFile() const;
ALWAYS_INLINE const CompactDexFile* AsCompactDexFile() const;
+ DexFileContainer* GetContainer() const {
+ return container_.get();
+ }
+
protected:
DexFile(const uint8_t* base,
size_t size,
diff --git a/runtime/dex_file_loader.cc b/runtime/dex_file_loader.cc
index bc9276985b..6d4bbf13d8 100644
--- a/runtime/dex_file_loader.cc
+++ b/runtime/dex_file_loader.cc
@@ -379,7 +379,7 @@ std::unique_ptr<const DexFile> DexFileLoader::OpenOneDexFileFromZip(
std::unique_ptr<MemMap> map;
if (zip_entry->IsUncompressed()) {
- if (!zip_entry->IsAlignedTo(alignof(DexFile::Header))) {
+ if (!zip_entry->IsAlignedToDexHeader()) {
// Do not mmap unaligned ZIP entries because
// doing so would fail dex verification which requires 4 byte alignment.
LOG(WARNING) << "Can't mmap dex file " << location << "!" << entry_name << " directly; "
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index c82df7119f..1d05399de2 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -594,14 +594,6 @@ bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) {
dex_file_location.c_str());
return false;
}
- if (UNLIKELY(dex_file_offset == 0U)) {
- *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with zero dex "
- "file offset",
- GetLocation().c_str(),
- i,
- dex_file_location.c_str());
- return false;
- }
if (UNLIKELY(dex_file_offset > DexSize())) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
"offset %u > %zu",
@@ -612,20 +604,36 @@ bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) {
DexSize());
return false;
}
- if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
- *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
- "offset %u of %zu but the size of dex file header is %zu",
- GetLocation().c_str(),
- i,
- dex_file_location.c_str(),
- dex_file_offset,
- DexSize(),
- sizeof(DexFile::Header));
- return false;
+ const uint8_t* dex_file_pointer = nullptr;
+ if (UNLIKELY(dex_file_offset == 0U)) {
+ if (uncompressed_dex_files_ == nullptr) {
+ uncompressed_dex_files_.reset(new std::vector<std::unique_ptr<const DexFile>>());
+ // No dex files, load it from location.
+ if (!DexFileLoader::Open(dex_file_location.c_str(),
+ dex_file_location,
+ /* verify */ false,
+ /* verify_checksum */ false,
+ error_msg,
+ uncompressed_dex_files_.get())) {
+ return false;
+ }
+ }
+ dex_file_pointer = uncompressed_dex_files_.get()->at(i)->Begin();
+ } else {
+ if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
+ "offset %u of %zu but the size of dex file header is %zu",
+ GetLocation().c_str(),
+ i,
+ dex_file_location.c_str(),
+ dex_file_offset,
+ DexSize(),
+ sizeof(DexFile::Header));
+ return false;
+ }
+ dex_file_pointer = DexBegin() + dex_file_offset;
}
- const uint8_t* dex_file_pointer = DexBegin() + dex_file_offset;
-
const bool valid_magic = DexFileLoader::IsMagicValid(dex_file_pointer);
if (UNLIKELY(!valid_magic)) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
@@ -646,7 +654,7 @@ bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) {
return false;
}
const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
- if (DexSize() - dex_file_offset < header->file_size_) {
+ if (dex_file_offset != 0 && (DexSize() - dex_file_offset < header->file_size_)) {
*error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
"offset %u and size %u truncated at %zu",
GetLocation().c_str(),
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 36a4d7b8fc..61daa9579e 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -324,6 +324,11 @@ class OatFile {
return vdex_.get();
}
+ // Whether the OatFile embeds the Dex code.
+ bool ContainsDexCode() const {
+ return uncompressed_dex_files_ == nullptr;
+ }
+
protected:
OatFile(const std::string& filename, bool executable);
@@ -389,6 +394,10 @@ class OatFile {
// elements. std::list<> and std::deque<> satisfy this requirement, std::vector<> doesn't.
mutable std::list<std::string> string_cache_ GUARDED_BY(secondary_lookup_lock_);
+ // Cache of dex files mapped directly from a location, in case the OatFile does
+ // not embed the dex code.
+ std::unique_ptr<std::vector<std::unique_ptr<const DexFile>>> uncompressed_dex_files_;
+
friend class gc::collector::DummyOatFile; // For modifying begin_ and end_.
friend class OatClass;
friend class art::OatDexFile;
diff --git a/runtime/zip_archive.cc b/runtime/zip_archive.cc
index f3d4d77214..279c0e4e83 100644
--- a/runtime/zip_archive.cc
+++ b/runtime/zip_archive.cc
@@ -27,6 +27,7 @@
#include "android-base/stringprintf.h"
#include "ziparchive/zip_archive.h"
+#include "dex_file.h"
#include "base/bit_utils.h"
#include "base/unix_file/fd_file.h"
@@ -49,11 +50,15 @@ bool ZipEntry::IsUncompressed() {
return zip_entry_->method == kCompressStored;
}
-bool ZipEntry::IsAlignedTo(size_t alignment) {
+bool ZipEntry::IsAlignedTo(size_t alignment) const {
DCHECK(IsPowerOfTwo(alignment)) << alignment;
return IsAlignedParam(zip_entry_->offset, static_cast<int>(alignment));
}
+bool ZipEntry::IsAlignedToDexHeader() const {
+ return IsAlignedTo(alignof(DexFile::Header));
+}
+
ZipEntry::~ZipEntry() {
delete zip_entry_;
}
diff --git a/runtime/zip_archive.h b/runtime/zip_archive.h
index 821cc5ceb1..ca7bbe965b 100644
--- a/runtime/zip_archive.h
+++ b/runtime/zip_archive.h
@@ -58,7 +58,8 @@ class ZipEntry {
uint32_t GetCrc32();
bool IsUncompressed();
- bool IsAlignedTo(size_t alignment);
+ bool IsAlignedTo(size_t alignment) const;
+ bool IsAlignedToDexHeader() const;
private:
ZipEntry(ZipArchiveHandle handle,