Separate MemMap from DexFile completely
Create a container class for holding ownership of MemMap and segregate
that functionality to dex_file_loader. This removes the dependency
between dex_file.cc and mem_map.cc.
Bug: 22322814
Test: make test-art-host
Change-Id: I96db6fd10cdbad774c2f1f85c249418a154fbd52
diff --git a/runtime/cdex/compact_dex_file.h b/runtime/cdex/compact_dex_file.h
index 910473b..3c1b638 100644
--- a/runtime/cdex/compact_dex_file.h
+++ b/runtime/cdex/compact_dex_file.h
@@ -51,8 +51,9 @@
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) {}
+ const OatDexFile* oat_dex_file,
+ DexFileContainer* container)
+ : DexFile(base, size, location, location_checksum, oat_dex_file, container) {}
friend class DexFile;
friend class DexFileLoader;
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index bd73692..3e92317 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -1466,6 +1466,7 @@
old_dex_file->Size(),
location->ToModifiedUtf8(),
0u,
+ nullptr,
nullptr));
{
WriterMutexLock mu(soa.Self(), *Locks::dex_lock_);
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index f2c43f7..974c7ac 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -16,13 +16,10 @@
#include "dex_file.h"
-#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/file.h>
-#include <sys/mman.h> // For the PROT_* and MAP_* constants.
#include <zlib.h>
#include <memory>
@@ -35,11 +32,7 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "dex_file-inl.h"
-#include "dex_file_loader.h"
-#include "jvalue.h"
#include "leb128.h"
-#include "mem_map.h"
-#include "os.h"
#include "standard_dex_file.h"
#include "utf-inl.h"
#include "utils.h"
@@ -59,46 +52,32 @@
return adler32(adler32(0L, Z_NULL, 0), non_sum_ptr, Size() - non_sum);
}
-struct DexFile::AnnotationValue {
- JValue value_;
- uint8_t type_;
-};
-
int DexFile::GetPermissions() const {
- if (mem_map_.get() == nullptr) {
- return 0;
- } else {
- return mem_map_->GetProtect();
- }
+ CHECK(container_.get() != nullptr);
+ return container_->GetPermissions();
}
bool DexFile::IsReadOnly() const {
- return GetPermissions() == PROT_READ;
+ CHECK(container_.get() != nullptr);
+ return container_->IsReadOnly();
}
bool DexFile::EnableWrite() const {
- CHECK(IsReadOnly());
- if (mem_map_.get() == nullptr) {
- return false;
- } else {
- return mem_map_->Protect(PROT_READ | PROT_WRITE);
- }
+ CHECK(container_.get() != nullptr);
+ return container_->EnableWrite();
}
bool DexFile::DisableWrite() const {
- CHECK(!IsReadOnly());
- if (mem_map_.get() == nullptr) {
- return false;
- } else {
- return mem_map_->Protect(PROT_READ);
- }
+ CHECK(container_.get() != nullptr);
+ return container_->DisableWrite();
}
DexFile::DexFile(const uint8_t* base,
size_t size,
const std::string& location,
uint32_t location_checksum,
- const OatDexFile* oat_dex_file)
+ const OatDexFile* oat_dex_file,
+ DexFileContainer* container)
: begin_(base),
size_(size),
location_(location),
@@ -114,7 +93,8 @@
num_method_handles_(0),
call_site_ids_(nullptr),
num_call_site_ids_(0),
- oat_dex_file_(oat_dex_file) {
+ oat_dex_file_(oat_dex_file),
+ container_(container) {
CHECK(begin_ != nullptr) << GetLocation();
CHECK_GT(size_, 0U) << GetLocation();
// Check base (=header) alignment.
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 53e1f9e..c895e0d 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -39,6 +39,21 @@
class StringPiece;
class ZipArchive;
+// Some instances of DexFile own the storage referred to by DexFile. Clients who create
+// such management do so by subclassing Container.
+class DexFileContainer {
+ public:
+ DexFileContainer() { }
+ virtual ~DexFileContainer() { }
+ virtual int GetPermissions() = 0;
+ virtual bool IsReadOnly() = 0;
+ virtual bool EnableWrite() = 0;
+ virtual bool DisableWrite() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DexFileContainer);
+};
+
// Dex file is the API that exposes native dex files (ordinary dex files) and CompactDex.
// Originally, the dex file format used by ART was mostly the same as APKs. The only change was
// quickened opcodes and layout optimizations.
@@ -993,7 +1008,8 @@
size_t size,
const std::string& location,
uint32_t location_checksum,
- const OatDexFile* oat_dex_file);
+ const OatDexFile* oat_dex_file,
+ DexFileContainer* container);
// Top-level initializer that calls other Init methods.
bool Init(std::string* error_msg);
@@ -1018,9 +1034,6 @@
const uint32_t location_checksum_;
- // Manages the underlying memory allocation.
- std::unique_ptr<MemMap> mem_map_;
-
// Points to the header section.
const Header* const header_;
@@ -1059,6 +1072,9 @@
// null.
mutable const OatDexFile* oat_dex_file_;
+ // Manages the underlying memory allocation.
+ std::unique_ptr<DexFileContainer> container_;
+
friend class DexFileLoader;
friend class DexFileVerifierTest;
friend class OatWriter;
diff --git a/runtime/dex_file_loader.cc b/runtime/dex_file_loader.cc
index 26f7e76..06e3397 100644
--- a/runtime/dex_file_loader.cc
+++ b/runtime/dex_file_loader.cc
@@ -33,6 +33,50 @@
namespace art {
+namespace {
+
+class MemMapContainer : public DexFileContainer {
+ public:
+ explicit MemMapContainer(std::unique_ptr<MemMap>&& mem_map) : mem_map_(std::move(mem_map)) { }
+ virtual ~MemMapContainer() OVERRIDE { }
+
+ int GetPermissions() OVERRIDE {
+ if (mem_map_.get() == nullptr) {
+ return 0;
+ } else {
+ return mem_map_->GetProtect();
+ }
+ }
+
+ bool IsReadOnly() OVERRIDE {
+ return GetPermissions() == PROT_READ;
+ }
+
+ bool EnableWrite() OVERRIDE {
+ CHECK(IsReadOnly());
+ if (mem_map_.get() == nullptr) {
+ return false;
+ } else {
+ return mem_map_->Protect(PROT_READ | PROT_WRITE);
+ }
+ }
+
+ bool DisableWrite() OVERRIDE {
+ CHECK(!IsReadOnly());
+ if (mem_map_.get() == nullptr) {
+ return false;
+ } else {
+ return mem_map_->Protect(PROT_READ);
+ }
+ }
+
+ private:
+ std::unique_ptr<MemMap> mem_map_;
+ DISALLOW_COPY_AND_ASSIGN(MemMapContainer);
+};
+
+} // namespace
+
using android::base::StringPrintf;
static constexpr OatDexFile* kNoOatDexFile = nullptr;
@@ -151,7 +195,9 @@
oat_dex_file,
verify,
verify_checksum,
- error_msg);
+ error_msg,
+ /*container*/ nullptr,
+ /*verify_result*/ nullptr);
}
std::unique_ptr<const DexFile> DexFileLoader::Open(const std::string& location,
@@ -177,10 +223,9 @@
kNoOatDexFile,
verify,
verify_checksum,
- error_msg);
- if (dex_file != nullptr) {
- dex_file->mem_map_ = std::move(map);
- }
+ error_msg,
+ new MemMapContainer(std::move(map)),
+ /*verify_result*/ nullptr);
return dex_file;
}
@@ -296,10 +341,9 @@
kNoOatDexFile,
verify,
verify_checksum,
- error_msg);
- if (dex_file != nullptr) {
- dex_file->mem_map_ = std::move(map);
- }
+ error_msg,
+ new MemMapContainer(std::move(map)),
+ /*verify_result*/ nullptr);
return dex_file;
}
@@ -365,6 +409,7 @@
verify,
verify_checksum,
error_msg,
+ new MemMapContainer(std::move(map)),
&verify_result);
if (dex_file == nullptr) {
if (verify_result == VerifyResult::kVerifyNotAttempted) {
@@ -374,7 +419,6 @@
}
return nullptr;
}
- dex_file->mem_map_ = std::move(map);
if (!dex_file->DisableWrite()) {
*error_msg = StringPrintf("Failed to make dex file '%s' read only", location.c_str());
*error_code = ZipOpenErrorCode::kMakeReadOnlyError;
@@ -465,15 +509,18 @@
bool verify,
bool verify_checksum,
std::string* error_msg,
+ DexFileContainer* container,
VerifyResult* verify_result) {
if (verify_result != nullptr) {
*verify_result = VerifyResult::kVerifyNotAttempted;
}
std::unique_ptr<DexFile> dex_file;
if (StandardDexFile::IsMagicValid(base)) {
- dex_file.reset(new StandardDexFile(base, size, location, location_checksum, oat_dex_file));
+ dex_file.reset(
+ new StandardDexFile(base, size, location, location_checksum, oat_dex_file, container));
} else if (CompactDexFile::IsMagicValid(base)) {
- dex_file.reset(new CompactDexFile(base, size, location, location_checksum, oat_dex_file));
+ dex_file.reset(
+ new CompactDexFile(base, size, location, location_checksum, oat_dex_file, container));
}
if (dex_file == nullptr) {
*error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location.c_str(),
diff --git a/runtime/dex_file_loader.h b/runtime/dex_file_loader.h
index a1167dc..97c886a 100644
--- a/runtime/dex_file_loader.h
+++ b/runtime/dex_file_loader.h
@@ -25,6 +25,7 @@
namespace art {
class DexFile;
+class DexFileContainer;
class MemMap;
class OatDexFile;
class ZipArchive;
@@ -190,7 +191,8 @@
bool verify,
bool verify_checksum,
std::string* error_msg,
- VerifyResult* verify_result = nullptr);
+ DexFileContainer* container,
+ VerifyResult* verify_result);
};
} // namespace art
diff --git a/runtime/dex_file_verifier_test.cc b/runtime/dex_file_verifier_test.cc
index 7bda89d..ee577e7 100644
--- a/runtime/dex_file_verifier_test.cc
+++ b/runtime/dex_file_verifier_test.cc
@@ -57,7 +57,7 @@
class DexFileVerifierTest : public CommonRuntimeTest {
protected:
DexFile* GetDexFile(const uint8_t* dex_bytes, size_t length) {
- return new StandardDexFile(dex_bytes, length, "tmp", 0, nullptr);
+ return new StandardDexFile(dex_bytes, length, "tmp", 0, nullptr, nullptr);
}
void VerifyModification(const char* dex_file_base64_content,
diff --git a/runtime/standard_dex_file.h b/runtime/standard_dex_file.h
index 4fa3efe..906b0b7 100644
--- a/runtime/standard_dex_file.h
+++ b/runtime/standard_dex_file.h
@@ -49,8 +49,9 @@
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) {}
+ const OatDexFile* oat_dex_file,
+ DexFileContainer* container)
+ : DexFile(base, size, location, location_checksum, oat_dex_file, container) {}
friend class DexFileLoader;
friend class DexFileVerifierTest;