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