Rename DexFile to DexCache
Change-Id: I93fa3e4f7cf87fbaac974f0d2577628a23f0d8c2
diff --git a/src/dex_file.cc b/src/dex_file.cc
index e3c8fa0..506ae39 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -1,19 +1,270 @@
// Copyright 2011 Google Inc. All Rights Reserved.
#include "dex_file.h"
-#include "heap.h"
+
+#include <fcntl.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <map>
+
#include "globals.h"
#include "logging.h"
#include "object.h"
-#include "raw_dex_file.h"
+#include "scoped_ptr.h"
+#include "utils.h"
namespace art {
-void DexFile::Init(ObjectArray* strings, ObjectArray* classes, ObjectArray* methods, ObjectArray* fields) {
- Set(kStrings, strings);
- Set(kClasses, classes);
- Set(kMethods, methods);
- Set(kFields, fields);
+const byte RawDexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
+const byte RawDexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
+
+RawDexFile::Closer::~Closer() {}
+
+RawDexFile::MmapCloser::MmapCloser(void* addr, size_t length) : addr_(addr), length_(length) {
+ CHECK(addr != NULL);
+}
+RawDexFile::MmapCloser::~MmapCloser() {
+ if (munmap(addr_, length_) == -1) {
+ PLOG(INFO) << "munmap failed";
+ }
+}
+
+RawDexFile::PtrCloser::PtrCloser(byte* addr) : addr_(addr) {}
+RawDexFile::PtrCloser::~PtrCloser() { delete[] addr_; }
+
+RawDexFile* RawDexFile::OpenFile(const char* filename) {
+ CHECK(filename != NULL);
+ int fd = open(filename, O_RDONLY); // TODO: scoped_fd
+ if (fd == -1) {
+ PLOG(ERROR) << "open(\"" << filename << "\", O_RDONLY) failed";
+ return NULL;
+ }
+ struct stat sbuf;
+ memset(&sbuf, 0, sizeof(sbuf));
+ if (fstat(fd, &sbuf) == -1) {
+ PLOG(ERROR) << "fstat \"" << filename << "\" failed";
+ close(fd);
+ return NULL;
+ }
+ size_t length = sbuf.st_size;
+ void* addr = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
+ if (addr == MAP_FAILED) {
+ PLOG(ERROR) << "mmap \"" << filename << "\" failed";
+ close(fd);
+ return NULL;
+ }
+ close(fd);
+ byte* dex_file = reinterpret_cast<byte*>(addr);
+ Closer* closer = new MmapCloser(addr, length);
+ return Open(dex_file, length, closer);
+}
+
+RawDexFile* RawDexFile::OpenPtr(byte* ptr, size_t length) {
+ CHECK(ptr != NULL);
+ RawDexFile::Closer* closer = new PtrCloser(ptr);
+ return Open(ptr, length, closer);
+}
+
+RawDexFile* RawDexFile::Open(const byte* dex_file, size_t length,
+ Closer* closer) {
+ scoped_ptr<RawDexFile> raw(new RawDexFile(dex_file, length, closer));
+ if (!raw->Init()) {
+ return NULL;
+ } else {
+ return raw.release();
+ }
+}
+
+RawDexFile::~RawDexFile() {}
+
+bool RawDexFile::Init() {
+ InitMembers();
+ if (!IsMagicValid()) {
+ return false;
+ }
+ InitIndex();
+ return true;
+}
+
+void RawDexFile::InitMembers() {
+ const byte* b = base_;
+ header_ = reinterpret_cast<const Header*>(b);
+ const Header* h = header_;
+ string_ids_ = reinterpret_cast<const StringId*>(b + h->string_ids_off_);
+ type_ids_ = reinterpret_cast<const TypeId*>(b + h->type_ids_off_);
+ field_ids_ = reinterpret_cast<const FieldId*>(b + h->field_ids_off_);
+ method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
+ proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
+ class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
+}
+
+bool RawDexFile::IsMagicValid() {
+ return CheckMagic(header_->magic_);
+}
+
+bool RawDexFile::CheckMagic(const byte* magic) {
+ CHECK(magic != NULL);
+ if (memcmp(magic, kDexMagic, sizeof(kDexMagic)) != 0) {
+ LOG(WARNING) << "Unrecognized magic number:"
+ << " " << magic[0]
+ << " " << magic[1]
+ << " " << magic[2]
+ << " " << magic[3];
+ return false;
+ }
+ const byte* version = &magic[sizeof(kDexMagic)];
+ if (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) != 0) {
+ LOG(WARNING) << "Unrecognized version number:"
+ << " " << version[0]
+ << " " << version[1]
+ << " " << version[2]
+ << " " << version[3];
+ return false;
+ }
+ return true;
+}
+
+void RawDexFile::InitIndex() {
+ CHECK_EQ(index_.size(), 0U);
+ for (size_t i = 0; i < NumClassDefs(); ++i) {
+ const ClassDef& class_def = GetClassDef(i);
+ const char* descriptor = GetClassDescriptor(class_def);
+ index_[descriptor] = &class_def;
+ }
+}
+
+const RawDexFile::ClassDef* RawDexFile::FindClassDef(const StringPiece& descriptor) const {
+ CHECK(descriptor != NULL);
+ Index::const_iterator it = index_.find(descriptor);
+ if (it == index_.end()) {
+ return NULL;
+ } else {
+ return it->second;
+ }
+}
+
+// Read a signed integer. "zwidth" is the zero-based byte count.
+static int32_t ReadSignedInt(const byte* ptr, int zwidth)
+{
+ int32_t val = 0;
+ for (int i = zwidth; i >= 0; --i) {
+ val = ((uint32_t)val >> 8) | (((int32_t)*ptr++) << 24);
+ }
+ val >>= (3 - zwidth) * 8;
+ return val;
+}
+
+// Read an unsigned integer. "zwidth" is the zero-based byte count,
+// "fill_on_right" indicates which side we want to zero-fill from.
+static uint32_t ReadUnsignedInt(const byte* ptr, int zwidth,
+ bool fill_on_right) {
+ uint32_t val = 0;
+ if (!fill_on_right) {
+ for (int i = zwidth; i >= 0; --i) {
+ val = (val >> 8) | (((uint32_t)*ptr++) << 24);
+ }
+ val >>= (3 - zwidth) * 8;
+ } else {
+ for (int i = zwidth; i >= 0; --i) {
+ val = (val >> 8) | (((uint32_t)*ptr++) << 24);
+ }
+ }
+ return val;
+}
+
+// Read a signed long. "zwidth" is the zero-based byte count.
+static int64_t ReadSignedLong(const byte* ptr, int zwidth) {
+ int64_t val = 0;
+ for (int i = zwidth; i >= 0; --i) {
+ val = ((uint64_t)val >> 8) | (((int64_t)*ptr++) << 56);
+ }
+ val >>= (7 - zwidth) * 8;
+ return val;
+}
+
+// Read an unsigned long. "zwidth" is the zero-based byte count,
+// "fill_on_right" indicates which side we want to zero-fill from.
+static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth,
+ bool fill_on_right) {
+ uint64_t val = 0;
+ if (!fill_on_right) {
+ for (int i = zwidth; i >= 0; --i) {
+ val = (val >> 8) | (((uint64_t)*ptr++) << 56);
+ }
+ val >>= (7 - zwidth) * 8;
+ } else {
+ for (int i = zwidth; i >= 0; --i) {
+ val = (val >> 8) | (((uint64_t)*ptr++) << 56);
+ }
+ }
+ return val;
+}
+
+RawDexFile::ValueType RawDexFile::ReadEncodedValue(const byte** stream,
+ JValue* value) const {
+ const byte* ptr = *stream;
+ byte value_type = *ptr++;
+ byte value_arg = value_type >> kEncodedValueArgShift;
+ size_t width = value_arg + 1; // assume and correct later
+ int type = value_type & kEncodedValueTypeMask;
+ switch (type) {
+ case RawDexFile::kByte: {
+ int32_t b = ReadSignedInt(ptr, value_arg);
+ CHECK(IsInt(8, b));
+ value->i = b;
+ break;
+ }
+ case RawDexFile::kShort: {
+ int32_t s = ReadSignedInt(ptr, value_arg);
+ CHECK(IsInt(16, s));
+ value->i = s;
+ break;
+ }
+ case RawDexFile::kChar: {
+ uint32_t c = ReadUnsignedInt(ptr, value_arg, false);
+ CHECK(IsUint(16, c));
+ value->i = c;
+ break;
+ }
+ case RawDexFile::kInt:
+ value->i = ReadSignedInt(ptr, value_arg);
+ break;
+ case RawDexFile::kLong:
+ value->j = ReadSignedLong(ptr, value_arg);
+ break;
+ case RawDexFile::kFloat:
+ value->i = ReadUnsignedInt(ptr, value_arg, true);
+ break;
+ case RawDexFile::kDouble:
+ value->j = ReadUnsignedLong(ptr, value_arg, true);
+ break;
+ case RawDexFile::kBoolean:
+ value->i = (value_arg != 0);
+ width = 0;
+ break;
+ case RawDexFile::kString:
+ case RawDexFile::kType:
+ case RawDexFile::kMethod:
+ case RawDexFile::kEnum:
+ value->i = ReadUnsignedInt(ptr, value_arg, false);
+ break;
+ case RawDexFile::kField:
+ case RawDexFile::kArray:
+ case RawDexFile::kAnnotation:
+ LOG(FATAL) << "Unimplemented";
+ break;
+ case RawDexFile::kNull:
+ value->i = 0;
+ width = 0;
+ break;
+ default:
+ LOG(FATAL) << "Unreached";
+ }
+ ptr += width;
+ *stream = ptr;
+ return static_cast<ValueType>(type);
}
} // namespace art