summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2017-09-25 16:22:36 -0700
committer Mathieu Chartier <mathieuc@google.com> 2017-10-18 15:45:31 -0700
commitcf76bf83147f30cf23c70cfb7834a07420775143 (patch)
tree4b2b7c0f05c58214bbeb613bf3b0fec3d1a4cfc2
parent24276374dcaf95bfc52be2b8193eb4e337de62e4 (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.cc8
-rw-r--r--runtime/Android.bp2
-rw-r--r--runtime/cdex/compact_dex_file.cc41
-rw-r--r--runtime/cdex/compact_dex_file.h54
-rw-r--r--runtime/cdex/compact_dex_file_test.cc50
-rw-r--r--runtime/dex_file_loader.cc24
-rw-r--r--runtime/dex_file_loader.h7
-rw-r--r--runtime/oat_file.cc4
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(),