From 052f5fb6d28717b7ff236c508f5fb36a7705f662 Mon Sep 17 00:00:00 2001 From: David Srbecky Date: Mon, 13 Feb 2023 12:42:12 +0000 Subject: [PATCH] Refactor DexFileLoader The first parameter of the Open methods specifies the data source, that we intend to load the dex file(s) from. This creates large number of overloads when multiplied by diversity of the other arguments. Move the data source parameters to the constructor of DexFileLoader. Specifically, the constructor just creates the right DexFileContainer, and the rest of the loader is independent of the data source used. This removes large amount of the overloads as well as large amount of copy-pasted code. Majority of ArtDexFileLoader has been removed. Bug: 266950186 Test: ./art/test.py -b --host --optimizing --64 Change-Id: I6580b49e65441eec93a7e0124be23bd8c859904a --- dex2oat/dex2oat_test.cc | 8 +- dex2oat/linker/oat_writer.cc | 24 +- dexdump/dexdump.cc | 12 +- dexdump/dexdump_main.cc | 7 +- dexlayout/dexlayout.cc | 10 +- dexlayout/dexlayout_test.cc | 37 +- dexlist/dexlist.cc | 15 +- libartbase/base/common_art_test.cc | 18 +- libartbase/base/common_art_test.h | 9 +- libartbase/base/mem_map.cc | 2 + libartbase/base/mem_map.h | 1 + libartbase/base/systrace.h | 1 + libartbase/base/zip_archive.cc | 18 + libartbase/base/zip_archive.h | 4 + libdexfile/dex/art_dex_file_loader.cc | 511 +----------------- libdexfile/dex/art_dex_file_loader.h | 141 +---- libdexfile/dex/art_dex_file_loader_test.cc | 46 +- libdexfile/dex/code_item_accessors_test.cc | 7 +- libdexfile/dex/dex_file.h | 10 +- libdexfile/dex/dex_file_loader.cc | 428 ++++++++------- libdexfile/dex/dex_file_loader.h | 168 ++++-- libdexfile/dex/dex_file_loader_test.cc | 43 +- libdexfile/dex/dex_file_verifier_test.cc | 15 +- libdexfile/dex/test_dex_file_builder.h | 14 +- libdexfile/external/dex_file_ext.cc | 7 +- oatdump/oatdump.cc | 17 +- odrefresh/odrefresh.cc | 4 +- openjdkjvmti/ti_class.cc | 6 +- openjdkjvmti/ti_class_definition.cc | 6 +- openjdkjvmti/ti_redefine.cc | 6 +- openjdkjvmti/ti_search.cc | 6 +- profman/profman.cc | 35 +- runtime/class_loader_context.cc | 21 +- runtime/common_runtime_test.cc | 6 +- runtime/common_runtime_test.h | 11 +- runtime/dex2oat_environment_test.h | 22 +- runtime/dexopt_test.cc | 5 +- runtime/gc/space/image_space.cc | 3 +- runtime/hidden_api_test.cc | 11 +- runtime/oat_file.cc | 60 +- runtime/oat_file_assistant.cc | 13 +- runtime/oat_file_assistant_context.cc | 3 +- runtime/oat_file_assistant_test.cc | 6 +- runtime/oat_file_manager.cc | 11 +- runtime/runtime.cc | 10 +- runtime/sdk_checker.cc | 13 +- runtime/vdex_file.cc | 7 +- test/674-hiddenapi/hiddenapi.cc | 6 +- .../source_transform_art.cc | 7 +- tools/art_verifier/art_verifier.cc | 6 +- tools/dexanalyze/dexanalyze.cc | 28 +- tools/hiddenapi/hiddenapi.cc | 75 +-- tools/hiddenapi/hiddenapi_test.cc | 7 +- tools/veridex/Android.bp | 1 + tools/veridex/veridex.cc | 21 +- 55 files changed, 662 insertions(+), 1327 deletions(-) diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc index 0099ba3b74..fd321e4d95 100644 --- a/dex2oat/dex2oat_test.cc +++ b/dex2oat/dex2oat_test.cc @@ -619,9 +619,9 @@ class Dex2oatLayoutTest : public Dex2oatTest { const char* location = dex_location.c_str(); std::string error_msg; std::vector> dex_files; - const ArtDexFileLoader dex_file_loader; + ArtDexFileLoader dex_file_loader(location); ASSERT_TRUE(dex_file_loader.Open( - location, location, /*verify=*/true, /*verify_checksum=*/true, &error_msg, &dex_files)); + /*verify=*/true, /*verify_checksum=*/true, &error_msg, &dex_files)); EXPECT_EQ(dex_files.size(), 1U); std::unique_ptr& dex_file = dex_files[0]; @@ -811,9 +811,9 @@ class Dex2oatLayoutTest : public Dex2oatTest { const char* location = dex_location.c_str(); std::vector> dex_files; - const ArtDexFileLoader dex_file_loader; + ArtDexFileLoader dex_file_loader(location); ASSERT_TRUE(dex_file_loader.Open( - location, location, /*verify=*/ true, /*verify_checksum=*/ true, &error_msg, &dex_files)); + /*verify=*/true, /*verify_checksum=*/true, &error_msg, &dex_files)); EXPECT_EQ(dex_files.size(), 1U); std::unique_ptr& old_dex_file = dex_files[0]; diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index 6b4b0ca762..c2fa67e09a 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -462,11 +462,9 @@ bool OatWriter::AddDexFileSource(const char* filename, const char* location) { bool OatWriter::AddDexFileSource(File&& dex_file_fd, const char* location) { DCHECK(write_state_ == WriteState::kAddingDexFileSources); std::string error_msg; - const ArtDexFileLoader loader; + ArtDexFileLoader loader(dex_file_fd.Release(), location); std::vector> dex_files; - if (!loader.Open(dex_file_fd.Release(), - location, - /*verify=*/false, + if (!loader.Open(/*verify=*/false, /*verify_checksum=*/false, &error_msg, &dex_files)) { @@ -524,11 +522,8 @@ bool OatWriter::AddRawDexFileSource(const ArrayRef& data, uint32_t location_checksum) { DCHECK(write_state_ == WriteState::kAddingDexFileSources); std::string error_msg; - const ArtDexFileLoader loader; - auto dex_file = loader.Open(data.data(), - data.size(), - location, - location_checksum, + ArtDexFileLoader loader(data.data(), data.size(), location); + auto dex_file = loader.Open(location_checksum, nullptr, /*verify=*/false, /*verify_checksum=*/false, @@ -3187,7 +3182,8 @@ bool OatWriter::WriteDexFiles(File* file, if (copy_dex_files == CopyOption::kOnlyIfCompressed) { extract_dex_files_into_vdex_ = false; for (OatDexFile& oat_dex_file : oat_dex_files_) { - if (!oat_dex_file.GetDexFile()->GetContainer()->IsDirectMmap()) { + const DexFileContainer* container = oat_dex_file.GetDexFile()->GetContainer(); + if (!(container->IsZip() && container->IsFileMap())) { extract_dex_files_into_vdex_ = true; break; } @@ -3468,7 +3464,6 @@ bool OatWriter::OpenDexFiles( DCHECK_EQ(opened_dex_files_map->size(), 1u); DCHECK(vdex_begin_ == opened_dex_files_map->front().Begin()); - const ArtDexFileLoader dex_file_loader; std::vector> dex_files; for (OatDexFile& oat_dex_file : oat_dex_files_) { const uint8_t* raw_dex_file = vdex_begin_ + oat_dex_file.dex_file_offset_; @@ -3490,10 +3485,9 @@ bool OatWriter::OpenDexFiles( // Now, open the dex file. std::string error_msg; - dex_files.emplace_back(dex_file_loader.Open(raw_dex_file, - oat_dex_file.dex_file_size_, - oat_dex_file.GetLocation(), - oat_dex_file.dex_file_location_checksum_, + ArtDexFileLoader dex_file_loader( + raw_dex_file, oat_dex_file.dex_file_size_, oat_dex_file.GetLocation()); + dex_files.emplace_back(dex_file_loader.Open(oat_dex_file.dex_file_location_checksum_, /* oat_dex_file */ nullptr, verify, verify, diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc index 2ab98ec884..7e4c1a68d3 100644 --- a/dexdump/dexdump.cc +++ b/dexdump/dexdump.cc @@ -1962,18 +1962,12 @@ int processFile(const char* fileName) { LOG(ERROR) << "ReadFileToString failed"; return -1; } - const DexFileLoader dex_file_loader; DexFileLoaderErrorCode error_code; std::string error_msg; std::vector> dex_files; - if (!dex_file_loader.OpenAll(reinterpret_cast(content.data()), - content.size(), - fileName, - kVerify, - kVerifyChecksum, - &error_code, - &error_msg, - &dex_files)) { + DexFileLoader dex_file_loader( + reinterpret_cast(content.data()), content.size(), fileName); + if (!dex_file_loader.Open(kVerify, kVerifyChecksum, &error_code, &error_msg, &dex_files)) { // Display returned error message to user. Note that this error behavior // differs from the error messages shown by the original Dalvik dexdump. LOG(ERROR) << error_msg; diff --git a/dexdump/dexdump_main.cc b/dexdump/dexdump_main.cc index 0d46d6bf69..fed2ba7282 100644 --- a/dexdump/dexdump_main.cc +++ b/dexdump/dexdump_main.cc @@ -22,13 +22,13 @@ * Also, ODEX files are no longer supported. */ -#include "dexdump.h" - +#include +#include #include #include #include -#include +#include "dexdump.h" namespace art { @@ -157,6 +157,7 @@ int dexdumpDriver(int argc, char** argv) { int main(int argc, char** argv) { // Output all logging to stderr. android::base::SetLogger(android::base::StderrLogger); + art::MemMap::Init(); return art::dexdumpDriver(argc, argv); } diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index a35c6522b7..d2d31ac90b 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -2009,17 +2009,15 @@ bool DexLayout::ProcessDexFile(const char* file_name, std::string location = "memory mapped file for " + std::string(file_name); // Dex file verifier cannot handle compact dex. bool verify = options_.compact_dex_level_ == CompactDexLevel::kCompactDexLevelNone; - const ArtDexFileLoader dex_file_loader; DexContainer::Section* const main_section = (*dex_container)->GetMainSection(); DexContainer::Section* const data_section = (*dex_container)->GetDataSection(); DCHECK_EQ(file_size, main_section->Size()) << main_section->Size() << " " << data_section->Size(); auto container = std::make_unique( main_section->Begin(), main_section->End(), data_section->Begin(), data_section->End()); + ArtDexFileLoader dex_file_loader(std::move(container), location); std::unique_ptr output_dex_file( - dex_file_loader.Open(std::move(container), - location, - /* location_checksum= */ 0, + dex_file_loader.Open(/* location_checksum= */ 0, /*oat_dex_file=*/nullptr, verify, /*verify_checksum=*/false, @@ -2057,10 +2055,10 @@ int DexLayout::ProcessFile(const char* file_name) { // all of which are Zip archives with "classes.dex" inside. const bool verify_checksum = !options_.ignore_bad_checksum_; std::string error_msg; - const ArtDexFileLoader dex_file_loader; + ArtDexFileLoader dex_file_loader(file_name); std::vector> dex_files; if (!dex_file_loader.Open( - file_name, file_name, /* verify= */ true, verify_checksum, &error_msg, &dex_files)) { + /* verify= */ true, verify_checksum, &error_msg, &dex_files)) { // Display returned error message to user. Note that this error behavior // differs from the error messages shown by the original Dalvik dexdump. LOG(ERROR) << error_msg; diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc index 8d034b89ed..03df258f04 100644 --- a/dexlayout/dexlayout_test.cc +++ b/dexlayout/dexlayout_test.cc @@ -330,11 +330,9 @@ class DexLayoutTest : public CommonArtTest { const std::string& out_profile) { std::vector> dex_files; std::string error_msg; - const ArtDexFileLoader dex_file_loader; - bool result = dex_file_loader.Open(input_dex.c_str(), - input_dex, - /*verify=*/ true, - /*verify_checksum=*/ false, + ArtDexFileLoader dex_file_loader(input_dex); + bool result = dex_file_loader.Open(/*verify=*/true, + /*verify_checksum=*/false, &error_msg, &dex_files); @@ -774,14 +772,15 @@ TEST_F(DexLayoutTest, LinkData) { TEST_F(DexLayoutTest, ClassFilter) { std::vector> dex_files; std::string error_msg; - const ArtDexFileLoader dex_file_loader; const std::string input_jar = GetTestDexFileName("ManyMethods"); - CHECK(dex_file_loader.Open(input_jar.c_str(), - input_jar.c_str(), - /*verify=*/ true, - /*verify_checksum=*/ true, - &error_msg, - &dex_files)) << error_msg; + { + ArtDexFileLoader dex_file_loader(input_jar); + CHECK(dex_file_loader.Open(/*verify=*/true, + /*verify_checksum=*/true, + &error_msg, + &dex_files)) + << error_msg; + } ASSERT_EQ(dex_files.size(), 1u); for (const std::unique_ptr& dex_file : dex_files) { EXPECT_GT(dex_file->NumClassDefs(), 1u); @@ -808,14 +807,12 @@ TEST_F(DexLayoutTest, ClassFilter) { out->GetMainSection()->End(), out->GetDataSection()->Begin(), out->GetDataSection()->End()); - std::unique_ptr output_dex_file( - dex_file_loader.Open(std::move(container), - dex_file->GetLocation().c_str(), - /* location_checksum= */ 0, - /*oat_dex_file=*/nullptr, - /* verify= */ true, - /*verify_checksum=*/false, - &error_msg)); + ArtDexFileLoader dex_file_loader(std::move(container), dex_file->GetLocation()); + std::unique_ptr output_dex_file(dex_file_loader.Open(/* location_checksum= */ 0, + /*oat_dex_file=*/nullptr, + /* verify= */ true, + /*verify_checksum=*/false, + &error_msg)); ASSERT_TRUE(output_dex_file != nullptr); ASSERT_EQ(output_dex_file->NumClassDefs(), options.class_filter_.size()); diff --git a/dexlist/dexlist.cc b/dexlist/dexlist.cc index 9ef9ae9e47..3603675a70 100644 --- a/dexlist/dexlist.cc +++ b/dexlist/dexlist.cc @@ -30,6 +30,7 @@ #include #include +#include "base/mem_map.h" #include "dex/class_accessor-inl.h" #include "dex/code_item_accessors-inl.h" #include "dex/dex_file-inl.h" @@ -168,15 +169,10 @@ static int processFile(const char* fileName) { std::vector> dex_files; DexFileLoaderErrorCode error_code; std::string error_msg; - const DexFileLoader dex_file_loader; - if (!dex_file_loader.OpenAll(reinterpret_cast(content.data()), - content.size(), - fileName, - /*verify=*/ true, - kVerifyChecksum, - &error_code, - &error_msg, - &dex_files)) { + DexFileLoader dex_file_loader( + reinterpret_cast(content.data()), content.size(), fileName); + if (!dex_file_loader.Open( + /*verify=*/true, kVerifyChecksum, &error_code, &error_msg, &dex_files)) { LOG(ERROR) << error_msg; return -1; } @@ -281,6 +277,7 @@ int dexlistDriver(int argc, char** argv) { int main(int argc, char** argv) { // Output all logging to stderr. android::base::SetLogger(android::base::StderrLogger); + art::MemMap::Init(); return art::dexlistDriver(argc, argv); } diff --git a/libartbase/base/common_art_test.cc b/libartbase/base/common_art_test.cc index c921f2ebf1..02bfe6fd81 100644 --- a/libartbase/base/common_art_test.cc +++ b/libartbase/base/common_art_test.cc @@ -389,14 +389,9 @@ std::unique_ptr CommonArtTestImpl::LoadExpectSingleDexFile(const std::string error_msg; MemMap::Init(); static constexpr bool kVerifyChecksum = true; - const ArtDexFileLoader dex_file_loader; std::string filename(IsHost() ? GetAndroidBuildTop() + location : location); - if (!dex_file_loader.Open(filename.c_str(), - std::string(location), - /* verify= */ true, - kVerifyChecksum, - &error_msg, - &dex_files)) { + ArtDexFileLoader dex_file_loader(filename.c_str(), std::string(location)); + if (!dex_file_loader.Open(/* verify= */ true, kVerifyChecksum, &error_msg, &dex_files)) { LOG(FATAL) << "Could not open .dex file '" << filename << "': " << error_msg << "\n"; UNREACHABLE(); } @@ -516,14 +511,9 @@ std::vector> CommonArtTestImpl::OpenDexFiles(cons static constexpr bool kVerify = true; static constexpr bool kVerifyChecksum = true; std::string error_msg; - const ArtDexFileLoader dex_file_loader; + ArtDexFileLoader dex_file_loader(filename); std::vector> dex_files; - bool success = dex_file_loader.Open(filename, - filename, - kVerify, - kVerifyChecksum, - &error_msg, - &dex_files); + bool success = dex_file_loader.Open(kVerify, kVerifyChecksum, &error_msg, &dex_files); CHECK(success) << "Failed to open '" << filename << "': " << error_msg; for (auto& dex_file : dex_files) { CHECK(dex_file->IsReadOnly()); diff --git a/libartbase/base/common_art_test.h b/libartbase/base/common_art_test.h index f4935ccf4e..d7711f28a7 100644 --- a/libartbase/base/common_art_test.h +++ b/libartbase/base/common_art_test.h @@ -173,13 +173,12 @@ class CommonArtTestImpl { bool MutateDexFile(File* output_dex, const std::string& input_jar, const Mutator& mutator) { std::vector> dex_files; std::string error_msg; - const ArtDexFileLoader dex_file_loader; - CHECK(dex_file_loader.Open(input_jar.c_str(), - input_jar.c_str(), - /*verify*/ true, + ArtDexFileLoader dex_file_loader(input_jar); + CHECK(dex_file_loader.Open(/*verify*/ true, /*verify_checksum*/ true, &error_msg, - &dex_files)) << error_msg; + &dex_files)) + << error_msg; EXPECT_EQ(dex_files.size(), 1u) << "Only one input dex is supported"; const std::unique_ptr& dex = dex_files[0]; CHECK(dex->EnableWrite()) << "Failed to enable write"; diff --git a/libartbase/base/mem_map.cc b/libartbase/base/mem_map.cc index d36756e7a6..04c11ede63 100644 --- a/libartbase/base/mem_map.cc +++ b/libartbase/base/mem_map.cc @@ -1021,6 +1021,8 @@ void MemMap::Init() { TargetMMapInit(); } +bool MemMap::IsInitialized() { return mem_maps_lock_ != nullptr; } + void MemMap::Shutdown() { if (mem_maps_lock_ == nullptr) { // If MemMap::Shutdown is called more than once, there is no effect. diff --git a/libartbase/base/mem_map.h b/libartbase/base/mem_map.h index 3d74f8a559..c174f24fa4 100644 --- a/libartbase/base/mem_map.h +++ b/libartbase/base/mem_map.h @@ -316,6 +316,7 @@ class MemMap { // time after the first call to Init and before the first call to Shutodwn. static void Init() REQUIRES(!MemMap::mem_maps_lock_); static void Shutdown() REQUIRES(!MemMap::mem_maps_lock_); + static bool IsInitialized(); // If the map is PROT_READ, try to read each page of the map to check it is in fact readable (not // faulting). This is used to diagnose a bug b/19894268 where mprotect doesn't seem to be working diff --git a/libartbase/base/systrace.h b/libartbase/base/systrace.h index 42975d7931..6e5e0e013a 100644 --- a/libartbase/base/systrace.h +++ b/libartbase/base/systrace.h @@ -60,6 +60,7 @@ class ScopedTrace { } explicit ScopedTrace(const std::string& name) : ScopedTrace(name.c_str()) {} + ScopedTrace(ScopedTrace&&) = default; ~ScopedTrace() { ATraceEnd(); diff --git a/libartbase/base/zip_archive.cc b/libartbase/base/zip_archive.cc index 70778e7f76..ba44096be5 100644 --- a/libartbase/base/zip_archive.cc +++ b/libartbase/base/zip_archive.cc @@ -253,6 +253,24 @@ ZipArchive* ZipArchive::OpenFromOwnedFd(int fd, const char* filename, std::strin return OpenFromFdInternal(fd, /*assume_ownership=*/false, filename, error_msg); } +ZipArchive* ZipArchive::OpenFromMemory(const uint8_t* data, + size_t size, + const char* filename, + std::string* error_msg) { + DCHECK(filename != nullptr); + DCHECK(data != nullptr); + + ZipArchiveHandle handle; + const int32_t error = OpenArchiveFromMemory(data, size, filename, &handle); + if (error != 0) { + *error_msg = std::string(ErrorCodeString(error)); + CloseArchive(handle); + return nullptr; + } + + return new ZipArchive(handle); +} + ZipArchive* ZipArchive::OpenFromFdInternal(int fd, bool assume_ownership, const char* filename, diff --git a/libartbase/base/zip_archive.h b/libartbase/base/zip_archive.h index 084bfd0c78..e740c9f0f0 100644 --- a/libartbase/base/zip_archive.h +++ b/libartbase/base/zip_archive.h @@ -93,6 +93,10 @@ class ZipArchive { static ZipArchive* Open(const char* filename, std::string* error_msg); static ZipArchive* OpenFromFd(int fd, const char* filename, std::string* error_msg); static ZipArchive* OpenFromOwnedFd(int fd, const char* filename, std::string* error_msg); + static ZipArchive* OpenFromMemory(const uint8_t* data, + size_t size, + const char* filename, + std::string* error_msg); ZipEntry* Find(const char* name, std::string* error_msg) const; diff --git a/libdexfile/dex/art_dex_file_loader.cc b/libdexfile/dex/art_dex_file_loader.cc index 53a85bc823..3a15e90bc4 100644 --- a/libdexfile/dex/art_dex_file_loader.cc +++ b/libdexfile/dex/art_dex_file_loader.cc @@ -37,67 +37,14 @@ namespace art { -namespace { - -class MemMapContainer : public DexFileContainer { - public: - explicit MemMapContainer(MemMap&& mem_map, bool direct_mmap = false) - : mem_map_(std::move(mem_map)), direct_mmap_(direct_mmap) {} - ~MemMapContainer() override { } - - int GetPermissions() const { - if (!mem_map_.IsValid()) { - return 0; - } else { - return mem_map_.GetProtect(); - } - } - - bool IsReadOnly() const override { return GetPermissions() == PROT_READ; } - - bool EnableWrite() override { - CHECK(IsReadOnly()); - if (!mem_map_.IsValid()) { - return false; - } else { - return mem_map_.Protect(PROT_READ | PROT_WRITE); - } - } - - bool DisableWrite() override { - CHECK(!IsReadOnly()); - if (!mem_map_.IsValid()) { - return false; - } else { - return mem_map_.Protect(PROT_READ); - } - } - - const uint8_t* Begin() const override { return mem_map_.Begin(); } - - const uint8_t* End() const override { return mem_map_.End(); } - - bool IsDirectMmap() override { return direct_mmap_; } - - private: - MemMap mem_map_; - bool direct_mmap_; - DISALLOW_COPY_AND_ASSIGN(MemMapContainer); -}; - -} // namespace - using android::base::StringPrintf; -static constexpr OatDexFile* kNoOatDexFile = nullptr; - - bool ArtDexFileLoader::GetMultiDexChecksums(const char* filename, std::vector* checksums, std::vector* dex_locations, std::string* error_msg, int zip_fd, - bool* zip_file_only_contains_uncompressed_dex) const { + bool* zip_file_only_contains_uncompressed_dex) { CHECK(checksums != nullptr); uint32_t magic; @@ -154,459 +101,21 @@ bool ArtDexFileLoader::GetMultiDexChecksums(const char* filename, return true; } if (IsMagicValid(magic)) { - std::unique_ptr dex_file(OpenFile(fd.Release(), - filename, - /* verify= */ false, - /* verify_checksum= */ false, - /* mmap_shared= */ false, - error_msg)); - if (dex_file == nullptr) { + ArtDexFileLoader loader(fd.Release(), filename); + std::vector> dex_files; + if (!loader.Open(/* verify= */ false, + /* verify_checksum= */ false, + error_msg, + &dex_files)) { return false; } - checksums->push_back(dex_file->GetHeader().checksum_); + for (auto& dex_file : dex_files) { + checksums->push_back(dex_file->GetHeader().checksum_); + } return true; } *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename); return false; } -std::unique_ptr ArtDexFileLoader::Open(const uint8_t* base, - size_t size, - const std::string& location, - uint32_t location_checksum, - const OatDexFile* oat_dex_file, - bool verify, - bool verify_checksum, - std::string* error_msg) const { - ScopedTrace trace(std::string("Open dex file from RAM ") + location); - auto container = std::make_unique(base, base + size); - return OpenCommon(location, - location_checksum, - oat_dex_file, - verify, - verify_checksum, - error_msg, - std::move(container), - /*verify_result=*/nullptr); -} - -std::unique_ptr ArtDexFileLoader::Open(std::unique_ptr container, - const std::string& location, - uint32_t location_checksum, - const OatDexFile* oat_dex_file, - bool verify, - bool verify_checksum, - std::string* error_msg) const { - ScopedTrace trace(std::string("Open dex file from ") + location); - return OpenCommon(location, - location_checksum, - oat_dex_file, - verify, - verify_checksum, - error_msg, - std::move(container), - /*verify_result=*/nullptr); -} - -std::unique_ptr ArtDexFileLoader::Open(const std::string& location, - uint32_t location_checksum, - MemMap&& map, - bool verify, - bool verify_checksum, - std::string* error_msg) const { - ScopedTrace trace(std::string("Open dex file from mapped-memory ") + location); - CHECK(map.IsValid()); - - size_t size = map.Size(); - if (size < sizeof(DexFile::Header)) { - *error_msg = StringPrintf( - "DexFile: failed to open dex file '%s' that is too short to have a header", - location.c_str()); - return nullptr; - } - - std::unique_ptr dex_file = OpenCommon(location, - location_checksum, - kNoOatDexFile, - verify, - verify_checksum, - error_msg, - std::make_unique(std::move(map)), - /*verify_result=*/nullptr); - // Opening CompactDex is only supported from vdex files. - if (dex_file != nullptr && dex_file->IsCompactDexFile()) { - *error_msg = StringPrintf("Opening CompactDex file '%s' is only supported from vdex files", - location.c_str()); - return nullptr; - } - return dex_file; -} - -bool ArtDexFileLoader::Open(const char* filename, - const std::string& location, - bool verify, - bool verify_checksum, - std::string* error_msg, - std::vector>* dex_files) const { - uint32_t magic; - File fd = OpenAndReadMagic(filename, &magic, error_msg); - if (fd.Fd() == -1) { - DCHECK(!error_msg->empty()); - return false; - } - return OpenWithMagic( - magic, fd.Release(), location, verify, verify_checksum, error_msg, dex_files); -} - -bool ArtDexFileLoader::Open(int fd, - const std::string& location, - bool verify, - bool verify_checksum, - std::string* error_msg, - std::vector>* dex_files) const { - uint32_t magic; - if (!ReadMagicAndReset(fd, &magic, error_msg)) { - DCHECK(!error_msg->empty()); - return false; - } - return OpenWithMagic(magic, fd, location, verify, verify_checksum, error_msg, dex_files); -} - -bool ArtDexFileLoader::Open(const char* filename, - int fd, - const std::string& location, - bool verify, - bool verify_checksum, - std::string* error_msg, - std::vector>* dex_files) const { - return fd == -1 - ? Open(filename, location, verify, verify_checksum, error_msg, dex_files) - : Open(fd, location, verify, verify_checksum, error_msg, dex_files); -} - -bool ArtDexFileLoader::OpenWithMagic(uint32_t magic, - int fd, - const std::string& location, - bool verify, - bool verify_checksum, - std::string* error_msg, - std::vector>* dex_files) const { - ScopedTrace trace(std::string("Open dex file ") + std::string(location)); - DCHECK(dex_files != nullptr) << "DexFile::Open: out-param is nullptr"; - if (IsZipMagic(magic)) { - return OpenZip( - fd, location, verify, verify_checksum, /*allow_no_dex_files=*/false, error_msg, dex_files); - } - if (IsMagicValid(magic)) { - std::unique_ptr dex_file(OpenFile(fd, - location, - verify, - verify_checksum, - /* mmap_shared= */ false, - error_msg)); - if (dex_file.get() != nullptr) { - dex_files->push_back(std::move(dex_file)); - return true; - } else { - return false; - } - } - *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", location.c_str()); - return false; -} - -std::unique_ptr ArtDexFileLoader::OpenDex(int fd, - const std::string& location, - bool verify, - bool verify_checksum, - bool mmap_shared, - std::string* error_msg) const { - ScopedTrace trace("Open dex file " + std::string(location)); - return OpenFile(fd, location, verify, verify_checksum, mmap_shared, error_msg); -} - -bool ArtDexFileLoader::OpenZip(int fd, - const std::string& location, - bool verify, - bool verify_checksum, - bool allow_no_dex_files, - std::string* error_msg, - std::vector>* dex_files) const { - ScopedTrace trace("Dex file open Zip " + std::string(location)); - return OpenZipInternal(ZipArchive::OpenFromFd(fd, location.c_str(), error_msg), - location, - verify, - verify_checksum, - allow_no_dex_files, - error_msg, - dex_files); -} - -bool ArtDexFileLoader::OpenZipFromOwnedFd( - int fd, - const std::string& location, - bool verify, - bool verify_checksum, - bool allow_no_dex_files, - std::string* error_msg, - std::vector>* dex_files) const { - ScopedTrace trace("Dex file open Zip " + std::string(location) + " (owned fd)"); - return OpenZipInternal(ZipArchive::OpenFromOwnedFd(fd, location.c_str(), error_msg), - location, - verify, - verify_checksum, - allow_no_dex_files, - error_msg, - dex_files); -} - -bool ArtDexFileLoader::OpenZipInternal( - ZipArchive* raw_zip_archive, - const std::string& location, - bool verify, - bool verify_checksum, - bool allow_no_dex_files, - std::string* error_msg, - std::vector>* dex_files) const { - DCHECK(dex_files != nullptr) << "DexFile::OpenZip: out-param is nullptr"; - std::unique_ptr zip_archive(raw_zip_archive); - if (zip_archive.get() == nullptr) { - DCHECK(!error_msg->empty()); - return false; - } - return OpenAllDexFilesFromZip( - *zip_archive, location, verify, verify_checksum, allow_no_dex_files, error_msg, dex_files); -} - -std::unique_ptr ArtDexFileLoader::OpenFile(int fd, - const std::string& location, - bool verify, - bool verify_checksum, - bool mmap_shared, - std::string* error_msg) const { - ScopedTrace trace(std::string("Open dex file ") + std::string(location)); - CHECK(!location.empty()); - MemMap map; - { - File delayed_close(fd, /* check_usage= */ false); - struct stat sbuf; - memset(&sbuf, 0, sizeof(sbuf)); - if (fstat(fd, &sbuf) == -1) { - *error_msg = StringPrintf("DexFile: fstat '%s' failed: %s", location.c_str(), - strerror(errno)); - return nullptr; - } - if (S_ISDIR(sbuf.st_mode)) { - *error_msg = StringPrintf("Attempt to mmap directory '%s'", location.c_str()); - return nullptr; - } - size_t length = sbuf.st_size; - map = MemMap::MapFile(length, - PROT_READ, - mmap_shared ? MAP_SHARED : MAP_PRIVATE, - fd, - 0, - /*low_4gb=*/false, - location.c_str(), - error_msg); - if (!map.IsValid()) { - DCHECK(!error_msg->empty()); - return nullptr; - } - } - - const uint8_t* begin = map.Begin(); - size_t size = map.Size(); - if (size < sizeof(DexFile::Header)) { - *error_msg = StringPrintf( - "DexFile: failed to open dex file '%s' that is too short to have a header", - location.c_str()); - return nullptr; - } - - const DexFile::Header* dex_header = reinterpret_cast(begin); - - std::unique_ptr dex_file = OpenCommon(location, - dex_header->checksum_, - kNoOatDexFile, - verify, - verify_checksum, - error_msg, - std::make_unique(std::move(map)), - /*verify_result=*/nullptr); - - // Opening CompactDex is only supported from vdex files. - if (dex_file != nullptr && dex_file->IsCompactDexFile()) { - *error_msg = StringPrintf("Opening CompactDex file '%s' is only supported from vdex files", - location.c_str()); - return nullptr; - } - return dex_file; -} - -std::unique_ptr ArtDexFileLoader::OpenOneDexFileFromZip( - const ZipArchive& zip_archive, - const char* entry_name, - const std::string& location, - bool verify, - bool verify_checksum, - std::string* error_msg, - DexFileLoaderErrorCode* error_code) const { - ScopedTrace trace("Dex file open from Zip Archive " + std::string(location)); - CHECK(!location.empty()); - std::unique_ptr zip_entry(zip_archive.Find(entry_name, error_msg)); - if (zip_entry == nullptr) { - *error_code = DexFileLoaderErrorCode::kEntryNotFound; - return nullptr; - } - if (zip_entry->GetUncompressedLength() == 0) { - *error_msg = StringPrintf("Dex file '%s' has zero length", location.c_str()); - *error_code = DexFileLoaderErrorCode::kDexFileError; - return nullptr; - } - - MemMap map; - bool direct_mmap = false; - if (zip_entry->IsUncompressed()) { - if (!zip_entry->IsAlignedTo(alignof(DexFile::Header))) { - // 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; " - << "please zipalign to " << alignof(DexFile::Header) << " bytes. " - << "Falling back to extracting file."; - } else { - // Map uncompressed files within zip as file-backed to avoid a dirty copy. - map = zip_entry->MapDirectlyFromFile(location.c_str(), /*out*/error_msg); - if (!map.IsValid()) { - LOG(WARNING) << "Can't mmap dex file " << location << "!" << entry_name << " directly; " - << "is your ZIP file corrupted? Falling back to extraction."; - // Try again with Extraction which still has a chance of recovery. - } - direct_mmap = true; - } - } - - ScopedTrace map_extract_trace(StringPrintf("Mapped=%s Extracted=%s", - map.IsValid() ? "true" : "false", - map.IsValid() ? "false" : "true")); // this is redundant but much easier to read in traces. - - if (!map.IsValid()) { - // Default path for compressed ZIP entries, - // and fallback for stored ZIP entries. - map = zip_entry->ExtractToMemMap(location.c_str(), entry_name, error_msg); - } - - if (!map.IsValid()) { - *error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", entry_name, location.c_str(), - error_msg->c_str()); - *error_code = DexFileLoaderErrorCode::kExtractToMemoryError; - return nullptr; - } - VerifyResult verify_result; - auto container = std::make_unique(std::move(map), direct_mmap); - std::unique_ptr dex_file = OpenCommon(location, - zip_entry->GetCrc32(), - kNoOatDexFile, - verify, - verify_checksum, - error_msg, - std::move(container), - &verify_result); - if (dex_file != nullptr && dex_file->IsCompactDexFile()) { - *error_msg = StringPrintf("Opening CompactDex file '%s' is only supported from vdex files", - location.c_str()); - return nullptr; - } - if (dex_file == nullptr) { - if (verify_result == VerifyResult::kVerifyNotAttempted) { - *error_code = DexFileLoaderErrorCode::kDexFileError; - } else { - *error_code = DexFileLoaderErrorCode::kVerifyError; - } - return nullptr; - } - if (!dex_file->DisableWrite()) { - *error_msg = StringPrintf("Failed to make dex file '%s' read only", location.c_str()); - *error_code = DexFileLoaderErrorCode::kMakeReadOnlyError; - return nullptr; - } - CHECK(dex_file->IsReadOnly()) << location; - if (verify_result != VerifyResult::kVerifySucceeded) { - *error_code = DexFileLoaderErrorCode::kVerifyError; - return nullptr; - } - *error_code = DexFileLoaderErrorCode::kNoError; - return dex_file; -} - -// Technically we do not have a limitation with respect to the number of dex files that can be in a -// multidex APK. However, it's bad practice, as each dex file requires its own tables for symbols -// (types, classes, methods, ...) and dex caches. So warn the user that we open a zip with what -// seems an excessive number. -static constexpr size_t kWarnOnManyDexFilesThreshold = 100; - -bool ArtDexFileLoader::OpenAllDexFilesFromZip( - const ZipArchive& zip_archive, - const std::string& location, - bool verify, - bool verify_checksum, - bool allow_no_dex_files, - std::string* error_msg, - std::vector>* dex_files) const { - ScopedTrace trace("Dex file open from Zip " + std::string(location)); - DCHECK(dex_files != nullptr) << "DexFile::OpenFromZip: out-param is nullptr"; - DexFileLoaderErrorCode error_code; - std::string local_error_msg; - std::unique_ptr dex_file(OpenOneDexFileFromZip( - zip_archive, kClassesDex, location, verify, verify_checksum, &local_error_msg, &error_code)); - if (dex_file.get() == nullptr) { - if (allow_no_dex_files && error_code == DexFileLoaderErrorCode::kEntryNotFound) { - return true; - } - *error_msg = std::move(local_error_msg); - return false; - } else { - // Had at least classes.dex. - dex_files->push_back(std::move(dex_file)); - - // Now try some more. - - // We could try to avoid std::string allocations by working on a char array directly. As we - // do not expect a lot of iterations, this seems too involved and brittle. - - for (size_t i = 1;; ++i) { - std::string name = GetMultiDexClassesDexName(i); - std::string fake_location = GetMultiDexLocation(i, location.c_str()); - std::unique_ptr next_dex_file(OpenOneDexFileFromZip(zip_archive, - name.c_str(), - fake_location, - verify, - verify_checksum, - error_msg, - &error_code)); - if (next_dex_file.get() == nullptr) { - if (error_code != DexFileLoaderErrorCode::kEntryNotFound) { - LOG(WARNING) << "Zip open failed: " << *error_msg; - } - break; - } else { - dex_files->push_back(std::move(next_dex_file)); - } - - if (i == kWarnOnManyDexFilesThreshold) { - LOG(WARNING) << location << " has in excess of " << kWarnOnManyDexFilesThreshold - << " dex files. Please consider coalescing and shrinking the number to " - " avoid runtime overhead."; - } - - if (i == std::numeric_limits::max()) { - LOG(ERROR) << "Overflow in number of dex files!"; - break; - } - } - - return true; - } -} - } // namespace art diff --git a/libdexfile/dex/art_dex_file_loader.h b/libdexfile/dex/art_dex_file_loader.h index 6f8b3c6955..9806c46517 100644 --- a/libdexfile/dex/art_dex_file_loader.h +++ b/libdexfile/dex/art_dex_file_loader.h @@ -36,6 +36,7 @@ class ZipArchive; // Class that is used to open dex files and deal with corresponding multidex and location logic. class ArtDexFileLoader : public DexFileLoader { public: + using DexFileLoader::DexFileLoader; virtual ~ArtDexFileLoader() { } // Returns the checksums of a file for comparison with GetLocationChecksum(). @@ -51,140 +52,12 @@ class ArtDexFileLoader : public DexFileLoader { // locations. // // Return true if the checksums could be found, false otherwise. - bool GetMultiDexChecksums(const char* filename, - std::vector* checksums, - std::vector* dex_locations, - std::string* error_msg, - int zip_fd = -1, - bool* only_contains_uncompressed_dex = nullptr) const override; - - // Opens .dex file, backed by existing memory - std::unique_ptr Open(const uint8_t* base, - size_t size, - const std::string& location, - uint32_t location_checksum, - const OatDexFile* oat_dex_file, - bool verify, - bool verify_checksum, - std::string* error_msg) const override; - - // Opens .dex file, backed by existing memory - std::unique_ptr Open(std::unique_ptr container, - const std::string& location, - uint32_t location_checksum, - const OatDexFile* oat_dex_file, - bool verify, - bool verify_checksum, - std::string* error_msg) const; - - // Opens .dex file that has been memory-mapped by the caller. - std::unique_ptr Open(const std::string& location, - uint32_t location_checkum, - MemMap&& mem_map, - bool verify, - bool verify_checksum, - std::string* error_msg) const; - - // Opens all .dex files found in the file, guessing the container format based on file magic. - bool Open(const char* filename, - const std::string& location, - bool verify, - bool verify_checksum, - std::string* error_msg, - std::vector>* dex_files) const; - bool Open(int fd, - const std::string& location, - bool verify, - bool verify_checksum, - std::string* error_msg, - std::vector>* dex_files) const; - // Opens all .dex files found in the file, guessing the container format based on file magic. - // If the fd is -1 then the dex files are opened using the filename; otherwise they are - // opened using the fd. - bool Open(const char* filename, - int fd, - const std::string& location, - bool verify, - bool verify_checksum, - std::string* error_msg, - std::vector>* dex_files) const; - - // Open a single dex file from an fd. This function closes the fd. - std::unique_ptr OpenDex(int fd, - const std::string& location, - bool verify, - bool verify_checksum, - bool mmap_shared, - std::string* error_msg) const; - - // Opens dex files from within a .jar, .zip, or .apk file using its file descriptor. The file - // descriptor ownership is taken over, i.e. will be closed by this class. - // If the zip file doesn't contain any dex code and `allow_no_dex_files` is true, returns true and - // keeps `dex_files` to be an empty vector; if the zip file doesn't contain any dex code and - // `allow_no_dex_files` is false, returns false and sets the error message. - bool OpenZip(int fd, - const std::string& location, - bool verify, - bool verify_checksum, - bool allow_no_dex_files, - std::string* error_msg, - std::vector>* dex_files) const; - - // Opens dex files from within a .jar, .zip, or .apk file using its file descriptor. The file - // descriptor is assumed owned by the caller. - // If the zip file doesn't contain any dex code and `allow_no_dex_files` is true, returns true and - // keeps `dex_files` to be an empty vector; if the zip file doesn't contain any dex code and - // `allow_no_dex_files` is false, returns false and sets the error message. - bool OpenZipFromOwnedFd(int fd, - const std::string& location, - bool verify, - bool verify_checksum, - bool allow_no_dex_files, - std::string* error_msg, - std::vector>* dex_files) const; - - private: - bool OpenWithMagic(uint32_t magic, - int fd, - const std::string& location, - bool verify, - bool verify_checksum, - std::string* error_msg, - std::vector>* dex_files) const; - - std::unique_ptr OpenFile(int fd, - const std::string& location, - bool verify, - bool verify_checksum, - bool mmap_shared, - std::string* error_msg) const; - - // Open all classesXXX.dex files from a zip archive. - bool OpenAllDexFilesFromZip(const ZipArchive& zip_archive, - const std::string& location, - bool verify, - bool verify_checksum, - bool allow_no_dex_files, - std::string* error_msg, - std::vector>* dex_files) const; - - // Opens .dex file from the entry_name in a zip archive. error_code is undefined when non-null - // return. - std::unique_ptr OpenOneDexFileFromZip(const ZipArchive& zip_archive, - const char* entry_name, - const std::string& location, - bool verify, - bool verify_checksum, - std::string* error_msg, - DexFileLoaderErrorCode* error_code) const; - - bool OpenZipInternal(ZipArchive* raw_zip_archive, - const std::string& location, - bool verify, - bool verify_checksum, - bool allow_no_dex_files, - std::string* error_msg, - std::vector>* dex_files) const; + static bool GetMultiDexChecksums(const char* filename, + std::vector* checksums, + std::vector* dex_locations, + std::string* error_msg, + int zip_fd = -1, + bool* only_contains_uncompressed_dex = nullptr); }; } // namespace art diff --git a/libdexfile/dex/art_dex_file_loader_test.cc b/libdexfile/dex/art_dex_file_loader_test.cc index 477d8c5784..833e73b614 100644 --- a/libdexfile/dex/art_dex_file_loader_test.cc +++ b/libdexfile/dex/art_dex_file_loader_test.cc @@ -61,16 +61,14 @@ TEST_F(ArtDexFileLoaderTest, OpenZipMultiDex) { std::string zip_file = GetTestDexFileName("MultiDex"); File file(zip_file, O_RDONLY, /*check_usage=*/false); ASSERT_GE(file.Fd(), 0); - ArtDexFileLoader dex_file_loader; std::vector> dex_files; std::string error_msg; - ASSERT_TRUE(dex_file_loader.OpenZip(file.Release(), - zip_file, - /*verify=*/false, - /*verify_checksum=*/true, - /*allow_no_dex_files=*/true, - &error_msg, - &dex_files)) + ArtDexFileLoader dex_file_loader(file.Release(), zip_file); + ASSERT_TRUE(dex_file_loader.Open(/*verify=*/false, + /*verify_checksum=*/true, + /*allow_no_dex_files=*/true, + &error_msg, + &dex_files)) << error_msg; EXPECT_GT(dex_files.size(), 1); } @@ -79,16 +77,14 @@ TEST_F(ArtDexFileLoaderTest, OpenZipEmpty) { std::string zip_file = GetTestDexFileName("MainEmptyUncompressed"); File file(zip_file, O_RDONLY, /*check_usage=*/false); ASSERT_GE(file.Fd(), 0); - ArtDexFileLoader dex_file_loader; std::vector> dex_files; std::string error_msg; - ASSERT_TRUE(dex_file_loader.OpenZip(file.Release(), - zip_file, - /*verify=*/false, - /*verify_checksum=*/true, - /*allow_no_dex_files=*/true, - &error_msg, - &dex_files)) + ArtDexFileLoader dex_file_loader(file.Release(), zip_file); + ASSERT_TRUE(dex_file_loader.Open(/*verify=*/false, + /*verify_checksum=*/true, + /*allow_no_dex_files=*/true, + &error_msg, + &dex_files)) << error_msg; EXPECT_EQ(dex_files.size(), 0); } @@ -102,11 +98,8 @@ TEST_F(ArtDexFileLoaderTest, GetChecksum) { std::vector checksums; std::vector dex_locations; std::string error_msg; - const ArtDexFileLoader dex_file_loader; - EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(GetLibCoreDexFileNames()[0].c_str(), - &checksums, - &dex_locations, - &error_msg)) + EXPECT_TRUE(ArtDexFileLoader::GetMultiDexChecksums( + GetLibCoreDexFileNames()[0].c_str(), &checksums, &dex_locations, &error_msg)) << error_msg; ASSERT_EQ(1U, checksums.size()); ASSERT_EQ(1U, dex_locations.size()); @@ -119,11 +112,9 @@ TEST_F(ArtDexFileLoaderTest, GetMultiDexChecksums) { std::vector checksums; std::vector dex_locations; std::string multidex_file = GetTestDexFileName("MultiDex"); - const ArtDexFileLoader dex_file_loader; - EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(multidex_file.c_str(), - &checksums, - &dex_locations, - &error_msg)) << error_msg; + EXPECT_TRUE(ArtDexFileLoader::GetMultiDexChecksums( + multidex_file.c_str(), &checksums, &dex_locations, &error_msg)) + << error_msg; std::vector> dexes = OpenTestDexFiles("MultiDex"); ASSERT_EQ(2U, dexes.size()); @@ -144,8 +135,7 @@ TEST_F(ArtDexFileLoaderTest, GetMultiDexChecksumsEmptyZip) { std::vector checksums; std::vector dex_locations; std::string multidex_file = GetTestDexFileName("MainEmptyUncompressed"); - const ArtDexFileLoader dex_file_loader; - EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums( + EXPECT_TRUE(ArtDexFileLoader::GetMultiDexChecksums( multidex_file.c_str(), &checksums, &dex_locations, &error_msg)) << error_msg; diff --git a/libdexfile/dex/code_item_accessors_test.cc b/libdexfile/dex/code_item_accessors_test.cc index c5891f9d46..d43db7006e 100644 --- a/libdexfile/dex/code_item_accessors_test.cc +++ b/libdexfile/dex/code_item_accessors_test.cc @@ -40,12 +40,9 @@ std::unique_ptr CreateFakeDex(bool compact_dex, std::vectordata()); StandardDexFile::WriteCurrentVersion(data->data()); } - const DexFileLoader dex_file_loader; + DexFileLoader dex_file_loader(data->data(), data->size(), "location"); std::string error_msg; - std::unique_ptr dex(dex_file_loader.Open(data->data(), - data->size(), - "location", - /*location_checksum=*/ 123, + std::unique_ptr dex(dex_file_loader.Open(/*location_checksum=*/123, /*oat_dex_file=*/nullptr, /*verify=*/false, /*verify_checksum=*/false, diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h index c9a16ae9a5..0cf5ae26f9 100644 --- a/libdexfile/dex/dex_file.h +++ b/libdexfile/dex/dex_file.h @@ -58,9 +58,14 @@ class DexFileContainer { public: DexFileContainer() { } virtual ~DexFileContainer() {} + virtual bool IsReadOnly() const = 0; + + // Make the underlying writeable. Return true on success (memory can be written). virtual bool EnableWrite() = 0; + // Make the underlying read-only. Return true on success (memory is read-only now). virtual bool DisableWrite() = 0; + virtual const uint8_t* Begin() const = 0; virtual const uint8_t* End() const = 0; size_t Size() const { return End() - Begin(); } @@ -70,9 +75,12 @@ class DexFileContainer { virtual const uint8_t* DataBegin() const { return nullptr; } virtual const uint8_t* DataEnd() const { return nullptr; } - virtual bool IsDirectMmap() { return false; } + bool IsZip() const { return is_zip_; } + void SetIsZip() { is_zip_ = true; } + virtual bool IsFileMap() const { return false; } private: + bool is_zip_ = false; DISALLOW_COPY_AND_ASSIGN(DexFileContainer); }; diff --git a/libdexfile/dex/dex_file_loader.cc b/libdexfile/dex/dex_file_loader.cc index 541d10b68c..942a4bc400 100644 --- a/libdexfile/dex/dex_file_loader.cc +++ b/libdexfile/dex/dex_file_loader.cc @@ -16,20 +16,30 @@ #include "dex_file_loader.h" +#include + #include #include "android-base/stringprintf.h" +#include "base/bit_utils.h" +#include "base/file_magic.h" +#include "base/mem_map.h" +#include "base/os.h" #include "base/stl_util.h" +#include "base/systrace.h" +#include "base/unix_file/fd_file.h" +#include "base/zip_archive.h" #include "compact_dex_file.h" #include "dex_file.h" #include "dex_file_verifier.h" #include "standard_dex_file.h" -#include "ziparchive/zip_archive.h" namespace art { namespace { +using android::base::StringPrintf; + class VectorContainer : public DexFileContainer { public: explicit VectorContainer(std::vector&& vector) : vector_(std::move(vector)) { } @@ -37,13 +47,9 @@ class VectorContainer : public DexFileContainer { bool IsReadOnly() const override { return true; } - bool EnableWrite() override { - return false; - } + bool EnableWrite() override { return true; } - bool DisableWrite() override { - return false; - } + bool DisableWrite() override { return false; } const uint8_t* Begin() const override { return vector_.data(); } @@ -54,99 +60,52 @@ class VectorContainer : public DexFileContainer { DISALLOW_COPY_AND_ASSIGN(VectorContainer); }; -} // namespace - -using android::base::StringPrintf; - -class DexZipArchive; - -class DexZipEntry { +class MemMapContainer : public DexFileContainer { public: - // Extract this entry to memory. - // Returns null on failure and sets error_msg. - const std::vector Extract(std::string* error_msg) { - std::vector map(GetUncompressedLength()); - if (map.size() == 0) { - DCHECK(!error_msg->empty()); - return map; - } - const int32_t error = ExtractToMemory(handle_, zip_entry_, map.data(), map.size()); - if (error) { - *error_msg = std::string(ErrorCodeString(error)); - } - return map; - } + explicit MemMapContainer(MemMap&& mem_map, bool is_file_map = false) + : mem_map_(std::move(mem_map)), is_file_map_(is_file_map) {} - virtual ~DexZipEntry() { - delete zip_entry_; - } - - uint32_t GetUncompressedLength() { - return zip_entry_->uncompressed_length; - } - - uint32_t GetCrc32() { - return zip_entry_->crc32; + int GetPermissions() const { + if (!mem_map_.IsValid()) { + return 0; + } else { + return mem_map_.GetProtect(); + } } - private: - DexZipEntry(ZipArchiveHandle handle, - ::ZipEntry* zip_entry, - const std::string& entry_name) - : handle_(handle), zip_entry_(zip_entry), entry_name_(entry_name) {} - - ZipArchiveHandle handle_; - ::ZipEntry* const zip_entry_; - std::string const entry_name_; + bool IsReadOnly() const override { return GetPermissions() == PROT_READ; } - friend class DexZipArchive; - DISALLOW_COPY_AND_ASSIGN(DexZipEntry); -}; - -class DexZipArchive { - public: - // return new DexZipArchive instance on success, null on error. - static DexZipArchive* Open(const uint8_t* base, size_t size, std::string* error_msg) { - ZipArchiveHandle handle; - uint8_t* nonconst_base = const_cast(base); - const int32_t error = OpenArchiveFromMemory(nonconst_base, size, "ZipArchiveMemory", &handle); - if (error) { - *error_msg = std::string(ErrorCodeString(error)); - CloseArchive(handle); - return nullptr; + bool EnableWrite() override { + CHECK(IsReadOnly()); + if (!mem_map_.IsValid()) { + return false; + } else { + return mem_map_.Protect(PROT_READ | PROT_WRITE); } - return new DexZipArchive(handle); } - DexZipEntry* Find(const char* name, std::string* error_msg) const { - DCHECK(name != nullptr); - // Resist the urge to delete the space. <: is a bigraph sequence. - std::unique_ptr< ::ZipEntry> zip_entry(new ::ZipEntry); - const int32_t error = FindEntry(handle_, name, zip_entry.get()); - if (error) { - *error_msg = std::string(ErrorCodeString(error)); - return nullptr; + bool DisableWrite() override { + CHECK(!IsReadOnly()); + if (!mem_map_.IsValid()) { + return false; + } else { + return mem_map_.Protect(PROT_READ); } - return new DexZipEntry(handle_, zip_entry.release(), name); } - ~DexZipArchive() { - CloseArchive(handle_); - } + const uint8_t* Begin() const override { return mem_map_.Begin(); } + const uint8_t* End() const override { return mem_map_.End(); } - private: - explicit DexZipArchive(ZipArchiveHandle handle) : handle_(handle) {} - ZipArchiveHandle handle_; + bool IsFileMap() const override { return is_file_map_; } - friend class DexZipEntry; - DISALLOW_COPY_AND_ASSIGN(DexZipArchive); + protected: + MemMap mem_map_; + bool is_file_map_; + DISALLOW_COPY_AND_ASSIGN(MemMapContainer); }; -static bool IsZipMagic(uint32_t magic) { - return (('P' == ((magic >> 0) & 0xff)) && - ('K' == ((magic >> 8) & 0xff))); -} +} // namespace bool DexFileLoader::IsMagicValid(uint32_t magic) { return IsMagicValid(reinterpret_cast(&magic)); @@ -205,91 +164,152 @@ std::string DexFileLoader::GetDexCanonicalLocation(const char* dex_location) { } // All of the implementations here should be independent of the runtime. -// TODO: implement all the virtual methods. -bool DexFileLoader::GetMultiDexChecksums( - const char* filename ATTRIBUTE_UNUSED, - std::vector* checksums ATTRIBUTE_UNUSED, - std::vector* dex_locations ATTRIBUTE_UNUSED, - std::string* error_msg, - int zip_fd ATTRIBUTE_UNUSED, - bool* zip_file_only_contains_uncompress_dex ATTRIBUTE_UNUSED) const { - *error_msg = "UNIMPLEMENTED"; - return false; -} +DexFileLoader::DexFileLoader(const uint8_t* base, size_t size, const std::string& location) + : DexFileLoader(std::make_unique(base, base + size), location) {} -std::unique_ptr DexFileLoader::Open( - const std::string& location, - uint32_t location_checksum, - std::vector&& memory, - const OatDexFile* oat_dex_file, - bool verify, - bool verify_checksum, - std::string* error_msg) { - return OpenCommon(location, - location_checksum, - oat_dex_file, - verify, - verify_checksum, - error_msg, - std::make_unique(std::move(memory)), - /*verify_result=*/nullptr); -} +DexFileLoader::DexFileLoader(std::vector&& memory, const std::string& location) + : DexFileLoader(std::make_unique(std::move(memory)), location) {} -std::unique_ptr DexFileLoader::Open(const uint8_t* base, - size_t size, - const std::string& location, - uint32_t location_checksum, +DexFileLoader::DexFileLoader(MemMap&& mem_map, const std::string& location) + : DexFileLoader(std::make_unique(std::move(mem_map)), location) {} + +std::unique_ptr DexFileLoader::Open(uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, bool verify_checksum, - std::string* error_msg) const { - auto container = std::make_unique(base, base + size); - return OpenCommon(location, - location_checksum, - oat_dex_file, - verify, - verify_checksum, - error_msg, - std::move(container), - /*verify_result=*/nullptr); + std::string* error_msg) { + ScopedTrace trace(std::string("Open dex file ") + location_); + + uint32_t magic; + if (!InitAndReadMagic(&magic, error_msg) || !MapRootContainer(error_msg)) { + DCHECK(!error_msg->empty()); + return {}; + } + std::unique_ptr dex_file = OpenCommon(std::move(root_container_), + location_, + location_checksum, + oat_dex_file, + verify, + verify_checksum, + error_msg, + nullptr); + return dex_file; } -bool DexFileLoader::OpenAll( - const uint8_t* base, - size_t size, - const std::string& location, - bool verify, - bool verify_checksum, - DexFileLoaderErrorCode* error_code, - std::string* error_msg, - std::vector>* dex_files) const { +bool DexFileLoader::InitAndReadMagic(uint32_t* magic, std::string* error_msg) { + if (root_container_ != nullptr) { + if (root_container_->Size() < sizeof(uint32_t)) { + *error_msg = StringPrintf("Unable to open '%s' : Size is too small", location_.c_str()); + return false; + } + *magic = *reinterpret_cast(root_container_->Begin()); + } else { + // Open the file if we have not been given the file-descriptor directly before. + if (!file_.has_value()) { + CHECK(!filename_.empty()); + file_.emplace(filename_, O_RDONLY, /* check_usage= */ false); + if (file_->Fd() == -1) { + *error_msg = StringPrintf("Unable to open '%s' : %s", filename_.c_str(), strerror(errno)); + return false; + } + } + if (!ReadMagicAndReset(file_->Fd(), magic, error_msg)) { + return false; + } + } + return true; +} + +bool DexFileLoader::MapRootContainer(std::string* error_msg) { + if (root_container_ != nullptr) { + return true; + } + + CHECK(MemMap::IsInitialized()); + CHECK(file_.has_value()); + struct stat sbuf; + memset(&sbuf, 0, sizeof(sbuf)); + if (fstat(file_->Fd(), &sbuf) == -1) { + *error_msg = StringPrintf("DexFile: fstat '%s' failed: %s", filename_.c_str(), strerror(errno)); + return false; + } + if (S_ISDIR(sbuf.st_mode)) { + *error_msg = StringPrintf("Attempt to mmap directory '%s'", filename_.c_str()); + return false; + } + MemMap map = MemMap::MapFile(sbuf.st_size, + PROT_READ, + MAP_PRIVATE, + file_->Fd(), + 0, + /*low_4gb=*/false, + filename_.c_str(), + error_msg); + if (!map.IsValid()) { + DCHECK(!error_msg->empty()); + return false; + } + root_container_ = std::make_unique(std::move(map)); + return true; +} + +bool DexFileLoader::Open(bool verify, + bool verify_checksum, + bool allow_no_dex_files, + DexFileLoaderErrorCode* error_code, + std::string* error_msg, + std::vector>* dex_files) { + ScopedTrace trace(std::string("Open dex file ") + location_); + DCHECK(dex_files != nullptr) << "DexFile::Open: out-param is nullptr"; - uint32_t magic = *reinterpret_cast(base); + + uint32_t magic; + if (!InitAndReadMagic(&magic, error_msg)) { + return false; + } + if (IsZipMagic(magic)) { - std::unique_ptr zip_archive(DexZipArchive::Open(base, size, error_msg)); + std::unique_ptr zip_archive( + file_.has_value() ? + ZipArchive::OpenFromOwnedFd(file_->Fd(), location_.c_str(), error_msg) : + ZipArchive::OpenFromMemory( + root_container_->Begin(), root_container_->Size(), location_.c_str(), error_msg)); if (zip_archive.get() == nullptr) { DCHECK(!error_msg->empty()); return false; } - return OpenAllDexFilesFromZip(*zip_archive.get(), - location, - verify, - verify_checksum, - error_code, - error_msg, - dex_files); + bool ok = OpenAllDexFilesFromZip(*zip_archive.get(), + location_, + verify, + verify_checksum, + allow_no_dex_files, + error_code, + error_msg, + dex_files); + return ok; } if (IsMagicValid(magic)) { + if (!MapRootContainer(error_msg)) { + return false; + } + const uint8_t* base = root_container_->Begin(); + size_t size = root_container_->Size(); + if (size < sizeof(DexFile::Header)) { + *error_msg = + StringPrintf("DexFile: failed to open dex file '%s' that is too short to have a header", + location_.c_str()); + return false; + } const DexFile::Header* dex_header = reinterpret_cast(base); - std::unique_ptr dex_file(Open(base, - size, - location, - dex_header->checksum_, - /*oat_dex_file=*/ nullptr, - verify, - verify_checksum, - error_msg)); + std::unique_ptr dex_file = OpenCommon(std::move(root_container_), + location_, + dex_header->checksum_, + /*oat_dex_file=*/nullptr, + verify, + verify_checksum, + error_msg, + nullptr); if (dex_file.get() != nullptr) { dex_files->push_back(std::move(dex_file)); return true; @@ -301,13 +321,13 @@ bool DexFileLoader::OpenAll( return false; } -std::unique_ptr DexFileLoader::OpenCommon(const std::string& location, +std::unique_ptr DexFileLoader::OpenCommon(std::unique_ptr container, + const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, bool verify_checksum, std::string* error_msg, - std::unique_ptr container, VerifyResult* verify_result) { CHECK(container != nullptr); const uint8_t* base = container->Begin(); @@ -322,12 +342,8 @@ std::unique_ptr DexFileLoader::OpenCommon(const std::string& location, if (data_size != 0) { CHECK_EQ(base, data_base) << "Unsupported for standard dex"; } - dex_file.reset(new StandardDexFile(base, - size, - location, - location_checksum, - oat_dex_file, - std::move(container))); + dex_file.reset(new StandardDexFile( + base, size, location, location_checksum, oat_dex_file, std::move(container))); } else if (size >= sizeof(CompactDexFile::Header) && CompactDexFile::IsMagicValid(base)) { if (data_base == nullptr) { // TODO: Is there a clean way to support both an explicit data section and reading the one @@ -351,24 +367,27 @@ std::unique_ptr DexFileLoader::OpenCommon(const std::string& location, *error_msg = "Invalid or truncated dex file"; } if (dex_file == nullptr) { - *error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location.c_str(), - error_msg->c_str()); + *error_msg = + StringPrintf("Failed to open dex file '%s': %s", location.c_str(), error_msg->c_str()); return nullptr; } if (!dex_file->Init(error_msg)) { dex_file.reset(); return nullptr; } - if (verify && !dex::Verify(dex_file.get(), - dex_file->Begin(), - dex_file->Size(), - location.c_str(), - verify_checksum, - error_msg)) { - if (verify_result != nullptr) { - *verify_result = VerifyResult::kVerifyFailed; + if (verify) { + ScopedTrace trace(std::string("Verify dex file ") + location); + if (!dex::Verify(dex_file.get(), + dex_file->Begin(), + dex_file->Size(), + location.c_str(), + verify_checksum, + error_msg)) { + if (verify_result != nullptr) { + *verify_result = VerifyResult::kVerifyFailed; + } + return nullptr; } - return nullptr; } if (verify_result != nullptr) { *verify_result = VerifyResult::kVerifySucceeded; @@ -377,7 +396,7 @@ std::unique_ptr DexFileLoader::OpenCommon(const std::string& location, } std::unique_ptr DexFileLoader::OpenOneDexFileFromZip( - const DexZipArchive& zip_archive, + const ZipArchive& zip_archive, const char* entry_name, const std::string& location, bool verify, @@ -385,7 +404,7 @@ std::unique_ptr DexFileLoader::OpenOneDexFileFromZip( DexFileLoaderErrorCode* error_code, std::string* error_msg) const { CHECK(!location.empty()); - std::unique_ptr zip_entry(zip_archive.Find(entry_name, error_msg)); + std::unique_ptr zip_entry(zip_archive.Find(entry_name, error_msg)); if (zip_entry == nullptr) { *error_code = DexFileLoaderErrorCode::kEntryNotFound; return nullptr; @@ -396,23 +415,52 @@ std::unique_ptr DexFileLoader::OpenOneDexFileFromZip( return nullptr; } - std::vector map(zip_entry->Extract(error_msg)); - if (map.size() == 0) { + CHECK(MemMap::IsInitialized()); + MemMap map; + bool is_file_map = false; + if (file_.has_value() && zip_entry->IsUncompressed()) { + if (!zip_entry->IsAlignedTo(alignof(DexFile::Header))) { + // 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; " + << "please zipalign to " << alignof(DexFile::Header) << " bytes. " + << "Falling back to extracting file."; + } else { + // Map uncompressed files within zip as file-backed to avoid a dirty copy. + map = zip_entry->MapDirectlyFromFile(location.c_str(), /*out*/ error_msg); + if (!map.IsValid()) { + LOG(WARNING) << "Can't mmap dex file " << location << "!" << entry_name << " directly; " + << "is your ZIP file corrupted? Falling back to extraction."; + // Try again with Extraction which still has a chance of recovery. + } + is_file_map = true; + } + } + if (!map.IsValid()) { + ScopedTrace trace(std::string("Extract dex file ") + location); + + // Default path for compressed ZIP entries, + // and fallback for stored ZIP entries. + map = zip_entry->ExtractToMemMap(location.c_str(), entry_name, error_msg); + } + if (!map.IsValid()) { *error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", entry_name, location.c_str(), error_msg->c_str()); *error_code = DexFileLoaderErrorCode::kExtractToMemoryError; return nullptr; } + auto container = std::make_unique(std::move(map), is_file_map); + container->SetIsZip(); + VerifyResult verify_result; - std::unique_ptr dex_file = - OpenCommon(location, - zip_entry->GetCrc32(), - /*oat_dex_file=*/nullptr, - verify, - verify_checksum, - error_msg, - std::make_unique(std::move(map)), - &verify_result); + std::unique_ptr dex_file = OpenCommon(std::move(container), + location, + zip_entry->GetCrc32(), + /*oat_dex_file=*/nullptr, + verify, + verify_checksum, + error_msg, + &verify_result); if (verify_result != VerifyResult::kVerifySucceeded) { if (verify_result == VerifyResult::kVerifyNotAttempted) { *error_code = DexFileLoaderErrorCode::kDexFileError; @@ -421,6 +469,12 @@ std::unique_ptr DexFileLoader::OpenOneDexFileFromZip( } return nullptr; } + if (!dex_file->DisableWrite()) { + *error_msg = StringPrintf("Failed to make dex file '%s' read only", location.c_str()); + *error_code = DexFileLoaderErrorCode::kMakeReadOnlyError; + return nullptr; + } + CHECK(dex_file->IsReadOnly()) << location; *error_code = DexFileLoaderErrorCode::kNoError; return dex_file; } @@ -432,10 +486,11 @@ std::unique_ptr DexFileLoader::OpenOneDexFileFromZip( static constexpr size_t kWarnOnManyDexFilesThreshold = 100; bool DexFileLoader::OpenAllDexFilesFromZip( - const DexZipArchive& zip_archive, + const ZipArchive& zip_archive, const std::string& location, bool verify, bool verify_checksum, + bool allow_no_dex_files, DexFileLoaderErrorCode* error_code, std::string* error_msg, std::vector>* dex_files) const { @@ -448,6 +503,9 @@ bool DexFileLoader::OpenAllDexFilesFromZip( error_code, error_msg)); if (*error_code != DexFileLoaderErrorCode::kNoError) { + if (allow_no_dex_files && *error_code == DexFileLoaderErrorCode::kEntryNotFound) { + return true; + } return false; } else { // Had at least classes.dex. diff --git a/libdexfile/dex/dex_file_loader.h b/libdexfile/dex/dex_file_loader.h index ef45aa8472..a2a29bc44e 100644 --- a/libdexfile/dex/dex_file_loader.h +++ b/libdexfile/dex/dex_file_loader.h @@ -18,18 +18,21 @@ #define ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_ #include +#include #include #include #include +#include "base/os.h" +#include "base/unix_file/fd_file.h" +#include "dex_file.h" + namespace art { -class DexFile; -class DexFileContainer; class MemMap; class OatDexFile; - -class DexZipArchive; +class ScopedTrace; +class ZipArchive; enum class DexFileLoaderErrorCode { kNoError, @@ -103,58 +106,90 @@ class DexFileLoader { return (pos == std::string::npos) ? std::string() : location.substr(pos); } - virtual ~DexFileLoader() { } + DexFileLoader(const char* filename, int fd, const std::string& location) + : filename_(filename), + file_(fd == -1 ? std::optional() : File(fd, /*check_usage=*/false)), + location_(location) {} - // Returns the checksums of a file for comparison with GetLocationChecksum(). - // For .dex files, this is the single header checksum. - // For zip files, this is the zip entry CRC32 checksum for classes.dex and - // each additional multidex entry classes2.dex, classes3.dex, etc. - // If a valid zip_fd is provided the file content will be read directly from - // the descriptor and `filename` will be used as alias for error logging. If - // zip_fd is -1, the method will try to open the `filename` and read the - // content from it. - // - // The dex_locations vector will be populated with the corresponding multidex - // locations. - // - // Return true if the checksums could be found, false otherwise. - virtual bool GetMultiDexChecksums(const char* filename, - std::vector* checksums, - std::vector* dex_locations, - std::string* error_msg, - int zip_fd = -1, - bool* zip_file_only_contains_uncompress_dex = nullptr) const; - - // Opens .dex file, backed by existing vector memory. - static std::unique_ptr Open( - const std::string& location, - uint32_t location_checksum, - std::vector&& memory, - const OatDexFile* oat_dex_file, - bool verify, - bool verify_checksum, - std::string* error_msg); - - // Opens .dex file, backed by existing memory. - virtual std::unique_ptr Open(const uint8_t* base, - size_t size, - const std::string& location, - uint32_t location_checksum, - const OatDexFile* oat_dex_file, - bool verify, - bool verify_checksum, - std::string* error_msg) const; - - // Opens all .dex files found in the memory map, guessing the container format based on file - // extension. - virtual bool OpenAll(const uint8_t* base, - size_t size, - const std::string& location, - bool verify, - bool verify_checksum, - DexFileLoaderErrorCode* error_code, - std::string* error_msg, - std::vector>* dex_files) const; + DexFileLoader(std::unique_ptr&& container, const std::string& location) + : root_container_(std::move(container)), location_(location) {} + + DexFileLoader(const uint8_t* base, size_t size, const std::string& location); + + DexFileLoader(std::vector&& memory, const std::string& location); + + DexFileLoader(MemMap&& mem_map, const std::string& location); + + DexFileLoader(int fd, const std::string& location) + : DexFileLoader(/*filename=*/location.c_str(), fd, location) {} + + DexFileLoader(const char* filename, const std::string& location) + : DexFileLoader(filename, /*fd=*/-1, location) {} + + explicit DexFileLoader(const std::string& location) + : DexFileLoader(location.c_str(), /*fd=*/-1, location) {} + + virtual ~DexFileLoader() {} + + std::unique_ptr Open(uint32_t location_checksum, + const OatDexFile* oat_dex_file, + bool verify, + bool verify_checksum, + std::string* error_msg); + + std::unique_ptr Open(uint32_t location_checksum, + bool verify, + bool verify_checksum, + std::string* error_msg) { + return Open(location_checksum, + /*oat_dex_file=*/nullptr, + verify, + verify_checksum, + error_msg); + } + + // Opens all .dex files, guessing the container format based on file extension. + bool Open(bool verify, + bool verify_checksum, + bool allow_no_dex_files, + DexFileLoaderErrorCode* error_code, + std::string* error_msg, + std::vector>* dex_files); + + bool Open(bool verify, + bool verify_checksum, + DexFileLoaderErrorCode* error_code, + std::string* error_msg, + std::vector>* dex_files) { + return Open(verify, + verify_checksum, + /*allow_no_dex_files=*/false, + error_code, + error_msg, + dex_files); + } + + bool Open(bool verify, + bool verify_checksum, + bool allow_no_dex_files, + std::string* error_msg, + std::vector>* dex_files) { + DexFileLoaderErrorCode error_code; + return Open(verify, verify_checksum, allow_no_dex_files, &error_code, error_msg, dex_files); + } + + bool Open(bool verify, + bool verify_checksum, + std::string* error_msg, + std::vector>* dex_files) { + DexFileLoaderErrorCode error_code; + return Open(verify, + verify_checksum, + /*allow_no_dex_files=*/false, + &error_code, + error_msg, + dex_files); + } protected: enum class VerifyResult { // private @@ -163,34 +198,47 @@ class DexFileLoader { kVerifyFailed }; - static std::unique_ptr OpenCommon(const std::string& location, + bool InitAndReadMagic(uint32_t* magic, std::string* error_msg); + + // Ensure we have root container. If we are backed by a file, memory-map it. + // We can only do this for dex files since zip files might be too big to map. + bool MapRootContainer(std::string* error_msg); + + static std::unique_ptr OpenCommon(std::unique_ptr container, + const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, bool verify_checksum, std::string* error_msg, - std::unique_ptr container, VerifyResult* verify_result); - private: // Open all classesXXX.dex files from a zip archive. - bool OpenAllDexFilesFromZip(const DexZipArchive& zip_archive, + bool OpenAllDexFilesFromZip(const ZipArchive& zip_archive, const std::string& location, bool verify, bool verify_checksum, + bool allow_no_dex_files, DexFileLoaderErrorCode* error_code, std::string* error_msg, std::vector>* dex_files) const; // Opens .dex file from the entry_name in a zip archive. error_code is undefined when non-null // return. - std::unique_ptr OpenOneDexFileFromZip(const DexZipArchive& zip_archive, + std::unique_ptr OpenOneDexFileFromZip(const ZipArchive& zip_archive, const char* entry_name, const std::string& location, bool verify, bool verify_checksum, DexFileLoaderErrorCode* error_code, std::string* error_msg) const; + + // The DexFileLoader can be backed either by file or by memory (i.e. DexFileContainer). + // We can not just mmap the file since APKs might be unreasonably large for 32-bit system. + std::string filename_; + std::optional file_; + std::unique_ptr root_container_; + const std::string location_; }; } // namespace art diff --git a/libdexfile/dex/dex_file_loader_test.cc b/libdexfile/dex/dex_file_loader_test.cc index 30c60b10cb..381dfdc23a 100644 --- a/libdexfile/dex/dex_file_loader_test.cc +++ b/libdexfile/dex/dex_file_loader_test.cc @@ -217,15 +217,9 @@ static bool OpenDexFilesBase64(const char* base64, // read dex file(s) static constexpr bool kVerifyChecksum = true; std::vector> tmp; - const DexFileLoader dex_file_loader; - bool success = dex_file_loader.OpenAll(dex_bytes->data(), - dex_bytes->size(), - location, - /* verify= */ true, - kVerifyChecksum, - error_code, - error_msg, - dex_files); + DexFileLoader dex_file_loader(dex_bytes->data(), dex_bytes->size(), location); + bool success = + dex_file_loader.Open(/* verify= */ true, kVerifyChecksum, error_code, error_msg, dex_files); return success; } @@ -251,11 +245,8 @@ static std::unique_ptr OpenDexFileInMemoryBase64(const char* base DecodeDexFile(base64, dex_bytes); std::string error_message; - const DexFileLoader dex_file_loader; - std::unique_ptr dex_file(dex_file_loader.Open(dex_bytes->data(), - dex_bytes->size(), - location, - location_checksum, + DexFileLoader dex_file_loader(dex_bytes->data(), dex_bytes->size(), location); + std::unique_ptr dex_file(dex_file_loader.Open(location_checksum, /* oat_dex_file= */ nullptr, /* verify= */ true, /* verify_checksum= */ true, @@ -353,15 +344,9 @@ TEST_F(DexFileLoaderTest, Version41Rejected) { DexFileLoaderErrorCode error_code; std::string error_msg; std::vector> dex_files; - const DexFileLoader dex_file_loader; - ASSERT_FALSE(dex_file_loader.OpenAll(dex_bytes.data(), - dex_bytes.size(), - kLocationString, - /* verify= */ true, - kVerifyChecksum, - &error_code, - &error_msg, - &dex_files)); + DexFileLoader dex_file_loader(dex_bytes.data(), dex_bytes.size(), kLocationString); + ASSERT_FALSE(dex_file_loader.Open( + /* verify= */ true, kVerifyChecksum, &error_code, &error_msg, &dex_files)); } TEST_F(DexFileLoaderTest, ZeroLengthDexRejected) { @@ -372,15 +357,9 @@ TEST_F(DexFileLoaderTest, ZeroLengthDexRejected) { DexFileLoaderErrorCode error_code; std::string error_msg; std::vector> dex_files; - const DexFileLoader dex_file_loader; - ASSERT_FALSE(dex_file_loader.OpenAll(dex_bytes.data(), - dex_bytes.size(), - kLocationString, - /* verify= */ true, - kVerifyChecksum, - &error_code, - &error_msg, - &dex_files)); + DexFileLoader dex_file_loader(dex_bytes.data(), dex_bytes.size(), kLocationString); + ASSERT_FALSE(dex_file_loader.Open( + /* verify= */ true, kVerifyChecksum, &error_code, &error_msg, &dex_files)); } TEST_F(DexFileLoaderTest, GetMultiDexClassesDexName) { diff --git a/libdexfile/dex/dex_file_verifier_test.cc b/libdexfile/dex/dex_file_verifier_test.cc index 79e9c8be90..ba0b24d131 100644 --- a/libdexfile/dex/dex_file_verifier_test.cc +++ b/libdexfile/dex/dex_file_verifier_test.cc @@ -104,16 +104,13 @@ static std::unique_ptr OpenDexFileBase64(const char* base64, // read dex std::vector> tmp; - const DexFileLoader dex_file_loader; + DexFileLoader dex_file_loader(dex_bytes.get(), length, location); DexFileLoaderErrorCode error_code; - bool success = dex_file_loader.OpenAll(dex_bytes.get(), - length, - location, - /* verify= */ true, - /* verify_checksum= */ true, - &error_code, - error_msg, - &tmp); + bool success = dex_file_loader.Open(/* verify= */ true, + /* verify_checksum= */ true, + &error_code, + error_msg, + &tmp); CHECK(success) << *error_msg; EXPECT_EQ(1U, tmp.size()); std::unique_ptr dex_file = std::move(tmp[0]); diff --git a/libdexfile/dex/test_dex_file_builder.h b/libdexfile/dex/test_dex_file_builder.h index 283dd48401..964f196ac7 100644 --- a/libdexfile/dex/test_dex_file_builder.h +++ b/libdexfile/dex/test_dex_file_builder.h @@ -237,14 +237,12 @@ class TestDexFileBuilder { static constexpr bool kVerify = false; static constexpr bool kVerifyChecksum = false; std::string error_msg; - std::unique_ptr dex_file(DexFileLoader::Open( - dex_location, - location_checksum, - std::move(dex_file_data), - /*oat_dex_file=*/ nullptr, - kVerify, - kVerifyChecksum, - &error_msg)); + DexFileLoader dex_file_loader(std::move(dex_file_data), dex_location); + std::unique_ptr dex_file(dex_file_loader.Open(location_checksum, + /*oat_dex_file=*/nullptr, + kVerify, + kVerifyChecksum, + &error_msg)); CHECK(dex_file != nullptr) << error_msg; return dex_file; } diff --git a/libdexfile/external/dex_file_ext.cc b/libdexfile/external/dex_file_ext.cc index 7c0bf2da7e..c7b1cbb83a 100644 --- a/libdexfile/external/dex_file_ext.cc +++ b/libdexfile/external/dex_file_ext.cc @@ -179,12 +179,9 @@ ADexFile_Error ADexFile_create(const void* _Nonnull address, } std::string loc_str(location); - art::DexFileLoader loader; std::string error_msg; - std::unique_ptr dex_file = loader.Open(static_cast(address), - size, - loc_str, - header->checksum_, + art::DexFileLoader loader(static_cast(address), size, loc_str); + std::unique_ptr dex_file = loader.Open(header->checksum_, /*oat_dex_file=*/nullptr, /*verify=*/false, /*verify_checksum=*/false, diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 3561673450..6f75fbd9d5 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -660,16 +660,13 @@ class OatDumper { DexContainer::Section* main_section = dex_container->GetMainSection(); CHECK_EQ(dex_container->GetDataSection()->Size(), 0u); - const ArtDexFileLoader dex_file_loader; - std::unique_ptr dex(dex_file_loader.Open( - main_section->Begin(), - main_section->Size(), - vdex_dex_file->GetLocation(), - vdex_file->GetLocationChecksum(i), - /*oat_dex_file=*/ nullptr, - /*verify=*/ false, - /*verify_checksum=*/ true, - &error_msg)); + ArtDexFileLoader dex_file_loader( + main_section->Begin(), main_section->Size(), vdex_dex_file->GetLocation()); + std::unique_ptr dex(dex_file_loader.Open(vdex_file->GetLocationChecksum(i), + /*oat_dex_file=*/nullptr, + /*verify=*/false, + /*verify_checksum=*/true, + &error_msg)); if (dex == nullptr) { os << "Failed to load DexFile from layout container: " + error_msg; success = false; diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc index 601d21d7a3..af5bfab994 100644 --- a/odrefresh/odrefresh.cc +++ b/odrefresh/odrefresh.cc @@ -290,7 +290,6 @@ std::vector GenerateComponents( custom_generator) { std::vector components; - ArtDexFileLoader loader; for (const std::string& path : jars) { std::string actual_path = RewriteParentDirectoryIfNeeded(path); struct stat sb; @@ -302,7 +301,8 @@ std::vector GenerateComponents( std::vector checksums; std::vector dex_locations; std::string error_msg; - if (!loader.GetMultiDexChecksums(actual_path.c_str(), &checksums, &dex_locations, &error_msg)) { + if (!ArtDexFileLoader::GetMultiDexChecksums( + actual_path.c_str(), &checksums, &dex_locations, &error_msg)) { LOG(ERROR) << "Failed to get multi-dex checksums: " << error_msg; return {}; } diff --git a/openjdkjvmti/ti_class.cc b/openjdkjvmti/ti_class.cc index 37ceb37958..3d44516173 100644 --- a/openjdkjvmti/ti_class.cc +++ b/openjdkjvmti/ti_class.cc @@ -113,10 +113,8 @@ static std::unique_ptr MakeSingleDexFile(art::Thread* self, } uint32_t checksum = reinterpret_cast(map.Begin())->checksum_; std::string map_name = map.GetName(); - const art::ArtDexFileLoader dex_file_loader; - std::unique_ptr dex_file(dex_file_loader.Open(map_name, - checksum, - std::move(map), + art::ArtDexFileLoader dex_file_loader(std::move(map), map_name); + std::unique_ptr dex_file(dex_file_loader.Open(checksum, /*verify=*/true, /*verify_checksum=*/true, &error_msg)); diff --git a/openjdkjvmti/ti_class_definition.cc b/openjdkjvmti/ti_class_definition.cc index f1f559388d..a9e7b3191a 100644 --- a/openjdkjvmti/ti_class_definition.cc +++ b/openjdkjvmti/ti_class_definition.cc @@ -172,10 +172,8 @@ jvmtiError ArtClassDefinition::Init(const art::DexFile& dex_file) { if (dex_file.IsCompactDexFile()) { std::string error_msg; std::vector> dex_files; - const art::ArtDexFileLoader dex_file_loader; - if (!dex_file_loader.Open(dex_file.GetLocation().c_str(), - dex_file.GetLocation().c_str(), - /* verify= */ false, + art::ArtDexFileLoader dex_file_loader(dex_file.GetLocation()); + if (!dex_file_loader.Open(/* verify= */ false, /* verify_checksum= */ false, &error_msg, &dex_files)) { diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index d40964fb6e..aafca47605 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -725,10 +725,8 @@ jvmtiError Redefiner::AddRedefinition(ArtJvmTiEnv* env, const ArtClassDefinition } std::string name = map.GetName(); uint32_t checksum = reinterpret_cast(map.Begin())->checksum_; - const art::ArtDexFileLoader dex_file_loader; - std::unique_ptr dex_file(dex_file_loader.Open(name, - checksum, - std::move(map), + art::ArtDexFileLoader dex_file_loader(std::move(map), name); + std::unique_ptr dex_file(dex_file_loader.Open(checksum, /*verify=*/true, /*verify_checksum=*/true, error_msg_)); diff --git a/openjdkjvmti/ti_search.cc b/openjdkjvmti/ti_search.cc index 4d96732494..2e98e0db9f 100644 --- a/openjdkjvmti/ti_search.cc +++ b/openjdkjvmti/ti_search.cc @@ -235,10 +235,8 @@ jvmtiError SearchUtil::AddToBootstrapClassLoaderSearch(jvmtiEnv* env, std::string error_msg; std::vector> dex_files; - const art::ArtDexFileLoader dex_file_loader; - if (!dex_file_loader.Open(segment, - segment, - /* verify= */ true, + art::ArtDexFileLoader dex_file_loader(segment); + if (!dex_file_loader.Open(/* verify= */ true, /* verify_checksum= */ true, &error_msg, &dex_files)) { diff --git a/profman/profman.cc b/profman/profman.cc index 55c8555f53..21efd45ff3 100644 --- a/profman/profman.cc +++ b/profman/profman.cc @@ -607,34 +607,31 @@ class ProfMan final { static constexpr bool kVerifyChecksum = true; for (size_t i = 0; i < dex_locations_.size(); ++i) { std::string error_msg; - const ArtDexFileLoader dex_file_loader; std::vector> dex_files_for_location; // We do not need to verify the apk for processing profiles. if (use_apk_fd_list) { - if (dex_file_loader.OpenZip(apks_fd_[i], - dex_locations_[i], - /*verify=*/false, - kVerifyChecksum, - /*allow_no_dex_files=*/true, - &error_msg, - &dex_files_for_location)) { - } else { - LOG(ERROR) << "OpenZip failed for '" << dex_locations_[i] << "' " << error_msg; - return false; - } + ArtDexFileLoader dex_file_loader(apks_fd_[i], dex_locations_[i]); + if (dex_file_loader.Open(/*verify=*/false, + kVerifyChecksum, + /*allow_no_dex_files=*/true, + &error_msg, + &dex_files_for_location)) { + } else { + LOG(ERROR) << "OpenZip failed for '" << dex_locations_[i] << "' " << error_msg; + return false; + } } else { File file(apk_files_[i], O_RDONLY, /*check_usage=*/false); if (file.Fd() < 0) { PLOG(ERROR) << "Unable to open '" << apk_files_[i] << "'"; return false; } - if (dex_file_loader.OpenZip(file.Release(), - dex_locations_[i], - /*verify=*/false, - kVerifyChecksum, - /*allow_no_dex_files=*/true, - &error_msg, - &dex_files_for_location)) { + ArtDexFileLoader dex_file_loader(file.Release(), dex_locations_[i]); + if (dex_file_loader.Open(/*verify=*/false, + kVerifyChecksum, + /*allow_no_dex_files=*/true, + &error_msg, + &dex_files_for_location)) { } else { LOG(ERROR) << "Open failed for '" << dex_locations_[i] << "' " << error_msg; return false; diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc index 722b8f7a64..074a819d0a 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -438,7 +438,6 @@ bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir, // We may get resource-only apks which we cannot load. // TODO(calin): Refine the dex opening interface to be able to tell if an archive contains // no dex files. So that we can distinguish the real failures... - const ArtDexFileLoader dex_file_loader; std::vector work_list; if (class_loader_chain_ == nullptr) { return true; @@ -480,12 +479,12 @@ bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir, std::string error_msg; if (only_read_checksums) { bool zip_file_only_contains_uncompress_dex; - if (!dex_file_loader.GetMultiDexChecksums(location.c_str(), - &dex_checksums, - &dex_locations, - &error_msg, - fd, - &zip_file_only_contains_uncompress_dex)) { + if (!ArtDexFileLoader::GetMultiDexChecksums(location.c_str(), + &dex_checksums, + &dex_locations, + &error_msg, + fd, + &zip_file_only_contains_uncompress_dex)) { LOG(WARNING) << "Could not get dex checksums for location " << location << ", fd=" << fd; dex_files_state_ = kDexFilesOpenFailed; } @@ -495,11 +494,9 @@ bool ClassLoaderContext::OpenDexFiles(const std::string& classpath_dir, // We don't need to do structural dex file verification, we only need to // check the checksum, so pass false to verify. size_t opened_dex_files_index = info->opened_dex_files.size(); - if (!dex_file_loader.Open(location.c_str(), - fd, - location.c_str(), - /*verify=*/ false, - /*verify_checksum=*/ true, + ArtDexFileLoader dex_file_loader(location.c_str(), fd, location); + if (!dex_file_loader.Open(/*verify=*/false, + /*verify_checksum=*/true, &error_msg, &info->opened_dex_files)) { LOG(WARNING) << "Could not open dex files for location " << location << ", fd=" << fd; diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index 131d0d8548..ee574bca62 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -572,10 +572,8 @@ void CommonRuntimeTestImpl::VisitDexes(ArrayRef dexes, for (const std::string& dex : dexes) { std::vector> dex_files; std::string error_msg; - const ArtDexFileLoader dex_file_loader; - CHECK(dex_file_loader.Open(dex.c_str(), - dex, - /*verify*/ true, + ArtDexFileLoader dex_file_loader(dex); + CHECK(dex_file_loader.Open(/*verify*/ true, /*verify_checksum*/ false, &error_msg, &dex_files)) diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h index 56e32254d9..85c48a240c 100644 --- a/runtime/common_runtime_test.h +++ b/runtime/common_runtime_test.h @@ -88,13 +88,12 @@ class CommonRuntimeTestImpl : public CommonArtTestImpl { bool MutateDexFile(File* output_dex, const std::string& input_jar, const Mutator& mutator) { std::vector> dex_files; std::string error_msg; - const ArtDexFileLoader dex_file_loader; - CHECK(dex_file_loader.Open(input_jar.c_str(), - input_jar.c_str(), - /*verify=*/ true, - /*verify_checksum=*/ true, + ArtDexFileLoader dex_file_loader(input_jar); + CHECK(dex_file_loader.Open(/*verify=*/true, + /*verify_checksum=*/true, &error_msg, - &dex_files)) << error_msg; + &dex_files)) + << error_msg; EXPECT_EQ(dex_files.size(), 1u) << "Only one input dex is supported"; const std::unique_ptr& dex = dex_files[0]; CHECK(dex->EnableWrite()) << "Failed to enable write"; diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h index deda75ad9a..c7febcd4fb 100644 --- a/runtime/dex2oat_environment_test.h +++ b/runtime/dex2oat_environment_test.h @@ -97,8 +97,6 @@ class Dex2oatEnvironmentTest : public Dex2oatScratchDirs, public CommonRuntimeTe CommonRuntimeTest::SetUp(); Dex2oatScratchDirs::SetUp(android_data_); - const ArtDexFileLoader dex_file_loader; - // Verify the environment is as we expect std::vector checksums; std::vector dex_locations; @@ -109,7 +107,7 @@ class Dex2oatEnvironmentTest : public Dex2oatScratchDirs, public CommonRuntimeTe << "Expected dex file to be at: " << GetDexSrc1(); ASSERT_TRUE(OS::FileExists(GetResourceOnlySrc1().c_str())) << "Expected stripped dex file to be at: " << GetResourceOnlySrc1(); - ASSERT_TRUE(dex_file_loader.GetMultiDexChecksums( + ASSERT_TRUE(ArtDexFileLoader::GetMultiDexChecksums( GetResourceOnlySrc1().c_str(), &checksums, &dex_locations, &error_msg)) << "Expected stripped dex file to be stripped: " << GetResourceOnlySrc1(); ASSERT_TRUE(OS::FileExists(GetDexSrc2().c_str())) @@ -119,21 +117,15 @@ class Dex2oatEnvironmentTest : public Dex2oatScratchDirs, public CommonRuntimeTe // GetMultiDexSrc1, but a different secondary dex checksum. static constexpr bool kVerifyChecksum = true; std::vector> multi1; - ASSERT_TRUE(dex_file_loader.Open(GetMultiDexSrc1().c_str(), - GetMultiDexSrc1().c_str(), - /* verify= */ true, - kVerifyChecksum, - &error_msg, - &multi1)) << error_msg; + ArtDexFileLoader dex_file_loader1(GetMultiDexSrc1()); + ASSERT_TRUE(dex_file_loader1.Open(/* verify= */ true, kVerifyChecksum, &error_msg, &multi1)) + << error_msg; ASSERT_GT(multi1.size(), 1u); std::vector> multi2; - ASSERT_TRUE(dex_file_loader.Open(GetMultiDexSrc2().c_str(), - GetMultiDexSrc2().c_str(), - /* verify= */ true, - kVerifyChecksum, - &error_msg, - &multi2)) << error_msg; + ArtDexFileLoader dex_file_loader2(GetMultiDexSrc2()); + ASSERT_TRUE(dex_file_loader2.Open(/* verify= */ true, kVerifyChecksum, &error_msg, &multi2)) + << error_msg; ASSERT_GT(multi2.size(), 1u); ASSERT_EQ(multi1[0]->GetLocationChecksum(), multi2[0]->GetLocationChecksum()); diff --git a/runtime/dexopt_test.cc b/runtime/dexopt_test.cc index 1f44a67500..6ba75737f5 100644 --- a/runtime/dexopt_test.cc +++ b/runtime/dexopt_test.cc @@ -120,10 +120,9 @@ void DexoptTest::GenerateOatForTest(const std::string& dex_location, // doesn't get an empty profile and changes the filter to verify. std::string error_msg; std::vector> dex_files; - const ArtDexFileLoader dex_file_loader; + ArtDexFileLoader dex_file_loader(dex_location); ASSERT_TRUE(dex_file_loader.Open( - dex_location.c_str(), dex_location.c_str(), /*verify=*/ false, /*verify_checksum=*/ false, - &error_msg, &dex_files)); + /*verify=*/false, /*verify_checksum=*/false, &error_msg, &dex_files)); EXPECT_GE(dex_files.size(), 1U); std::unique_ptr& dex_file = dex_files[0]; ProfileCompilationInfo info; diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 4860509d9a..02ad72b01d 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -3420,7 +3420,6 @@ bool ImageSpace::ValidateOatFile(const OatFile& oat_file, return false; } - const ArtDexFileLoader dex_file_loader; size_t dex_file_index = 0; for (const OatDexFile* oat_dex_file : oat_file.GetOatDexFiles()) { // Skip multidex locations - These will be checked when we visit their @@ -3437,7 +3436,7 @@ bool ImageSpace::ValidateOatFile(const OatFile& oat_file, std::vector checksums; std::vector dex_locations_ignored; - if (!dex_file_loader.GetMultiDexChecksums( + if (!ArtDexFileLoader::GetMultiDexChecksums( dex_file_location.c_str(), &checksums, &dex_locations_ignored, error_msg, dex_fd)) { *error_msg = StringPrintf("ValidateOatFile failed to get checksums of dex file '%s' " "referenced by oat file %s: %s", diff --git a/runtime/hidden_api_test.cc b/runtime/hidden_api_test.cc index a3d5db1f79..c2c40c5af3 100644 --- a/runtime/hidden_api_test.cc +++ b/runtime/hidden_api_test.cc @@ -63,12 +63,11 @@ static bool LoadDexFiles(const std::string& path, /* out */ std::vector>* dex_files, /* out */ ObjPtr* class_loader, /* out */ std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) { - if (!ArtDexFileLoader().Open(path.c_str(), - path, - /* verify= */ true, - /* verify_checksum= */ true, - error_msg, - dex_files)) { + ArtDexFileLoader dex_file_loader(path); + if (!dex_file_loader.Open(/* verify= */ true, + /* verify_checksum= */ true, + error_msg, + dex_files)) { return false; } diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index de14835b23..ab26ee963b 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -787,30 +787,24 @@ bool OatFileBase::Setup(int zip_fd, if (i == external_dex_files_.size()) { std::vector> new_dex_files; // No dex files, load it from location. - const ArtDexFileLoader dex_file_loader; bool loaded = false; CHECK(zip_fd == -1 || dex_fds.empty()); // Allow only the supported combinations. if (zip_fd != -1) { - loaded = dex_file_loader.OpenZip(zip_fd, - dex_file_location, - /*verify=*/false, - /*verify_checksum=*/false, - /*allow_no_dex_files=*/false, - error_msg, - &new_dex_files); + ArtDexFileLoader dex_file_loader(zip_fd, dex_file_location); + loaded = dex_file_loader.Open(/*verify=*/false, + /*verify_checksum=*/false, + error_msg, + &new_dex_files); } else if (dex_fd != -1) { // Note that we assume dex_fds are backing by jars. - loaded = dex_file_loader.OpenZipFromOwnedFd(dex_fd, - dex_file_location, - /*verify=*/false, - /*verify_checksum=*/false, - /*allow_no_dex_files=*/false, - error_msg, - &new_dex_files); + ArtDexFileLoader dex_file_loader(DupCloexec(dex_fd), dex_file_location); + loaded = dex_file_loader.Open(/*verify=*/false, + /*verify_checksum=*/false, + error_msg, + &new_dex_files); } else { - loaded = dex_file_loader.Open(dex_file_name.c_str(), - dex_file_location, - /*verify=*/false, + ArtDexFileLoader dex_file_loader(dex_file_name.c_str(), dex_file_location); + loaded = dex_file_loader.Open(/*verify=*/false, /*verify_checksum=*/false, error_msg, &new_dex_files); @@ -1806,20 +1800,16 @@ class OatFileBackedByVdex final : public OatFileBase { } else { // No need for any verification when loading dex files as we already have // a vdex file. - const ArtDexFileLoader dex_file_loader; bool loaded = false; if (zip_fd != -1) { - loaded = dex_file_loader.OpenZip(zip_fd, - dex_location, - /*verify=*/false, - /*verify_checksum=*/false, - /*allow_no_dex_files=*/false, - error_msg, - &oat_file->external_dex_files_); + ArtDexFileLoader dex_file_loader(zip_fd, dex_location); + loaded = dex_file_loader.Open(/*verify=*/false, + /*verify_checksum=*/false, + error_msg, + &oat_file->external_dex_files_); } else { - loaded = dex_file_loader.Open(dex_location.c_str(), - dex_location, - /*verify=*/false, + ArtDexFileLoader dex_file_loader(dex_location); + loaded = dex_file_loader.Open(/*verify=*/false, /*verify_checksum=*/false, error_msg, &oat_file->external_dex_files_); @@ -2250,15 +2240,9 @@ std::unique_ptr OatDexFile::OpenDexFile(std::string* error_msg) c ScopedTrace trace(__PRETTY_FUNCTION__); static constexpr bool kVerify = false; static constexpr bool kVerifyChecksum = false; - const ArtDexFileLoader dex_file_loader; - return dex_file_loader.Open(dex_file_pointer_, - FileSize(), - dex_file_location_, - dex_file_location_checksum_, - this, - kVerify, - kVerifyChecksum, - error_msg); + ArtDexFileLoader dex_file_loader(dex_file_pointer_, FileSize(), dex_file_location_); + return dex_file_loader.Open( + dex_file_location_checksum_, this, kVerify, kVerifyChecksum, error_msg); } uint32_t OatDexFile::GetOatClassOffset(uint16_t class_def_index) const { diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 1b49ce9b38..d324a241b7 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -726,14 +726,13 @@ const std::vector* OatFileAssistant::GetRequiredDexChecksums(std::stri if (!required_dex_checksums_attempted_) { required_dex_checksums_attempted_ = true; std::vector checksums; - const ArtDexFileLoader dex_file_loader; std::vector dex_locations_ignored; - if (dex_file_loader.GetMultiDexChecksums(dex_location_.c_str(), - &checksums, - &dex_locations_ignored, - &cached_required_dex_checksums_error_, - zip_fd_, - &zip_file_only_contains_uncompressed_dex_)) { + if (ArtDexFileLoader::GetMultiDexChecksums(dex_location_.c_str(), + &checksums, + &dex_locations_ignored, + &cached_required_dex_checksums_error_, + zip_fd_, + &zip_file_only_contains_uncompressed_dex_)) { if (checksums.empty()) { // The only valid case here is for APKs without dex files. VLOG(oat) << "No dex file found in " << dex_location_; diff --git a/runtime/oat_file_assistant_context.cc b/runtime/oat_file_assistant_context.cc index 4bd83b7023..c3fb73de4b 100644 --- a/runtime/oat_file_assistant_context.cc +++ b/runtime/oat_file_assistant_context.cc @@ -158,8 +158,7 @@ const std::vector* OatFileAssistantContext::GetBcpChecksums(size_t std::vector checksums; std::vector dex_locations; - ArtDexFileLoader dex_file_loader; - if (!dex_file_loader.GetMultiDexChecksums( + if (!ArtDexFileLoader::GetMultiDexChecksums( runtime_options_->boot_class_path[bcp_index].c_str(), &checksums, &dex_locations, diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index 45f763137a..baa3094f29 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -117,10 +117,8 @@ class OatFileAssistantTest : public OatFileAssistantBaseTest, bool InsertNewBootClasspathEntry(const std::string& src, std::string* error_msg) { std::vector> dex_files; - ArtDexFileLoader dex_file_loader; - if (!dex_file_loader.Open(src.c_str(), - src, - /*verify=*/true, + ArtDexFileLoader dex_file_loader(src); + if (!dex_file_loader.Open(/*verify=*/true, /*verify_checksum=*/false, error_msg, &dex_files)) { diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc index 71af566c63..7d68ccad3c 100644 --- a/runtime/oat_file_manager.cc +++ b/runtime/oat_file_manager.cc @@ -450,10 +450,8 @@ std::vector> OatFileManager::OpenDexFilesFromOat( if (dex_files.empty()) { std::string error_msg; static constexpr bool kVerifyChecksum = true; - const ArtDexFileLoader dex_file_loader; - if (!dex_file_loader.Open(dex_location, - dex_location, - Runtime::Current()->IsVerificationEnabled(), + ArtDexFileLoader dex_file_loader(dex_location); + if (!dex_file_loader.Open(Runtime::Current()->IsVerificationEnabled(), kVerifyChecksum, /*out*/ &error_msg, &dex_files)) { @@ -556,11 +554,10 @@ std::vector> OatFileManager::OpenDexFilesFromOat_ std::vector> dex_files; for (size_t i = 0; i < dex_mem_maps.size(); ++i) { static constexpr bool kVerifyChecksum = true; - const ArtDexFileLoader dex_file_loader; + ArtDexFileLoader dex_file_loader(std::move(dex_mem_maps[i]), + DexFileLoader::GetMultiDexLocation(i, dex_location.c_str())); std::unique_ptr dex_file(dex_file_loader.Open( - DexFileLoader::GetMultiDexLocation(i, dex_location.c_str()), dex_headers[i]->checksum_, - std::move(dex_mem_maps[i]), /* verify= */ (vdex_file == nullptr) && Runtime::Current()->IsVerificationEnabled(), kVerifyChecksum, &error_msg)); diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 040d819608..86c7772b90 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -1291,7 +1291,6 @@ static size_t OpenBootDexFiles(ArrayRef dex_filenames, std::vector>* dex_files) { DCHECK(dex_files != nullptr) << "OpenDexFiles: out-param is nullptr"; size_t failure_count = 0; - const ArtDexFileLoader dex_file_loader; for (size_t i = 0; i < dex_filenames.size(); i++) { const char* dex_filename = dex_filenames[i].c_str(); const char* dex_location = dex_locations[i].c_str(); @@ -1303,13 +1302,8 @@ static size_t OpenBootDexFiles(ArrayRef dex_filenames, continue; } bool verify = Runtime::Current()->IsVerificationEnabled(); - if (!dex_file_loader.Open(dex_filename, - dex_fd, - dex_location, - verify, - kVerifyChecksum, - &error_msg, - dex_files)) { + ArtDexFileLoader dex_file_loader(dex_filename, dex_fd, dex_location); + if (!dex_file_loader.Open(verify, kVerifyChecksum, &error_msg, dex_files)) { LOG(WARNING) << "Failed to open .dex from file '" << dex_filename << "' / fd " << dex_fd << ": " << error_msg; ++failure_count; diff --git a/runtime/sdk_checker.cc b/runtime/sdk_checker.cc index 1dbe39c32e..9097dc62a2 100644 --- a/runtime/sdk_checker.cc +++ b/runtime/sdk_checker.cc @@ -30,16 +30,13 @@ SdkChecker* SdkChecker::Create( std::vector dex_file_paths; Split(public_sdk, ':', &dex_file_paths); - ArtDexFileLoader dex_loader; - std::unique_ptr sdk_checker(new SdkChecker()); for (const std::string& path : dex_file_paths) { - if (!dex_loader.Open(path.c_str(), - path, - /*verify=*/ true, - /*verify_checksum*/ false, - error_msg, - &sdk_checker->sdk_dex_files_)) { + DexFileLoader dex_file_loader(path); + if (!dex_file_loader.Open(/*verify=*/true, + /*verify_checksum*/ false, + error_msg, + &sdk_checker->sdk_dex_files_)) { return nullptr; } } diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc index 6ad8a0f91b..bdead55390 100644 --- a/runtime/vdex_file.cc +++ b/runtime/vdex_file.cc @@ -215,7 +215,6 @@ const uint8_t* VdexFile::GetNextTypeLookupTableData(const uint8_t* cursor, bool VdexFile::OpenAllDexFiles(std::vector>* dex_files, std::string* error_msg) const { - const ArtDexFileLoader dex_file_loader; size_t i = 0; for (const uint8_t* dex_file_start = GetNextDexFileData(nullptr, i); dex_file_start != nullptr; @@ -224,10 +223,8 @@ bool VdexFile::OpenAllDexFiles(std::vector>* dex_ // TODO: Supply the location information for a vdex file. static constexpr char kVdexLocation[] = ""; std::string location = DexFileLoader::GetMultiDexLocation(i, kVdexLocation); - std::unique_ptr dex(dex_file_loader.Open(dex_file_start, - size, - location, - GetLocationChecksum(i), + ArtDexFileLoader dex_file_loader(dex_file_start, size, location); + std::unique_ptr dex(dex_file_loader.Open(GetLocationChecksum(i), /*oat_dex_file=*/nullptr, /*verify=*/false, /*verify_checksum=*/false, diff --git a/test/674-hiddenapi/hiddenapi.cc b/test/674-hiddenapi/hiddenapi.cc index 5fa2532f12..f1b0c18c27 100644 --- a/test/674-hiddenapi/hiddenapi.cc +++ b/test/674-hiddenapi/hiddenapi.cc @@ -59,12 +59,10 @@ extern "C" JNIEXPORT jint JNICALL Java_Main_appendToBootClassLoader( const jint int_index = static_cast(index); opened_dex_files.push_back(std::vector>()); - ArtDexFileLoader dex_loader; + DexFileLoader dex_loader(path); std::string error_msg; - if (!dex_loader.Open(path, - path, - /* verify */ false, + if (!dex_loader.Open(/* verify */ false, /* verify_checksum */ true, &error_msg, &opened_dex_files[index])) { diff --git a/test/983-source-transform-verify/source_transform_art.cc b/test/983-source-transform-verify/source_transform_art.cc index a1916a03bd..289874b95b 100644 --- a/test/983-source-transform-verify/source_transform_art.cc +++ b/test/983-source-transform-verify/source_transform_art.cc @@ -41,12 +41,9 @@ void VerifyClassData(jint class_data_len, const unsigned char* class_data) { CHECK_LE(static_cast(header_file_size), class_data_len); class_data_len = static_cast(header_file_size); - const ArtDexFileLoader dex_file_loader; + ArtDexFileLoader dex_file_loader(class_data, class_data_len, "fake_location.dex"); std::string error; - std::unique_ptr dex(dex_file_loader.Open(class_data, - class_data_len, - "fake_location.dex", - /*location_checksum*/ 0, + std::unique_ptr dex(dex_file_loader.Open(/*location_checksum*/ 0, /*oat_dex_file*/ nullptr, /*verify*/ true, /*verify_checksum*/ true, diff --git a/tools/art_verifier/art_verifier.cc b/tools/art_verifier/art_verifier.cc index 2f2562b973..e68d2ca3d5 100644 --- a/tools/art_verifier/art_verifier.cc +++ b/tools/art_verifier/art_verifier.cc @@ -42,11 +42,9 @@ namespace { bool LoadDexFile(const std::string& dex_filename, std::vector>* dex_files) { - const ArtDexFileLoader dex_file_loader; + ArtDexFileLoader dex_file_loader(dex_filename); std::string error_msg; - if (!dex_file_loader.Open(dex_filename.c_str(), - dex_filename.c_str(), - /* verify= */ true, + if (!dex_file_loader.Open(/* verify= */ true, /* verify_checksum= */ true, &error_msg, dex_files)) { diff --git a/tools/dexanalyze/dexanalyze.cc b/tools/dexanalyze/dexanalyze.cc index f0ce4c4607..0a3cd8c8a8 100644 --- a/tools/dexanalyze/dexanalyze.cc +++ b/tools/dexanalyze/dexanalyze.cc @@ -14,20 +14,21 @@ * limitations under the License. */ +#include + #include #include #include #include -#include - -#include "dexanalyze_bytecode.h" -#include "dexanalyze_experiments.h" -#include "dexanalyze_strings.h" +#include "base/mem_map.h" #include "dex/code_item_accessors-inl.h" #include "dex/dex_file.h" #include "dex/dex_file_loader.h" #include "dex/dex_instruction-inl.h" +#include "dexanalyze_bytecode.h" +#include "dexanalyze_experiments.h" +#include "dexanalyze_strings.h" namespace art { namespace dexanalyze { @@ -207,15 +208,13 @@ class DexAnalyze { return kExitCodeFailedToOpenFile; } std::vector> dex_files; - const DexFileLoader dex_file_loader; - if (!dex_file_loader.OpenAll(reinterpret_cast(content.data()), - content.size(), - filename.c_str(), - options.run_dex_file_verifier_, - options.verify_checksum_, - &error_code, - &error_msg, - &dex_files)) { + DexFileLoader dex_file_loader( + reinterpret_cast(content.data()), content.size(), filename); + if (!dex_file_loader.Open(options.run_dex_file_verifier_, + options.verify_checksum_, + &error_code, + &error_msg, + &dex_files)) { LOG(ERROR) << "OpenAll failed for " + filename << " with " << error_msg << std::endl; return kExitCodeFailedToOpenDex; } @@ -240,6 +239,7 @@ class DexAnalyze { } // namespace art int main(int argc, char** argv) { + art::MemMap::Init(); return art::dexanalyze::DexAnalyze::Run(argc, argv); } diff --git a/tools/hiddenapi/hiddenapi.cc b/tools/hiddenapi/hiddenapi.cc index c4e7d40d22..5c750af4aa 100644 --- a/tools/hiddenapi/hiddenapi.cc +++ b/tools/hiddenapi/hiddenapi.cc @@ -246,8 +246,8 @@ class DexMember { class ClassPath final { public: - ClassPath(const std::vector& dex_paths, bool open_writable, bool ignore_empty) { - OpenDexFiles(dex_paths, open_writable, ignore_empty); + ClassPath(const std::vector& dex_paths, bool ignore_empty) { + OpenDexFiles(dex_paths, ignore_empty); } template @@ -292,47 +292,18 @@ class ClassPath final { } private: - void OpenDexFiles(const std::vector& dex_paths, - bool open_writable, - bool ignore_empty) { - ArtDexFileLoader dex_loader; + void OpenDexFiles(const std::vector& dex_paths, bool ignore_empty) { std::string error_msg; - if (open_writable) { - for (const std::string& filename : dex_paths) { - File fd(filename.c_str(), O_RDWR, /* check_usage= */ false); - CHECK_NE(fd.Fd(), -1) << "Unable to open file '" << filename << "': " << strerror(errno); - - // Memory-map the dex file with MAP_SHARED flag so that changes in memory - // propagate to the underlying file. We run dex file verification as if - // the dex file was not in boot claass path to check basic assumptions, - // such as that at most one of public/private/protected flag is set. - // We do those checks here and skip them when loading the processed file - // into boot class path. - std::unique_ptr dex_file(dex_loader.OpenDex(fd.Release(), - /* location= */ filename, - /* verify= */ true, - /* verify_checksum= */ true, - /* mmap_shared= */ true, - &error_msg)); - CHECK(dex_file.get() != nullptr) << "Open failed for '" << filename << "' " << error_msg; - CHECK(dex_file->IsStandardDexFile()) << "Expected a standard dex file '" << filename << "'"; - CHECK(dex_file->EnableWrite()) - << "Failed to enable write permission for '" << filename << "'"; - dex_files_.push_back(std::move(dex_file)); - } - } else { - for (const std::string& filename : dex_paths) { - bool success = dex_loader.Open(filename.c_str(), - /* location= */ filename, - /* verify= */ true, - /* verify_checksum= */ true, - &error_msg, - &dex_files_); - // If requested ignore a jar with no classes.dex files. - if (!success && ignore_empty && error_msg != "Entry not found") { - CHECK(success) << "Open failed for '" << filename << "' " << error_msg; - } + for (const std::string& filename : dex_paths) { + DexFileLoader dex_file_loader(filename); + bool success = dex_file_loader.Open(/* verify= */ true, + /* verify_checksum= */ true, + &error_msg, + &dex_files_); + // If requested ignore a jar with no classes.dex files. + if (!success && ignore_empty && error_msg != "Entry not found") { + CHECK(success) << "Open failed for '" << filename << "' " << error_msg; } } } @@ -781,11 +752,9 @@ class DexFileEditor final { void ReloadDex(const char* filename) { std::string error_msg; - ArtDexFileLoader loader; + ArtDexFileLoader loader(filename); std::vector> dex_files; - bool ok = loader.Open(filename, - filename, - /*verify*/ true, + bool ok = loader.Open(/*verify*/ true, /*verify_checksum*/ true, &error_msg, &dex_files); @@ -912,9 +881,7 @@ class HiddenApi final { const std::string& input_path = boot_dex_paths_[i]; const std::string& output_path = output_dex_paths_[i]; - ClassPath boot_classpath({ input_path }, - /* open_writable= */ false, - /* ignore_empty= */ false); + ClassPath boot_classpath({input_path}, /* ignore_empty= */ false); DexFileEditor dex_editor; for (const DexFile* input_dex : boot_classpath.GetDexFiles()) { HiddenapiClassDataBuilder builder(*input_dex); @@ -1032,9 +999,7 @@ class HiddenApi final { std::set unresolved; // Open all dex files. - ClassPath boot_classpath(boot_dex_paths_, - /* open_writable= */ false, - /* ignore_empty= */ false); + ClassPath boot_classpath(boot_dex_paths_, /* ignore_empty= */ false); Hierarchy boot_hierarchy(boot_classpath, fragment_, verbose_); // Mark all boot dex members private. @@ -1043,9 +1008,7 @@ class HiddenApi final { }); // Open all dependency API stub dex files. - ClassPath dependency_classpath(dependency_stub_dex_paths_, - /* open_writable= */ false, - /* ignore_empty= */ false); + ClassPath dependency_classpath(dependency_stub_dex_paths_, /* ignore_empty= */ false); // Mark all dependency API stub dex members as coming from the dependency. dependency_classpath.ForEachDexMember([&](const DexMember& boot_member) { @@ -1057,9 +1020,7 @@ class HiddenApi final { // Ignore any empty stub jars as it just means that they provide no APIs // for the current kind, e.g. framework-sdkextensions does not provide // any public APIs. - ClassPath stub_classpath(android::base::Split(cp_entry.first, ":"), - /* open_writable= */ false, - /* ignore_empty= */ true); + ClassPath stub_classpath(android::base::Split(cp_entry.first, ":"), /*ignore_empty=*/true); Hierarchy stub_hierarchy(stub_classpath, fragment_, verbose_); const ApiStubs::Kind stub_api = cp_entry.second; diff --git a/tools/hiddenapi/hiddenapi_test.cc b/tools/hiddenapi/hiddenapi_test.cc index f408c6663b..36e80c5c23 100644 --- a/tools/hiddenapi/hiddenapi_test.cc +++ b/tools/hiddenapi/hiddenapi_test.cc @@ -106,7 +106,6 @@ class HiddenApiTest : public CommonRuntimeTest { } std::unique_ptr OpenDex(const ScratchFile& file) { - ArtDexFileLoader dex_loader; std::string error_msg; File fd(file.GetFilename(), O_RDONLY, /* check_usage= */ false); @@ -115,9 +114,9 @@ class HiddenApiTest : public CommonRuntimeTest { UNREACHABLE(); } - std::unique_ptr dex_file(dex_loader.OpenDex( - fd.Release(), /* location= */ file.GetFilename(), /* verify= */ true, - /* verify_checksum= */ true, /* mmap_shared= */ false, &error_msg)); + ArtDexFileLoader dex_loader(fd.Release(), file.GetFilename()); + std::unique_ptr dex_file(dex_loader.Open( + /* verify= */ true, /* verify_checksum= */ true, /* mmap_shared= */ false, &error_msg)); if (dex_file.get() == nullptr) { LOG(FATAL) << "Open failed for '" << file.GetFilename() << "' " << error_msg; UNREACHABLE(); diff --git a/tools/veridex/Android.bp b/tools/veridex/Android.bp index d5f5162419..7b120cfcc4 100644 --- a/tools/veridex/Android.bp +++ b/tools/veridex/Android.bp @@ -40,6 +40,7 @@ cc_binary { static_libs: [ "libdexfile", "libartbase", + "libartpalette", "libbase", "liblog", "libz", diff --git a/tools/veridex/veridex.cc b/tools/veridex/veridex.cc index ae1c33e1d2..2ef236d70e 100644 --- a/tools/veridex/veridex.cc +++ b/tools/veridex/veridex.cc @@ -19,6 +19,10 @@ #include #include +#include +#include + +#include "base/mem_map.h" #include "dex/dex_file.h" #include "dex/dex_file_loader.h" #include "hidden_api.h" @@ -26,9 +30,6 @@ #include "precise_hidden_api_finder.h" #include "resolver.h" -#include -#include - namespace art { static VeriClass z_(Primitive::Type::kPrimBoolean, 0, nullptr); @@ -301,18 +302,13 @@ class Veridex { return false; } - const DexFileLoader dex_file_loader; DexFileLoaderErrorCode error_code; static constexpr bool kVerifyChecksum = true; static constexpr bool kRunDexFileVerifier = true; - if (!dex_file_loader.OpenAll(reinterpret_cast(content.data()), - content.size(), - filename.c_str(), - kRunDexFileVerifier, - kVerifyChecksum, - &error_code, - error_msg, - dex_files)) { + DexFileLoader dex_file_loader( + reinterpret_cast(content.data()), content.size(), filename.c_str()); + if (!dex_file_loader.Open( + kRunDexFileVerifier, kVerifyChecksum, &error_code, error_msg, dex_files)) { if (error_code == DexFileLoaderErrorCode::kEntryNotFound) { LOG(INFO) << "No .dex found, skipping analysis."; return true; @@ -343,5 +339,6 @@ class Veridex { } // namespace art int main(int argc, char** argv) { + art::MemMap::Init(); return art::Veridex::Run(argc, argv); }