diff options
author | 2023-02-13 12:42:12 +0000 | |
---|---|---|
committer | 2023-02-21 18:00:00 +0000 | |
commit | 052f5fb6d28717b7ff236c508f5fb36a7705f662 (patch) | |
tree | d148b944857d92cc4ad5666f7139c16b6ba56394 | |
parent | 4184f23701a64e9902ffced803968fcc5601764b (diff) |
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
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<std::unique_ptr<const DexFile>> 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<const DexFile>& dex_file = dex_files[0]; @@ -811,9 +811,9 @@ class Dex2oatLayoutTest : public Dex2oatTest { const char* location = dex_location.c_str(); std::vector<std::unique_ptr<const DexFile>> 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<const DexFile>& 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<std::unique_ptr<const DexFile>> 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<const uint8_t>& 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<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> dex_files; - if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(content.data()), - content.size(), - fileName, - kVerify, - kVerifyChecksum, - &error_code, - &error_msg, - &dex_files)) { + DexFileLoader dex_file_loader( + reinterpret_cast<const uint8_t*>(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 <android-base/logging.h> +#include <base/mem_map.h> #include <stdio.h> #include <string.h> #include <unistd.h> -#include <android-base/logging.h> +#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<DexLoaderContainer>( main_section->Begin(), main_section->End(), data_section->Begin(), data_section->End()); + ArtDexFileLoader dex_file_loader(std::move(container), location); std::unique_ptr<const DexFile> 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<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> 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<const DexFile>& 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<const DexFile> 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<const DexFile> 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 <android-base/file.h> #include <android-base/logging.h> +#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<std::unique_ptr<const DexFile>> dex_files; DexFileLoaderErrorCode error_code; std::string error_msg; - const DexFileLoader dex_file_loader; - if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(content.data()), - content.size(), - fileName, - /*verify=*/ true, - kVerifyChecksum, - &error_code, - &error_msg, - &dex_files)) { + DexFileLoader dex_file_loader( + reinterpret_cast<const uint8_t*>(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<const DexFile> 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<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> 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<const DexFile>& 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<uint32_t>* checksums, std::vector<std::string>* 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<const DexFile> 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<std::unique_ptr<const DexFile>> 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<const DexFile> 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<MemoryDexFileContainer>(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<const DexFile> ArtDexFileLoader::Open(std::unique_ptr<DexFileContainer> 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<const DexFile> 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<DexFile> dex_file = OpenCommon(location, - location_checksum, - kNoOatDexFile, - verify, - verify_checksum, - error_msg, - std::make_unique<MemMapContainer>(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<std::unique_ptr<const DexFile>>* 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<std::unique_ptr<const DexFile>>* 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<std::unique_ptr<const DexFile>>* 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<std::unique_ptr<const DexFile>>* 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<const DexFile> 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<const DexFile> 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<std::unique_ptr<const DexFile>>* 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<std::unique_ptr<const DexFile>>* 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<std::unique_ptr<const DexFile>>* dex_files) const { - DCHECK(dex_files != nullptr) << "DexFile::OpenZip: out-param is nullptr"; - std::unique_ptr<ZipArchive> 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<const DexFile> 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<const DexFile::Header*>(begin); - - std::unique_ptr<DexFile> dex_file = OpenCommon(location, - dex_header->checksum_, - kNoOatDexFile, - verify, - verify_checksum, - error_msg, - std::make_unique<MemMapContainer>(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<const DexFile> 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<ZipEntry> 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<MemMapContainer>(std::move(map), direct_mmap); - std::unique_ptr<DexFile> 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<std::unique_ptr<const DexFile>>* 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<const DexFile> 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<const DexFile> 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<size_t>::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<uint32_t>* checksums, - std::vector<std::string>* 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<const DexFile> 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<const DexFile> Open(std::unique_ptr<DexFileContainer> 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<const DexFile> 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<std::unique_ptr<const DexFile>>* dex_files) const; - bool Open(int fd, - const std::string& location, - bool verify, - bool verify_checksum, - std::string* error_msg, - std::vector<std::unique_ptr<const DexFile>>* 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<std::unique_ptr<const DexFile>>* dex_files) const; - - // Open a single dex file from an fd. This function closes the fd. - std::unique_ptr<const DexFile> 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<std::unique_ptr<const DexFile>>* 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<std::unique_ptr<const DexFile>>* 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<std::unique_ptr<const DexFile>>* dex_files) const; - - std::unique_ptr<const DexFile> 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<std::unique_ptr<const DexFile>>* 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<const DexFile> 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<std::unique_ptr<const DexFile>>* dex_files) const; + static bool GetMultiDexChecksums(const char* filename, + std::vector<uint32_t>* checksums, + std::vector<std::string>* 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<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> 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<uint32_t> checksums; std::vector<std::string> 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<uint32_t> checksums; std::vector<std::string> 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<std::unique_ptr<const DexFile>> dexes = OpenTestDexFiles("MultiDex"); ASSERT_EQ(2U, dexes.size()); @@ -144,8 +135,7 @@ TEST_F(ArtDexFileLoaderTest, GetMultiDexChecksumsEmptyZip) { std::vector<uint32_t> checksums; std::vector<std::string> 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<const DexFile> CreateFakeDex(bool compact_dex, std::vector<uint8 StandardDexFile::WriteMagic(data->data()); 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<const DexFile> dex(dex_file_loader.Open(data->data(), - data->size(), - "location", - /*location_checksum=*/ 123, + std::unique_ptr<const DexFile> 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 <sys/stat.h> + #include <memory> #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<uint8_t>&& 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<uint8_t> Extract(std::string* error_msg) { - std::vector<uint8_t> 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<uint8_t*>(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<uint8_t*>(&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<uint32_t>* checksums ATTRIBUTE_UNUSED, - std::vector<std::string>* 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<MemoryDexFileContainer>(base, base + size), location) {} -std::unique_ptr<const DexFile> DexFileLoader::Open( - const std::string& location, - uint32_t location_checksum, - std::vector<uint8_t>&& 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<VectorContainer>(std::move(memory)), - /*verify_result=*/nullptr); -} +DexFileLoader::DexFileLoader(std::vector<uint8_t>&& memory, const std::string& location) + : DexFileLoader(std::make_unique<VectorContainer>(std::move(memory)), location) {} -std::unique_ptr<const DexFile> 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<MemMapContainer>(std::move(mem_map)), location) {} + +std::unique_ptr<const DexFile> 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<MemoryDexFileContainer>(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<const DexFile> 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<std::unique_ptr<const DexFile>>* 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<const uint32_t*>(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<MemMapContainer>(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<std::unique_ptr<const DexFile>>* 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<const uint32_t*>(base); + + uint32_t magic; + if (!InitAndReadMagic(&magic, error_msg)) { + return false; + } + if (IsZipMagic(magic)) { - std::unique_ptr<DexZipArchive> zip_archive(DexZipArchive::Open(base, size, error_msg)); + std::unique_ptr<ZipArchive> 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<const DexFile::Header*>(base); - std::unique_ptr<const DexFile> dex_file(Open(base, - size, - location, - dex_header->checksum_, - /*oat_dex_file=*/ nullptr, - verify, - verify_checksum, - error_msg)); + std::unique_ptr<const DexFile> 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<DexFile> DexFileLoader::OpenCommon(const std::string& location, +std::unique_ptr<DexFile> DexFileLoader::OpenCommon(std::unique_ptr<DexFileContainer> 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<DexFileContainer> container, VerifyResult* verify_result) { CHECK(container != nullptr); const uint8_t* base = container->Begin(); @@ -322,12 +342,8 @@ std::unique_ptr<DexFile> 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<DexFile> 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<DexFile> DexFileLoader::OpenCommon(const std::string& location, } std::unique_ptr<const DexFile> 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<const DexFile> DexFileLoader::OpenOneDexFileFromZip( DexFileLoaderErrorCode* error_code, std::string* error_msg) const { CHECK(!location.empty()); - std::unique_ptr<DexZipEntry> zip_entry(zip_archive.Find(entry_name, error_msg)); + std::unique_ptr<ZipEntry> 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<const DexFile> DexFileLoader::OpenOneDexFileFromZip( return nullptr; } - std::vector<uint8_t> 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<MemMapContainer>(std::move(map), is_file_map); + container->SetIsZip(); + VerifyResult verify_result; - std::unique_ptr<const DexFile> dex_file = - OpenCommon(location, - zip_entry->GetCrc32(), - /*oat_dex_file=*/nullptr, - verify, - verify_checksum, - error_msg, - std::make_unique<VectorContainer>(std::move(map)), - &verify_result); + std::unique_ptr<const DexFile> 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<const DexFile> 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<const DexFile> 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<std::unique_ptr<const DexFile>>* 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 <cstdint> +#include <functional> #include <memory> #include <string> #include <vector> +#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>() : 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<uint32_t>* checksums, - std::vector<std::string>* 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<const DexFile> Open( - const std::string& location, - uint32_t location_checksum, - std::vector<uint8_t>&& 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<const DexFile> 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<std::unique_ptr<const DexFile>>* dex_files) const; + DexFileLoader(std::unique_ptr<DexFileContainer>&& 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<uint8_t>&& 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<const DexFile> Open(uint32_t location_checksum, + const OatDexFile* oat_dex_file, + bool verify, + bool verify_checksum, + std::string* error_msg); + + std::unique_ptr<const DexFile> 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<std::unique_ptr<const DexFile>>* dex_files); + + bool Open(bool verify, + bool verify_checksum, + DexFileLoaderErrorCode* error_code, + std::string* error_msg, + std::vector<std::unique_ptr<const DexFile>>* 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<std::unique_ptr<const DexFile>>* 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<std::unique_ptr<const DexFile>>* 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<DexFile> 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<DexFile> OpenCommon(std::unique_ptr<DexFileContainer> 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<DexFileContainer> 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<std::unique_ptr<const DexFile>>* 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<const DexFile> OpenOneDexFileFromZip(const DexZipArchive& zip_archive, + std::unique_ptr<const DexFile> 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> file_; + std::unique_ptr<DexFileContainer> 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<std::unique_ptr<const DexFile>> 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<const DexFile> OpenDexFileInMemoryBase64(const char* base DecodeDexFile(base64, dex_bytes); std::string error_message; - const DexFileLoader dex_file_loader; - std::unique_ptr<const DexFile> 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<const DexFile> 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<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> 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<const DexFile> OpenDexFileBase64(const char* base64, // read dex std::vector<std::unique_ptr<const DexFile>> 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<const DexFile> 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<const DexFile> 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<const DexFile> 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<const art::DexFile> dex_file = loader.Open(static_cast<const uint8_t*>(address), - size, - loc_str, - header->checksum_, + art::DexFileLoader loader(static_cast<const uint8_t*>(address), size, loc_str); + std::unique_ptr<const art::DexFile> 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<const DexFile> 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<const DexFile> 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<T> GenerateComponents( custom_generator) { std::vector<T> components; - ArtDexFileLoader loader; for (const std::string& path : jars) { std::string actual_path = RewriteParentDirectoryIfNeeded(path); struct stat sb; @@ -302,7 +301,8 @@ std::vector<T> GenerateComponents( std::vector<uint32_t> checksums; std::vector<std::string> 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<const art::DexFile> MakeSingleDexFile(art::Thread* self, } uint32_t checksum = reinterpret_cast<const art::DexFile::Header*>(map.Begin())->checksum_; std::string map_name = map.GetName(); - const art::ArtDexFileLoader dex_file_loader; - std::unique_ptr<const art::DexFile> 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<const art::DexFile> 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<std::unique_ptr<const art::DexFile>> 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<const art::DexFile::Header*>(map.Begin())->checksum_; - const art::ArtDexFileLoader dex_file_loader; - std::unique_ptr<const art::DexFile> dex_file(dex_file_loader.Open(name, - checksum, - std::move(map), + art::ArtDexFileLoader dex_file_loader(std::move(map), name); + std::unique_ptr<const art::DexFile> 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<std::unique_ptr<const art::DexFile>> 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<std::unique_ptr<const DexFile>> 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<ClassLoaderInfo*> 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<const std::string> dexes, for (const std::string& dex : dexes) { std::vector<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> 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<const DexFile>& 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<uint32_t> checksums; std::vector<std::string> 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<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> 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<const DexFile>& 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<uint32_t> checksums; std::vector<std::string> 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<std::unique_ptr<const DexFile>>* dex_files, /* out */ ObjPtr<mirror::ClassLoader>* 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<std::unique_ptr<const DexFile>> 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<const DexFile> 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<uint32_t>* OatFileAssistant::GetRequiredDexChecksums(std::stri if (!required_dex_checksums_attempted_) { required_dex_checksums_attempted_ = true; std::vector<uint32_t> checksums; - const ArtDexFileLoader dex_file_loader; std::vector<std::string> 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<std::string>* OatFileAssistantContext::GetBcpChecksums(size_t std::vector<uint32_t> checksums; std::vector<std::string> 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<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> 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<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat_ std::vector<std::unique_ptr<const DexFile>> 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<const DexFile> 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<const std::string> dex_filenames, std::vector<std::unique_ptr<const DexFile>>* 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<const std::string> 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<std::string> dex_file_paths; Split(public_sdk, ':', &dex_file_paths); - ArtDexFileLoader dex_loader; - std::unique_ptr<SdkChecker> 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<std::unique_ptr<const DexFile>>* 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<std::unique_ptr<const DexFile>>* dex_ // TODO: Supply the location information for a vdex file. static constexpr char kVdexLocation[] = ""; std::string location = DexFileLoader::GetMultiDexLocation(i, kVdexLocation); - std::unique_ptr<const DexFile> dex(dex_file_loader.Open(dex_file_start, - size, - location, - GetLocationChecksum(i), + ArtDexFileLoader dex_file_loader(dex_file_start, size, location); + std::unique_ptr<const DexFile> 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<jint>(index); opened_dex_files.push_back(std::vector<std::unique_ptr<const DexFile>>()); - 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<jint>(header_file_size), class_data_len); class_data_len = static_cast<jint>(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<const DexFile> dex(dex_file_loader.Open(class_data, - class_data_len, - "fake_location.dex", - /*location_checksum*/ 0, + std::unique_ptr<const DexFile> 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<std::unique_ptr<const DexFile>>* 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 <android-base/file.h> + #include <cstdint> #include <iostream> #include <set> #include <sstream> -#include <android-base/file.h> - -#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<std::unique_ptr<const DexFile>> dex_files; - const DexFileLoader dex_file_loader; - if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(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<const uint8_t*>(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<std::string>& dex_paths, bool open_writable, bool ignore_empty) { - OpenDexFiles(dex_paths, open_writable, ignore_empty); + ClassPath(const std::vector<std::string>& dex_paths, bool ignore_empty) { + OpenDexFiles(dex_paths, ignore_empty); } template <typename Fn> @@ -292,47 +292,18 @@ class ClassPath final { } private: - void OpenDexFiles(const std::vector<std::string>& dex_paths, - bool open_writable, - bool ignore_empty) { - ArtDexFileLoader dex_loader; + void OpenDexFiles(const std::vector<std::string>& 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<const DexFile> 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<std::unique_ptr<const DexFile>> 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<std::string> 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<const DexFile> 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<const DexFile> 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<const DexFile> 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 <android-base/file.h> #include <android-base/strings.h> +#include <cstdlib> +#include <sstream> + +#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 <cstdlib> -#include <sstream> - 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<const uint8_t*>(content.data()), - content.size(), - filename.c_str(), - kRunDexFileVerifier, - kVerifyChecksum, - &error_code, - error_msg, - dex_files)) { + DexFileLoader dex_file_loader( + reinterpret_cast<const uint8_t*>(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); } |