diff options
author | 2017-09-25 16:22:36 -0700 | |
---|---|---|
committer | 2017-10-18 15:45:31 -0700 | |
commit | cf76bf83147f30cf23c70cfb7834a07420775143 (patch) | |
tree | 4b2b7c0f05c58214bbeb613bf3b0fec3d1a4cfc2 | |
parent | 24276374dcaf95bfc52be2b8193eb4e337de62e4 (diff) |
Add CompactDexFile
Add holder class for CompactDex. Add unit test.
Bug: 63756964
Test: test-art-host
Change-Id: I304d7cb0e38b20e51132ea2c155f3db7bd50028a
-rw-r--r-- | dex2oat/linker/oat_writer.cc | 8 | ||||
-rw-r--r-- | runtime/Android.bp | 2 | ||||
-rw-r--r-- | runtime/cdex/compact_dex_file.cc | 41 | ||||
-rw-r--r-- | runtime/cdex/compact_dex_file.h | 54 | ||||
-rw-r--r-- | runtime/cdex/compact_dex_file_test.cc | 50 | ||||
-rw-r--r-- | runtime/dex_file_loader.cc | 24 | ||||
-rw-r--r-- | runtime/dex_file_loader.h | 7 | ||||
-rw-r--r-- | runtime/oat_file.cc | 4 |
8 files changed, 176 insertions, 14 deletions
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index 0fd24a8a8f..17ceca3662 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -417,7 +417,7 @@ bool OatWriter::AddDexFileSource(const char* filename, if (fd.Fd() == -1) { PLOG(ERROR) << "Failed to read magic number from dex file: '" << filename << "'"; return false; - } else if (DexFileLoader::IsValidMagic(magic)) { + } else if (DexFileLoader::IsMagicValid(magic)) { // The file is open for reading, not writing, so it's OK to let the File destructor // close it without checking for explicit Close(), so pass checkUsage = false. raw_dex_files_.emplace_back(new File(fd.Release(), location, /* checkUsage */ false)); @@ -481,7 +481,7 @@ bool OatWriter::AddVdexDexFilesSource(const VdexFile& vdex_file, return false; } - if (!DexFileLoader::IsValidMagic(current_dex_data)) { + if (!DexFileLoader::IsMagicValid(current_dex_data)) { LOG(ERROR) << "Invalid magic in vdex file created from " << location; return false; } @@ -3110,12 +3110,12 @@ bool OatWriter::ReadDexFileHeader(File* file, OatDexFile* oat_dex_file) { } bool OatWriter::ValidateDexFileHeader(const uint8_t* raw_header, const char* location) { - const bool valid_standard_dex_magic = StandardDexFile::IsMagicValid(raw_header); + const bool valid_standard_dex_magic = DexFileLoader::IsMagicValid(raw_header); if (!valid_standard_dex_magic) { LOG(ERROR) << "Invalid magic number in dex file header. " << " File: " << location; return false; } - if (!StandardDexFile::IsVersionValid(raw_header)) { + if (!DexFileLoader::IsVersionAndMagicValid(raw_header)) { LOG(ERROR) << "Invalid version number in dex file header. " << " File: " << location; return false; } diff --git a/runtime/Android.bp b/runtime/Android.bp index ddfbed4499..6fb8d66835 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -46,6 +46,7 @@ cc_defaults { "base/timing_logger.cc", "base/unix_file/fd_file.cc", "base/unix_file/random_access_file_utils.cc", + "cdex/compact_dex_file.cc", "cha.cc", "check_jni.cc", "class_linker.cc", @@ -548,6 +549,7 @@ art_cc_test { "base/transform_iterator_test.cc", "base/variant_map_test.cc", "base/unix_file/fd_file_test.cc", + "cdex/compact_dex_file_test.cc", "cha_test.cc", "class_linker_test.cc", "class_loader_context_test.cc", diff --git a/runtime/cdex/compact_dex_file.cc b/runtime/cdex/compact_dex_file.cc new file mode 100644 index 0000000000..dbe2c66ecc --- /dev/null +++ b/runtime/cdex/compact_dex_file.cc @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "compact_dex_file.h" + +namespace art { + +constexpr uint8_t CompactDexFile::kDexMagic[kDexMagicSize]; +constexpr uint8_t CompactDexFile::kDexMagicVersion[]; + +bool CompactDexFile::IsMagicValid(const uint8_t* magic) { + return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0); +} + +bool CompactDexFile::IsVersionValid(const uint8_t* magic) { + const uint8_t* version = &magic[sizeof(kDexMagic)]; + return memcmp(version, kDexMagicVersion, kDexVersionLen) == 0; +} + +bool CompactDexFile::IsMagicValid() const { + return IsMagicValid(header_->magic_); +} + +bool CompactDexFile::IsVersionValid() const { + return IsVersionValid(header_->magic_); +} + +} // namespace art diff --git a/runtime/cdex/compact_dex_file.h b/runtime/cdex/compact_dex_file.h new file mode 100644 index 0000000000..fa6eab2d76 --- /dev/null +++ b/runtime/cdex/compact_dex_file.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_CDEX_COMPACT_DEX_FILE_H_ +#define ART_RUNTIME_CDEX_COMPACT_DEX_FILE_H_ + +#include "dex_file.h" + +namespace art { + +// CompactDex is a currently ART internal dex file format that aims to reduce storage/RAM usage. +class CompactDexFile : public DexFile { + public: + static constexpr uint8_t kDexMagic[kDexMagicSize] = { 'c', 'd', 'e', 'x' }; + static constexpr uint8_t kDexMagicVersion[] = {'0', '0', '1', '\0'}; + + // Returns true if the byte string points to the magic value. + static bool IsMagicValid(const uint8_t* magic); + virtual bool IsMagicValid() const OVERRIDE; + + // Returns true if the byte string after the magic is the correct value. + static bool IsVersionValid(const uint8_t* magic); + virtual bool IsVersionValid() const OVERRIDE; + + private: + // Not supported yet. + CompactDexFile(const uint8_t* base, + size_t size, + const std::string& location, + uint32_t location_checksum, + const OatDexFile* oat_dex_file) + : DexFile(base, size, location, location_checksum, oat_dex_file) {} + + friend class DexFile; + + DISALLOW_COPY_AND_ASSIGN(CompactDexFile); +}; + +} // namespace art + +#endif // ART_RUNTIME_CDEX_COMPACT_DEX_FILE_H_ diff --git a/runtime/cdex/compact_dex_file_test.cc b/runtime/cdex/compact_dex_file_test.cc new file mode 100644 index 0000000000..6fe4bccd16 --- /dev/null +++ b/runtime/cdex/compact_dex_file_test.cc @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cdex/compact_dex_file.h" +#include "dex_file_loader.h" +#include "common_runtime_test.h" + +namespace art { + +class CompactDexFileTest : public CommonRuntimeTest {}; + +TEST_F(CompactDexFileTest, MagicAndVersion) { + // Test permutations of valid/invalid headers. + for (size_t i = 0; i < 2; ++i) { + for (size_t j = 0; j < 2; ++j) { + static const size_t len = CompactDexFile::kDexVersionLen + CompactDexFile::kDexMagicSize; + uint8_t header[len] = {}; + std::fill_n(header, len, 0x99); + const bool valid_magic = (i & 1) == 0; + const bool valid_version = (j & 1) == 0; + if (valid_magic) { + std::copy_n(CompactDexFile::kDexMagic, CompactDexFile::kDexMagicSize, header); + } + if (valid_version) { + std::copy_n(CompactDexFile::kDexMagicVersion, + CompactDexFile::kDexVersionLen, + header + CompactDexFile::kDexMagicSize); + } + EXPECT_EQ(valid_magic, CompactDexFile::IsMagicValid(header)); + EXPECT_EQ(valid_version, CompactDexFile::IsVersionValid(header)); + EXPECT_EQ(valid_magic, DexFileLoader::IsMagicValid(header)); + EXPECT_EQ(valid_magic && valid_version, DexFileLoader::IsVersionAndMagicValid(header)); + } + } +} + +} // namespace art diff --git a/runtime/dex_file_loader.cc b/runtime/dex_file_loader.cc index 8cab1a501a..e300e0e58f 100644 --- a/runtime/dex_file_loader.cc +++ b/runtime/dex_file_loader.cc @@ -25,6 +25,7 @@ #include "base/stl_util.h" #include "base/systrace.h" #include "base/unix_file/fd_file.h" +#include "cdex/compact_dex_file.h" #include "dex_file.h" #include "dex_file_verifier.h" #include "standard_dex_file.h" @@ -37,12 +38,23 @@ using android::base::StringPrintf; static constexpr OatDexFile* kNoOatDexFile = nullptr; -bool DexFileLoader::IsValidMagic(uint32_t magic) { - return IsValidMagic(reinterpret_cast<uint8_t*>(&magic)); +bool DexFileLoader::IsMagicValid(uint32_t magic) { + return IsMagicValid(reinterpret_cast<uint8_t*>(&magic)); } -bool DexFileLoader::IsValidMagic(const uint8_t* magic) { - return StandardDexFile::IsMagicValid(magic); +bool DexFileLoader::IsMagicValid(const uint8_t* magic) { + return StandardDexFile::IsMagicValid(magic) || + CompactDexFile::IsMagicValid(magic); +} + +bool DexFileLoader::IsVersionAndMagicValid(const uint8_t* magic) { + if (StandardDexFile::IsMagicValid(magic)) { + return StandardDexFile::IsVersionValid(magic); + } + if (CompactDexFile::IsMagicValid(magic)) { + return CompactDexFile::IsVersionValid(magic); + } + return false; } bool DexFileLoader::GetMultiDexChecksums(const char* filename, @@ -81,7 +93,7 @@ bool DexFileLoader::GetMultiDexChecksums(const char* filename, } while (zip_entry.get() != nullptr); return true; } - if (IsValidMagic(magic)) { + if (IsMagicValid(magic)) { std::unique_ptr<const DexFile> dex_file( OpenFile(fd.Release(), filename, false, false, error_msg)); if (dex_file == nullptr) { @@ -188,7 +200,7 @@ bool DexFileLoader::Open(const char* filename, if (IsZipMagic(magic)) { return OpenZip(fd.Release(), location, verify_checksum, error_msg, dex_files); } - if (IsValidMagic(magic)) { + if (IsMagicValid(magic)) { std::unique_ptr<const DexFile> dex_file(OpenFile(fd.Release(), location, /* verify */ true, diff --git a/runtime/dex_file_loader.h b/runtime/dex_file_loader.h index 61b5c71726..cb17eccfc9 100644 --- a/runtime/dex_file_loader.h +++ b/runtime/dex_file_loader.h @@ -39,8 +39,11 @@ class DexFileLoader { static constexpr char kMultiDexSeparator = '!'; // Return true if the magic is valid for dex or cdex. - static bool IsValidMagic(uint32_t magic); - static bool IsValidMagic(const uint8_t* magic); + static bool IsMagicValid(uint32_t magic); + static bool IsMagicValid(const uint8_t* magic); + + // Return true if the corresponding version and magic is valid. + static bool IsVersionAndMagicValid(const uint8_t* magic); // Returns the checksums of a file for comparison with GetLocationChecksum(). // For .dex files, this is the single header checksum. diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 781ddd7aae..1269dcad93 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -552,7 +552,7 @@ bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) { const uint8_t* dex_file_pointer = DexBegin() + dex_file_offset; - const bool valid_magic = StandardDexFile::IsMagicValid(dex_file_pointer); + const bool valid_magic = DexFileLoader::IsMagicValid(dex_file_pointer); if (UNLIKELY(!valid_magic)) { *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid " "dex file magic '%s'", @@ -562,7 +562,7 @@ bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) { dex_file_pointer); return false; } - if (UNLIKELY(!StandardDexFile::IsVersionValid(dex_file_pointer))) { + if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_pointer))) { *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid " "dex file version '%s'", GetLocation().c_str(), |