Rename DexFile to DexCache
Change-Id: I93fa3e4f7cf87fbaac974f0d2577628a23f0d8c2
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 5dab0fd..7d5ef2b 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -34,6 +34,7 @@
src/assembler.cc \
src/calling_convention.cc \
src/class_linker.cc \
+ src/dex_cache.cc \
src/dex_file.cc \
src/dex_instruction.cc \
src/dex_verifier.cc \
@@ -47,7 +48,6 @@
src/object.cc \
src/object_bitmap.cc \
src/offsets.cc \
- src/raw_dex_file.cc \
src/runtime.cc \
src/space.cc \
src/stringpiece.cc \
@@ -77,11 +77,11 @@
TEST_COMMON_SRC_FILES := \
src/class_linker_test.cc \
+ src/dex_cache_test.cc \
src/dex_file_test.cc \
src/dex_instruction_visitor_test.cc \
src/jni_compiler_test.cc \
src/object_test.cc \
- src/raw_dex_file_test.cc \
src/space_test.cc
TEST_TARGET_SRC_FILES := \
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 20960d2..bacc9a3 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -7,13 +7,13 @@
#include <utility>
#include "casts.h"
-#include "dex_file.h"
+#include "dex_cache.h"
#include "dex_verifier.h"
#include "heap.h"
#include "logging.h"
#include "monitor.h"
#include "object.h"
-#include "raw_dex_file.h"
+#include "dex_file.h"
#include "scoped_ptr.h"
#include "thread.h"
#include "utils.h"
@@ -86,13 +86,13 @@
CHECK(object_array_class_ != NULL);
}
-DexFile* ClassLinker::AllocDexFile() {
- return down_cast<DexFile*>(Heap::AllocObjectArray(object_array_class_, DexFile::kMax));
+DexCache* ClassLinker::AllocDexCache() {
+ return down_cast<DexCache*>(Heap::AllocObjectArray(object_array_class_, DexCache::kMax));
}
-Class* ClassLinker::AllocClass(DexFile* dex_file) {
+Class* ClassLinker::AllocClass(DexCache* dex_cache) {
Class* klass = down_cast<Class*>(Heap::AllocObject(java_lang_Class_));
- klass->dex_file_ = dex_file;
+ klass->dex_cache_ = dex_cache;
return klass;
}
@@ -141,37 +141,37 @@
}
const RawDexFile* raw_dex_file = pair.first;
const RawDexFile::ClassDef* class_def = pair.second;
- DexFile* dex_file = FindDexFile(raw_dex_file);
+ DexCache* dex_cache = FindDexCache(raw_dex_file);
// Load the class from the dex file.
if (descriptor == "Ljava/lang/Object;") {
klass = java_lang_Object_;
- klass->dex_file_ = dex_file;
+ klass->dex_cache_ = dex_cache;
klass->object_size_ = sizeof(Object);
char_array_class_->super_class_idx_ = class_def->class_idx_;
} else if (descriptor == "Ljava/lang/Class;") {
klass = java_lang_Class_;
- klass->dex_file_ = dex_file;
+ klass->dex_cache_ = dex_cache;
klass->object_size_ = sizeof(Class);
} else if (descriptor == "Ljava/lang/ref/Field;") {
klass = java_lang_ref_Field_;
- klass->dex_file_ = dex_file;
+ klass->dex_cache_ = dex_cache;
klass->object_size_ = sizeof(Field);
} else if (descriptor == "Ljava/lang/ref/Method;") {
klass = java_lang_ref_Method_;
- klass->dex_file_ = dex_file;
+ klass->dex_cache_ = dex_cache;
klass->object_size_ = sizeof(Method);
} else if (descriptor == "Ljava/lang/Cloneable;") {
klass = java_lang_Cloneable_;
- klass->dex_file_ = dex_file;
+ klass->dex_cache_ = dex_cache;
} else if (descriptor == "Ljava/io/Serializable;") {
klass = java_io_Serializable_;
- klass->dex_file_ = dex_file;
+ klass->dex_cache_ = dex_cache;
} else if (descriptor == "Ljava/lang/String;") {
klass = java_lang_String_;
- klass->dex_file_ = dex_file;
+ klass->dex_cache_ = dex_cache;
klass->object_size_ = sizeof(String);
} else {
- klass = AllocClass(dex_file);
+ klass = AllocClass(dex_cache);
}
LoadClass(*raw_dex_file, *class_def, klass);
// Check for a pending exception during load
@@ -227,7 +227,7 @@
const RawDexFile::ClassDef& class_def,
Class* klass) {
CHECK(klass != NULL);
- CHECK(klass->dex_file_ != NULL);
+ CHECK(klass->dex_cache_ != NULL);
const byte* class_data = raw_dex_file.GetClassData(class_def);
RawDexFile::ClassDataHeader header = raw_dex_file.ReadClassDataHeader(&class_data);
@@ -387,19 +387,19 @@
void ClassLinker::RegisterDexFile(RawDexFile* raw_dex_file) {
raw_dex_files_.push_back(raw_dex_file);
- DexFile* dex_file = AllocDexFile();
- CHECK(dex_file != NULL);
- dex_file->Init(AllocObjectArray(raw_dex_file->NumStringIds()),
- AllocObjectArray(raw_dex_file->NumTypeIds()),
- AllocObjectArray(raw_dex_file->NumMethodIds()),
- AllocObjectArray(raw_dex_file->NumFieldIds()));
- dex_files_.push_back(dex_file);
+ DexCache* dex_cache = AllocDexCache();
+ CHECK(dex_cache != NULL);
+ dex_cache->Init(AllocObjectArray(raw_dex_file->NumStringIds()),
+ AllocObjectArray(raw_dex_file->NumTypeIds()),
+ AllocObjectArray(raw_dex_file->NumMethodIds()),
+ AllocObjectArray(raw_dex_file->NumFieldIds()));
+ dex_caches_.push_back(dex_cache);
}
-const RawDexFile* ClassLinker::FindRawDexFile(const DexFile* dex_file) const {
- CHECK(dex_file != NULL);
- for (size_t i = 0; i != dex_files_.size(); ++i) {
- if (dex_files_[i] == dex_file) {
+const RawDexFile* ClassLinker::FindRawDexFile(const DexCache* dex_cache) const {
+ CHECK(dex_cache != NULL);
+ for (size_t i = 0; i != dex_caches_.size(); ++i) {
+ if (dex_caches_[i] == dex_cache) {
return raw_dex_files_[i];
}
}
@@ -407,14 +407,14 @@
return NULL;
}
-DexFile* ClassLinker::FindDexFile(const RawDexFile* raw_dex_file) const {
+DexCache* ClassLinker::FindDexCache(const RawDexFile* raw_dex_file) const {
CHECK(raw_dex_file != NULL);
for (size_t i = 0; i != raw_dex_files_.size(); ++i) {
if (raw_dex_files_[i] == raw_dex_file) {
- return dex_files_[i];
+ return dex_caches_[i];
}
}
- CHECK(false) << "Could not find DexFile";
+ CHECK(false) << "Could not find DexCache";
return NULL;
}
@@ -799,7 +799,7 @@
bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method,
const Class* klass1,
const Class* klass2) {
- const RawDexFile* raw = FindRawDexFile(method->GetClass()->GetDexFile());
+ const RawDexFile* raw = FindRawDexFile(method->GetClass()->GetDexCache());
const RawDexFile::ProtoId& proto_id = raw->GetProtoId(method->proto_idx_);
RawDexFile::ParameterIterator *it;
for (it = raw->GetParameterIterator(proto_id); it->HasNext(); it->Next()) {
@@ -851,8 +851,8 @@
}
bool ClassLinker::HasSameArgumentTypes(const Method* m1, const Method* m2) const {
- const RawDexFile* raw1 = FindRawDexFile(m1->GetClass()->GetDexFile());
- const RawDexFile* raw2 = FindRawDexFile(m2->GetClass()->GetDexFile());
+ const RawDexFile* raw1 = FindRawDexFile(m1->GetClass()->GetDexCache());
+ const RawDexFile* raw2 = FindRawDexFile(m2->GetClass()->GetDexCache());
const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(m1->proto_idx_);
const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(m2->proto_idx_);
@@ -879,8 +879,8 @@
}
bool ClassLinker::HasSameReturnType(const Method* m1, const Method* m2) const {
- const RawDexFile* raw1 = FindRawDexFile(m1->GetClass()->GetDexFile());
- const RawDexFile* raw2 = FindRawDexFile(m2->GetClass()->GetDexFile());
+ const RawDexFile* raw1 = FindRawDexFile(m1->GetClass()->GetDexCache());
+ const RawDexFile* raw2 = FindRawDexFile(m2->GetClass()->GetDexCache());
const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(m1->proto_idx_);
const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(m2->proto_idx_);
const char* type1 = raw1->dexStringByTypeIdx(proto1.return_type_idx_);
@@ -914,7 +914,7 @@
if (num_static_fields == 0) {
return;
}
- DexFile* dex_file = klass->GetDexFile();
+ DexCache* dex_file = klass->GetDexCache();
if (dex_file == NULL) {
return;
}
@@ -1454,8 +1454,8 @@
Class* ClassLinker::ResolveClass(const Class* referrer,
uint32_t class_idx,
const RawDexFile* raw_dex_file) {
- DexFile* dex_file = referrer->GetDexFile();
- Class* resolved = dex_file->GetResolvedClass(class_idx);
+ DexCache* dex_cache = referrer->GetDexCache();
+ Class* resolved = dex_cache->GetResolvedClass(class_idx);
if (resolved != NULL) {
return resolved;
}
@@ -1467,13 +1467,13 @@
}
if (resolved != NULL) {
Class* check = resolved->IsArray() ? resolved->component_type_ : resolved;
- if (referrer->GetDexFile() != check->GetDexFile()) {
+ if (referrer->GetDexCache() != check->GetDexCache()) {
if (check->GetClassLoader() != NULL) {
LG << "Class resolved by unexpected DEX"; // TODO: IllegalAccessError
return NULL;
}
}
- dex_file->SetResolvedClass(class_idx, resolved);
+ dex_cache->SetResolvedClass(class_idx, resolved);
} else {
DCHECK(Thread::Current()->IsExceptionPending());
}
@@ -1488,14 +1488,14 @@
String* ClassLinker::ResolveString(const Class* referring,
uint32_t string_idx) {
- const RawDexFile* raw = FindRawDexFile(referring->GetDexFile());
+ const RawDexFile* raw = FindRawDexFile(referring->GetDexCache());
const RawDexFile::StringId& string_id = raw->GetStringId(string_idx);
const char* string_data = raw->GetStringData(string_id);
String* new_string = Heap::AllocStringFromModifiedUtf8(java_lang_String_,
char_array_class_,
string_data);
// TODO: intern the new string
- referring->GetDexFile()->SetResolvedString(string_idx, new_string);
+ referring->GetDexCache()->SetResolvedString(string_idx, new_string);
return new_string;
}
diff --git a/src/class_linker.h b/src/class_linker.h
index d7bb191..9d6c53e 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -8,7 +8,7 @@
#include <vector>
#include "macros.h"
-#include "raw_dex_file.h"
+#include "dex_file.h"
#include "thread.h"
#include "object.h"
#include "gtest/gtest.h"
@@ -22,8 +22,8 @@
~ClassLinker() {}
- DexFile* AllocDexFile();
- Class* AllocClass(DexFile* dex_file);
+ DexCache* AllocDexCache();
+ Class* AllocClass(DexCache* dex_cache);
StaticField* AllocStaticField();
InstanceField* AllocInstanceField();
Method* AllocMethod();
@@ -64,9 +64,9 @@
Class* FindPrimitiveClass(char type);
- const RawDexFile* FindRawDexFile(const DexFile* dex_file) const;
+ const RawDexFile* FindRawDexFile(const DexCache* dex_file) const;
- DexFile* FindDexFile(const RawDexFile* raw_dex_file) const;
+ DexCache* FindDexCache(const RawDexFile* raw_dex_file) const;
typedef std::pair<const RawDexFile*, const RawDexFile::ClassDef*> ClassPathEntry;
@@ -148,7 +148,7 @@
std::vector<RawDexFile*> raw_dex_files_;
- std::vector<DexFile*> dex_files_;
+ std::vector<DexCache*> dex_caches_;
// TODO: multimap
typedef std::map<const StringPiece, Class*> Table;
diff --git a/src/dex_cache.cc b/src/dex_cache.cc
new file mode 100644
index 0000000..f2a4768
--- /dev/null
+++ b/src/dex_cache.cc
@@ -0,0 +1,21 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "dex_cache.h"
+#include "heap.h"
+#include "globals.h"
+#include "logging.h"
+#include "object.h"
+
+namespace art {
+
+void DexCache::Init(ObjectArray* strings,
+ ObjectArray* classes,
+ ObjectArray* methods,
+ ObjectArray* fields) {
+ Set(kStrings, strings);
+ Set(kClasses, classes);
+ Set(kMethods, methods);
+ Set(kFields, fields);
+}
+
+} // namespace art
diff --git a/src/dex_cache.h b/src/dex_cache.h
new file mode 100644
index 0000000..2892e29
--- /dev/null
+++ b/src/dex_cache.h
@@ -0,0 +1,100 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_DEX_CACHE_H_
+#define ART_SRC_DEX_CACHE_H_
+
+#include "globals.h"
+#include "macros.h"
+#include "object.h"
+
+namespace art {
+
+class Class;
+class Field;
+class Method;
+class String;
+union JValue;
+
+class DexCache : public ObjectArray {
+ public:
+
+ enum ArrayIndexes {
+ kStrings = 0,
+ kClasses = 1,
+ kMethods = 2,
+ kFields = 3,
+ kMax = 4,
+ };
+
+ void Init(ObjectArray* strings,
+ ObjectArray* classes,
+ ObjectArray* methods,
+ ObjectArray* fields);
+
+ size_t NumStrings() const {
+ return GetStrings()->GetLength();
+ }
+
+ size_t NumClasses() const {
+ return GetClasses()->GetLength();
+ }
+
+ size_t NumMethods() const {
+ return GetMethods()->GetLength();
+ }
+
+ size_t NumFields() const {
+ return GetFields()->GetLength();
+ }
+
+ String* GetResolvedString(uint32_t string_idx) const {
+ return down_cast<String*>(GetStrings()->Get(string_idx));
+ }
+
+ void SetResolvedString(uint32_t string_idx, String* resolved) {
+ GetStrings()->Set(string_idx, resolved);
+ }
+
+ Class* GetResolvedClass(uint32_t class_idx) const {
+ return down_cast<Class*>(GetClasses()->Get(class_idx));
+ }
+
+ void SetResolvedClass(uint32_t class_idx, Class* resolved) {
+ GetClasses()->Set(class_idx, resolved);
+ }
+
+ Method* GetResolvedMethod(uint32_t method_idx) const {
+ return down_cast<Method*>(GetMethods()->Get(method_idx));
+ }
+
+ void SetResolvedMethod(uint32_t method_idx, Method* resolved) {
+ GetMethods()->Set(method_idx, resolved);
+ }
+
+ Field* GetResolvedField(uint32_t field_idx) const {
+ return down_cast<Field*>(GetFields()->Get(field_idx));
+ }
+
+ void SetResolvedfield(uint32_t field_idx, Field* resolved) {
+ GetFields()->Set(field_idx, resolved);
+ }
+
+ private:
+ ObjectArray* GetStrings() const {
+ return down_cast<ObjectArray*>(Get(kStrings));
+ }
+ ObjectArray* GetClasses() const {
+ return down_cast<ObjectArray*>(Get(kClasses));
+ }
+ ObjectArray* GetMethods() const {
+ return down_cast<ObjectArray*>(Get(kMethods));
+ }
+ ObjectArray* GetFields() const {
+ return down_cast<ObjectArray*>(Get(kFields));
+ }
+ DexCache();
+};
+
+} // namespace art
+
+#endif // ART_SRC_DEX_CACHE_H_
diff --git a/src/dex_cache_test.cc b/src/dex_cache_test.cc
new file mode 100644
index 0000000..7cfb634
--- /dev/null
+++ b/src/dex_cache_test.cc
@@ -0,0 +1,31 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "class_linker.h"
+#include "common_test.h"
+#include "dex_cache.h"
+#include "heap.h"
+#include "object.h"
+#include "scoped_ptr.h"
+
+#include <stdio.h>
+#include "gtest/gtest.h"
+
+namespace art {
+
+class DexCacheTest : public RuntimeTest {};
+
+TEST_F(DexCacheTest, Open) {
+
+ DexCache* dex_cache = down_cast<DexCache*>(class_linker_->AllocObjectArray(DexCache::kMax));
+ ASSERT_TRUE(dex_cache != NULL);
+ dex_cache->Init(class_linker_->AllocObjectArray(1),
+ class_linker_->AllocObjectArray(2),
+ class_linker_->AllocObjectArray(3),
+ class_linker_->AllocObjectArray(4));
+ EXPECT_EQ(1U, dex_cache->NumStrings());
+ EXPECT_EQ(2U, dex_cache->NumClasses());
+ EXPECT_EQ(3U, dex_cache->NumMethods());
+ EXPECT_EQ(4U, dex_cache->NumFields());
+}
+
+} // namespace art
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
diff --git a/src/dex_file.h b/src/dex_file.h
index 6339317..e677b42 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -3,93 +3,521 @@
#ifndef ART_SRC_DEX_FILE_H_
#define ART_SRC_DEX_FILE_H_
+#include <map>
+
#include "globals.h"
-#include "macros.h"
-#include "object.h"
+#include "leb128.h"
+#include "logging.h"
+#include "scoped_ptr.h"
+#include "stringpiece.h"
+#include "strutil.h"
namespace art {
-class Class;
-class Field;
-class Method;
-class String;
union JValue;
-class DexFile : public ObjectArray {
+// TODO: move all of the macro functionality into the DexCache class.
+class RawDexFile {
public:
+ static const byte kDexMagic[];
+ static const byte kDexMagicVersion[];
+ static const size_t kSha1DigestSize = 20;
- enum ArrayIndexes {
- kStrings = 0,
- kClasses = 1,
- kMethods = 2,
- kFields = 3,
- kMax = 4,
+ static const byte kEncodedValueTypeMask = 0x1f; // 0b11111
+ static const byte kEncodedValueArgShift = 5;
+
+ // The value of an invalid index.
+ static const uint32_t kDexNoIndex = 0xFFFFFFFF;
+
+ enum ValueType {
+ kByte = 0x00,
+ kShort = 0x02,
+ kChar = 0x03,
+ kInt = 0x04,
+ kLong = 0x06,
+ kFloat = 0x10,
+ kDouble = 0x11,
+ kString = 0x17,
+ kType = 0x18,
+ kField = 0x19,
+ kMethod = 0x1a,
+ kEnum = 0x1b,
+ kArray = 0x1c,
+ kAnnotation = 0x1d,
+ kNull = 0x1e,
+ kBoolean = 0x1f
};
- void Init(ObjectArray* strings, ObjectArray* classes, ObjectArray* methods, ObjectArray* fields);
+ // Raw header_item.
+ struct Header {
+ uint8_t magic_[8];
+ uint32_t checksum_;
+ uint8_t signature_[kSha1DigestSize];
+ uint32_t file_size_; // length of entire file
+ uint32_t header_size_; // offset to start of next section
+ uint32_t endian_tag_;
+ uint32_t link_size_;
+ uint32_t link_off_;
+ uint32_t map_off_;
+ uint32_t string_ids_size_;
+ uint32_t string_ids_off_;
+ uint32_t type_ids_size_;
+ uint32_t type_ids_off_;
+ uint32_t proto_ids_size_;
+ uint32_t proto_ids_off_;
+ uint32_t field_ids_size_;
+ uint32_t field_ids_off_;
+ uint32_t method_ids_size_;
+ uint32_t method_ids_off_;
+ uint32_t class_defs_size_;
+ uint32_t class_defs_off_;
+ uint32_t data_size_;
+ uint32_t data_off_;
+ };
- size_t NumStrings() const {
- return GetStrings()->GetLength();
+ // Raw string_id_item.
+ struct StringId {
+ uint32_t string_data_off_; // offset in bytes from the base address
+ };
+
+ // Raw type_id_item.
+ struct TypeId {
+ uint32_t descriptor_idx_; // index into string_ids
+ };
+
+ // Raw field_id_item.
+ struct FieldId {
+ uint16_t class_idx_; // index into typeIds list for defining class
+ uint16_t type_idx_; // index into typeIds for field type
+ uint32_t name_idx_; // index into stringIds for field name
+ };
+
+ // Raw method_id_item.
+ struct MethodId {
+ uint16_t class_idx_; // index into typeIds list for defining class
+ uint16_t proto_idx_; // index into protoIds for method prototype
+ uint32_t name_idx_; // index into stringIds for method name
+ };
+
+ // Raw proto_id_item.
+ struct ProtoId {
+ uint32_t shorty_idx_; // index into string_ids for shorty descriptor
+ uint32_t return_type_idx_; // index into type_ids list for return type
+ uint32_t parameters_off_; // file offset to type_list for parameter types
+ };
+
+ // Raw class_def_item.
+ struct ClassDef {
+ uint32_t class_idx_; // index into typeIds for this class
+ uint32_t access_flags_;
+ uint32_t superclass_idx_; // index into typeIds for superclass
+ uint32_t interfaces_off_; // file offset to TypeList
+ uint32_t source_file_idx_; // index into stringIds for source file name
+ uint32_t annotations_off_; // file offset to annotations_directory_item
+ uint32_t class_data_off_; // file offset to class_data_item
+ uint32_t static_values_off_; // file offset to EncodedArray
+ };
+
+ // Raw type_item.
+ struct TypeItem {
+ uint16_t type_idx_; // index into type_ids section
+ };
+
+ // Raw type_list.
+ class TypeList {
+ public:
+ uint32_t Size() const {
+ return size_;
+ }
+
+ const TypeItem& GetTypeItem(uint32_t idx) const {
+ CHECK_LT(idx, this->size_);
+ return this->list_[idx];
+ }
+
+ private:
+ uint32_t size_; // size of the list, in entries
+ TypeItem list_[1]; // elements of the list
+ };
+
+ class ParameterIterator { // TODO: stream
+ public:
+ ParameterIterator(const RawDexFile& raw, const ProtoId& proto_id)
+ : raw_(raw), size_(0), pos_(0) {
+ type_list_ = raw_.GetProtoParameters(proto_id);
+ if (type_list_ != NULL) {
+ size_ = type_list_->Size();
+ }
+ }
+ bool HasNext() const { return pos_ != size_; }
+ void Next() { ++pos_; }
+ const char* GetDescriptor() {
+ uint32_t type_idx = type_list_->GetTypeItem(pos_).type_idx_;
+ return raw_.dexStringByTypeIdx(type_idx);
+ }
+ private:
+ const RawDexFile& raw_;
+ const TypeList* type_list_;
+ uint32_t size_;
+ uint32_t pos_;
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterIterator);
+ };
+
+ ParameterIterator* GetParameterIterator(const ProtoId& proto_id) const {
+ return new ParameterIterator(*this, proto_id);
}
- size_t NumClasses() const {
- return GetClasses()->GetLength();
+ const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
+ return dexStringByTypeIdx(proto_id.return_type_idx_);
}
- size_t NumMethods() const {
- return GetMethods()->GetLength();
+ // Raw code_item.
+ struct CodeItem {
+ uint16_t registers_size_;
+ uint16_t ins_size_;
+ uint16_t outs_size_;
+ uint16_t tries_size_;
+ uint32_t debug_info_off_; // file offset to debug info stream
+ uint32_t insns_size_; // size of the insns array, in 2 byte code units
+ uint16_t insns_[1];
+ };
+
+ // Partially decoded form of class_data_item.
+ struct ClassDataHeader {
+ uint32_t static_fields_size_; // the number of static fields
+ uint32_t instance_fields_size_; // the number of instance fields
+ uint32_t direct_methods_size_; // the number of direct methods
+ uint32_t virtual_methods_size_; // the number of virtual methods
+ };
+
+ // Decoded form of encoded_field.
+ struct Field {
+ uint32_t field_idx_; // index into the field_ids list for the identity of this field
+ uint32_t access_flags_; // access flags for the field
+ };
+
+ // Decoded form of encoded_method.
+ struct Method {
+ uint32_t method_idx_;
+ uint32_t access_flags_;
+ uint32_t code_off_;
+ };
+
+ // Opens a .dex file from the file system.
+ static RawDexFile* OpenFile(const char* filename);
+
+ // Opens a .dex file from a new allocated pointer
+ static RawDexFile* OpenPtr(byte* ptr, size_t length);
+
+ // Closes a .dex file.
+ virtual ~RawDexFile();
+
+ const Header& GetHeader() {
+ CHECK(header_ != NULL);
+ return *header_;
}
- size_t NumFields() const {
- return GetFields()->GetLength();
+ // Looks up a class definition by its class descriptor.
+ const ClassDef* FindClassDef(const StringPiece& descriptor) const;
+
+ // Returns the number of string identifiers in the .dex file.
+ size_t NumStringIds() const {
+ CHECK(header_ != NULL);
+ return header_->string_ids_size_;
}
- String* GetResolvedString(uint32_t string_idx) const {
- return down_cast<String*>(GetStrings()->Get(string_idx));
+ // Returns the number of type identifiers in the .dex file.
+ size_t NumTypeIds() const {
+ CHECK(header_ != NULL);
+ return header_->type_ids_size_;
}
- void SetResolvedString(uint32_t string_idx, String* resolved) {
- GetStrings()->Set(string_idx, resolved);
+ // Returns the number of prototype identifiers in the .dex file.
+ size_t NumProtoIds() const {
+ CHECK(header_ != NULL);
+ return header_->proto_ids_size_;
}
- Class* GetResolvedClass(uint32_t class_idx) const {
- return down_cast<Class*>(GetClasses()->Get(class_idx));
+ // Returns the number of field identifiers in the .dex file.
+ size_t NumFieldIds() const {
+ CHECK(header_ != NULL);
+ return header_->field_ids_size_;
}
- void SetResolvedClass(uint32_t class_idx, Class* resolved) {
- GetClasses()->Set(class_idx, resolved);
+ // Returns the number of method identifiers in the .dex file.
+ size_t NumMethodIds() const {
+ CHECK(header_ != NULL);
+ return header_->method_ids_size_;
}
- Method* GetResolvedMethod(uint32_t method_idx) const {
- return down_cast<Method*>(GetMethods()->Get(method_idx));
+ // Returns the number of class definitions in the .dex file.
+ size_t NumClassDefs() const {
+ CHECK(header_ != NULL);
+ return header_->class_defs_size_;
}
- void SetResolvedMethod(uint32_t method_idx, Method* resolved) {
- GetMethods()->Set(method_idx, resolved);
+ // Returns a pointer to the memory mapped class data.
+ // TODO: return a stream
+ const byte* GetClassData(const ClassDef& class_def) const {
+ if (class_def.class_data_off_ == 0) {
+ return NULL;
+ } else {
+ return base_ + class_def.class_data_off_;
+ }
}
- Field* GetResolvedField(uint32_t field_idx) const {
- return down_cast<Field*>(GetFields()->Get(field_idx));
+ // Decodes the header section from the raw class data bytes.
+ ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
+ CHECK(class_data != NULL);
+ ClassDataHeader header;
+ memset(&header, 0, sizeof(ClassDataHeader));
+ if (*class_data != NULL) {
+ header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
+ header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
+ header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
+ header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
+ }
+ return header;
}
- void SetResolvedfield(uint32_t field_idx, Field* resolved) {
- GetFields()->Set(field_idx, resolved);
+ // Returns the class descriptor string of a class definition.
+ const char* GetClassDescriptor(const ClassDef& class_def) const {
+ return dexStringByTypeIdx(class_def.class_idx_);
+ }
+
+ // Returns the StringId at the specified index.
+ const StringId& GetStringId(uint32_t idx) const {
+ CHECK_LT(idx, NumStringIds());
+ return string_ids_[idx];
+ }
+
+ // Returns the TypeId at the specified index.
+ const TypeId& GetTypeId(uint32_t idx) const {
+ CHECK_LT(idx, NumTypeIds());
+ return type_ids_[idx];
+ }
+
+ // Returns the FieldId at the specified index.
+ const FieldId& GetFieldId(uint32_t idx) const {
+ CHECK_LT(idx, NumFieldIds());
+ return field_ids_[idx];
+ }
+
+ // Returns the MethodId at the specified index.
+ const MethodId& GetMethodId(uint32_t idx) const {
+ CHECK_LT(idx, NumMethodIds());
+ return method_ids_[idx];
+ }
+
+ // Returns the ProtoId at the specified index.
+ const ProtoId& GetProtoId(uint32_t idx) const {
+ CHECK_LT(idx, NumProtoIds());
+ return proto_ids_[idx];
+ }
+
+ // Returns the ClassDef at the specified index.
+ const ClassDef& GetClassDef(uint32_t idx) const {
+ CHECK_LT(idx, NumClassDefs());
+ return class_defs_[idx];
+ }
+
+ const TypeList* GetInterfacesList(const ClassDef& class_def) const {
+ if (class_def.interfaces_off_ == 0) {
+ return NULL;
+ } else {
+ const byte* addr = base_ + class_def.interfaces_off_;
+ return reinterpret_cast<const TypeList*>(addr);
+ }
+ }
+
+ const CodeItem* GetCodeItem(const Method& method) const {
+ if (method.code_off_ == 0) {
+ return NULL; // native or abstract method
+ } else {
+ const byte* addr = base_ + method.code_off_;
+ return reinterpret_cast<const CodeItem*>(addr);
+ }
+ }
+
+ // Returns the short form method descriptor for the given prototype.
+ const char* GetShorty(uint32_t proto_idx) const {
+ const ProtoId& proto_id = GetProtoId(proto_idx);
+ return dexStringById(proto_id.shorty_idx_);
+ }
+
+ const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
+ if (proto_id.parameters_off_ == 0) {
+ return NULL;
+ } else {
+ const byte* addr = base_ + proto_id.parameters_off_;
+ return reinterpret_cast<const TypeList*>(addr);
+ }
+ }
+
+ const byte* GetEncodedArray(const ClassDef& class_def) const {
+ if (class_def.static_values_off_ == 0) {
+ return 0;
+ } else {
+ return base_ + class_def.static_values_off_;
+ }
+ }
+
+ int32_t GetStringLength(const StringId& string_id) const {
+ const byte* ptr = base_ + string_id.string_data_off_;
+ return DecodeUnsignedLeb128(&ptr);
+ }
+
+ ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const;
+
+ // From libdex...
+
+ // Returns a pointer to the UTF-8 string data referred to by the
+ // given string_id.
+ const char* GetStringData(const StringId& string_id) const {
+ const byte* ptr = base_ + string_id.string_data_off_;
+ // Skip the uleb128 length.
+ while (*(ptr++) > 0x7f) /* empty */ ;
+ return (const char*) ptr;
+ }
+
+ // return the UTF-8 encoded string with the specified string_id index
+ const char* dexStringById(uint32_t idx) const {
+ const StringId& string_id = GetStringId(idx);
+ return GetStringData(string_id);
+ }
+
+ // Get the descriptor string associated with a given type index.
+ const char* dexStringByTypeIdx(uint32_t idx) const {
+ const TypeId& type_id = GetTypeId(idx);
+ return dexStringById(type_id.descriptor_idx_);
+ }
+
+ // TODO: encoded_field is actually a stream of bytes
+ void dexReadClassDataField(const byte** encoded_field,
+ RawDexFile::Field* field,
+ uint32_t* last_idx) const {
+ uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
+ field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
+ field->field_idx_ = idx;
+ *last_idx = idx;
+ }
+
+ // TODO: encoded_method is actually a stream of bytes
+ void dexReadClassDataMethod(const byte** encoded_method,
+ RawDexFile::Method* method,
+ uint32_t* last_idx) const {
+ uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
+ method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
+ method->code_off_ = DecodeUnsignedLeb128(encoded_method);
+ method->method_idx_ = idx;
+ *last_idx = idx;
+ }
+
+
+ // TODO: const reference
+ uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
+ CHECK_GE(class_def, class_defs_);
+ CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
+ return class_def - class_defs_;
+ }
+
+ const char* dexGetSourceFile(const ClassDef& class_def) const {
+ if (class_def.source_file_idx_ == 0xffffffff) {
+ return NULL;
+ } else {
+ return dexStringById(class_def.source_file_idx_);
+ }
}
private:
- ObjectArray* GetStrings() const {
- return down_cast<ObjectArray*>(Get(kStrings));
- }
- ObjectArray* GetClasses() const {
- return down_cast<ObjectArray*>(Get(kClasses));
- }
- ObjectArray* GetMethods() const {
- return down_cast<ObjectArray*>(Get(kMethods));
- }
- ObjectArray* GetFields() const {
- return down_cast<ObjectArray*>(Get(kFields));
- }
- DexFile();
+ // Helper class to deallocate underlying storage.
+ class Closer {
+ public:
+ virtual ~Closer();
+ };
+
+ // Helper class to deallocate mmap-backed .dex files.
+ class MmapCloser : public Closer {
+ public:
+ MmapCloser(void* addr, size_t length);
+ virtual ~MmapCloser();
+ private:
+ void* addr_;
+ size_t length_;
+ };
+
+ // Helper class for deallocating new/delete-backed .dex files.
+ class PtrCloser : public Closer {
+ public:
+ PtrCloser(byte* addr);
+ virtual ~PtrCloser();
+ private:
+ byte* addr_;
+ };
+
+ // Opens a .dex file at a the given address.
+ static RawDexFile* Open(const byte* dex_file, size_t length, Closer* closer);
+
+ RawDexFile(const byte* addr, size_t length, Closer* closer)
+ : base_(addr),
+ length_(length),
+ closer_(closer),
+ header_(0),
+ string_ids_(0),
+ type_ids_(0),
+ field_ids_(0),
+ method_ids_(0),
+ proto_ids_(0),
+ class_defs_(0) {}
+
+ // Top-level initializer that calls other Init methods.
+ bool Init();
+
+ // Caches pointers into to the various file sections.
+ void InitMembers();
+
+ // Builds the index of descriptors to class definitions.
+ void InitIndex();
+
+ // Returns true if the byte string equals the magic value.
+ bool CheckMagic(const byte* magic);
+
+ // Returns true if the header magic is of the expected value.
+ bool IsMagicValid();
+
+ // The index of descriptors to class definitions.
+ typedef std::map<const StringPiece, const RawDexFile::ClassDef*> Index;
+ Index index_;
+
+ // The base address of the memory mapping.
+ const byte* base_;
+
+ // The size of the underlying memory allocation in bytes.
+ size_t length_;
+
+ // Helper object to free the underlying allocation.
+ scoped_ptr<Closer> closer_;
+
+ // Points to the header section.
+ const Header* header_;
+
+ // Points to the base of the string identifier list.
+ const StringId* string_ids_;
+
+ // Points to the base of the type identifier list.
+ const TypeId* type_ids_;
+
+ // Points to the base of the field identifier list.
+ const FieldId* field_ids_;
+
+ // Points to the base of the method identifier list.
+ const MethodId* method_ids_;
+
+ // Points to the base of the prototype identifier list.
+ const ProtoId* proto_ids_;
+
+ // Points to the base of the class definition list.
+ const ClassDef* class_defs_;
};
} // namespace art
diff --git a/src/dex_file_test.cc b/src/dex_file_test.cc
index 0ad0b3b..b6a7e77 100644
--- a/src/dex_file_test.cc
+++ b/src/dex_file_test.cc
@@ -1,10 +1,7 @@
// Copyright 2011 Google Inc. All Rights Reserved.
-#include "class_linker.h"
#include "common_test.h"
#include "dex_file.h"
-#include "heap.h"
-#include "object.h"
#include "scoped_ptr.h"
#include <stdio.h>
@@ -12,20 +9,49 @@
namespace art {
-class DexFileTest : public RuntimeTest {};
+TEST(RawDexFileTest, Open) {
+ scoped_ptr<RawDexFile> raw(OpenRawDexFileBase64(kNestedDex));
+ ASSERT_TRUE(raw != NULL);
+}
-TEST_F(DexFileTest, Open) {
+TEST(RawDexFileTest, Header) {
+ scoped_ptr<RawDexFile> raw(OpenRawDexFileBase64(kNestedDex));
+ ASSERT_TRUE(raw != NULL);
- DexFile* dex_file = down_cast<DexFile*>(class_linker_->AllocObjectArray(DexFile::kMax));
- ASSERT_TRUE(dex_file != NULL);
- dex_file->Init(class_linker_->AllocObjectArray(1),
- class_linker_->AllocObjectArray(2),
- class_linker_->AllocObjectArray(3),
- class_linker_->AllocObjectArray(4));
- EXPECT_EQ(1U, dex_file->NumStrings());
- EXPECT_EQ(2U, dex_file->NumClasses());
- EXPECT_EQ(3U, dex_file->NumMethods());
- EXPECT_EQ(4U, dex_file->NumFields());
+ const RawDexFile::Header& header = raw->GetHeader();
+ // TODO: header.magic_
+ EXPECT_EQ(0x00d87910U, header.checksum_);
+ // TODO: header.signature_
+ EXPECT_EQ(904U, header.file_size_);
+ EXPECT_EQ(112U, header.header_size_);
+ EXPECT_EQ(0U, header.link_size_);
+ EXPECT_EQ(0U, header.link_off_);
+ EXPECT_EQ(15U, header.string_ids_size_);
+ EXPECT_EQ(112U, header.string_ids_off_);
+ EXPECT_EQ(7U, header.type_ids_size_);
+ EXPECT_EQ(172U, header.type_ids_off_);
+ EXPECT_EQ(2U, header.proto_ids_size_);
+ EXPECT_EQ(200U, header.proto_ids_off_);
+ EXPECT_EQ(1U, header.field_ids_size_);
+ EXPECT_EQ(224U, header.field_ids_off_);
+ EXPECT_EQ(3U, header.method_ids_size_);
+ EXPECT_EQ(232U, header.method_ids_off_);
+ EXPECT_EQ(2U, header.class_defs_size_);
+ EXPECT_EQ(256U, header.class_defs_off_);
+ EXPECT_EQ(584U, header.data_size_);
+ EXPECT_EQ(320U, header.data_off_);
+}
+
+TEST(RawDexFileTest, ClassDefs) {
+ scoped_ptr<RawDexFile> raw(OpenRawDexFileBase64(kNestedDex));
+ ASSERT_TRUE(raw != NULL);
+ EXPECT_EQ(2U, raw->NumClassDefs());
+
+ const RawDexFile::ClassDef& c0 = raw->GetClassDef(0);
+ EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c0));
+
+ const RawDexFile::ClassDef& c1 = raw->GetClassDef(1);
+ EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1));
}
} // namespace art
diff --git a/src/object.cc b/src/object.cc
index fb80fb9..6d18beb 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -7,8 +7,8 @@
#include "globals.h"
#include "logging.h"
+#include "dex_cache.h"
#include "dex_file.h"
-#include "raw_dex_file.h"
namespace art {
diff --git a/src/object.h b/src/object.h
index abbf6ca..770e8bb 100644
--- a/src/object.h
+++ b/src/object.h
@@ -16,7 +16,7 @@
class Array;
class Class;
-class DexFile;
+class DexCache;
class InstanceField;
class InterfaceEntry;
class Monitor;
@@ -385,7 +385,7 @@
}
// const char* GetReturnTypeDescriptor() const {
- // return declaring_class_->GetDexFile_->GetRaw()
+ // return FindDexFile(declaring_class_->GetDexCache()
// ->dexStringByTypeIdx(proto_id_.return_type_id_);
// }
@@ -596,8 +596,8 @@
return class_loader_;
}
- DexFile* GetDexFile() const {
- return dex_file_;
+ DexCache* GetDexCache() const {
+ return dex_cache_;
}
Class* GetComponentType() const {
@@ -779,9 +779,9 @@
// access flags; low 16 bits are defined by VM spec
uint32_t access_flags_; // TODO: make an instance field?
- // DexFile from which we came; needed to resolve constant pool entries
+ // DexCache of resolved constant pool entries
// (will be NULL for VM-generated, e.g. arrays and primitive classes)
- DexFile* dex_file_;
+ DexCache* dex_cache_;
// state of class initialization
Status status_;
@@ -924,7 +924,7 @@
class CharArray : public Array {
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(CharArray);
+ CharArray();
};
class ObjectArray : public Array {
diff --git a/src/raw_dex_file.cc b/src/raw_dex_file.cc
deleted file mode 100644
index 21badb4..0000000
--- a/src/raw_dex_file.cc
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
-#include "raw_dex_file.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 "scoped_ptr.h"
-#include "utils.h"
-
-namespace art {
-
-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
diff --git a/src/raw_dex_file.h b/src/raw_dex_file.h
deleted file mode 100644
index da7cd86..0000000
--- a/src/raw_dex_file.h
+++ /dev/null
@@ -1,525 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
-#ifndef ART_SRC_RAW_DEX_FILE_H_
-#define ART_SRC_RAW_DEX_FILE_H_
-
-#include "globals.h"
-#include "leb128.h"
-#include "logging.h"
-#include "scoped_ptr.h"
-#include "stringpiece.h"
-#include "strutil.h"
-
-#include <map>
-
-namespace art {
-
-union JValue;
-
-// TODO: move all of the macro functionality into the DexFile class.
-class RawDexFile {
- public:
- static const byte kDexMagic[];
- static const byte kDexMagicVersion[];
- static const size_t kSha1DigestSize = 20;
-
- static const byte kEncodedValueTypeMask = 0x1f; // 0b11111
- static const byte kEncodedValueArgShift = 5;
-
- // The value of an invalid index.
- static const uint32_t kDexNoIndex = 0xFFFFFFFF;
-
- enum ValueType {
- kByte = 0x00,
- kShort = 0x02,
- kChar = 0x03,
- kInt = 0x04,
- kLong = 0x06,
- kFloat = 0x10,
- kDouble = 0x11,
- kString = 0x17,
- kType = 0x18,
- kField = 0x19,
- kMethod = 0x1a,
- kEnum = 0x1b,
- kArray = 0x1c,
- kAnnotation = 0x1d,
- kNull = 0x1e,
- kBoolean = 0x1f
- };
-
- // Raw header_item.
- struct Header {
- uint8_t magic_[8];
- uint32_t checksum_;
- uint8_t signature_[kSha1DigestSize];
- uint32_t file_size_; // length of entire file
- uint32_t header_size_; // offset to start of next section
- uint32_t endian_tag_;
- uint32_t link_size_;
- uint32_t link_off_;
- uint32_t map_off_;
- uint32_t string_ids_size_;
- uint32_t string_ids_off_;
- uint32_t type_ids_size_;
- uint32_t type_ids_off_;
- uint32_t proto_ids_size_;
- uint32_t proto_ids_off_;
- uint32_t field_ids_size_;
- uint32_t field_ids_off_;
- uint32_t method_ids_size_;
- uint32_t method_ids_off_;
- uint32_t class_defs_size_;
- uint32_t class_defs_off_;
- uint32_t data_size_;
- uint32_t data_off_;
- };
-
- // Raw string_id_item.
- struct StringId {
- uint32_t string_data_off_; // offset in bytes from the base address
- };
-
- // Raw type_id_item.
- struct TypeId {
- uint32_t descriptor_idx_; // index into string_ids
- };
-
- // Raw field_id_item.
- struct FieldId {
- uint16_t class_idx_; // index into typeIds list for defining class
- uint16_t type_idx_; // index into typeIds for field type
- uint32_t name_idx_; // index into stringIds for field name
- };
-
- // Raw method_id_item.
- struct MethodId {
- uint16_t class_idx_; // index into typeIds list for defining class
- uint16_t proto_idx_; // index into protoIds for method prototype
- uint32_t name_idx_; // index into stringIds for method name
- };
-
- // Raw proto_id_item.
- struct ProtoId {
- uint32_t shorty_idx_; // index into string_ids for shorty descriptor
- uint32_t return_type_idx_; // index into type_ids list for return type
- uint32_t parameters_off_; // file offset to type_list for parameter types
- };
-
- // Raw class_def_item.
- struct ClassDef {
- uint32_t class_idx_; // index into typeIds for this class
- uint32_t access_flags_;
- uint32_t superclass_idx_; // index into typeIds for superclass
- uint32_t interfaces_off_; // file offset to TypeList
- uint32_t source_file_idx_; // index into stringIds for source file name
- uint32_t annotations_off_; // file offset to annotations_directory_item
- uint32_t class_data_off_; // file offset to class_data_item
- uint32_t static_values_off_; // file offset to EncodedArray
- };
-
- // Raw type_item.
- struct TypeItem {
- uint16_t type_idx_; // index into type_ids section
- };
-
- // Raw type_list.
- class TypeList {
- public:
- uint32_t Size() const {
- return size_;
- }
-
- const TypeItem& GetTypeItem(uint32_t idx) const {
- CHECK_LT(idx, this->size_);
- return this->list_[idx];
- }
-
- private:
- uint32_t size_; // size of the list, in entries
- TypeItem list_[1]; // elements of the list
- };
-
- class ParameterIterator { // TODO: stream
- public:
- ParameterIterator(const RawDexFile& raw, const ProtoId& proto_id)
- : raw_(raw), size_(0), pos_(0) {
- type_list_ = raw_.GetProtoParameters(proto_id);
- if (type_list_ != NULL) {
- size_ = type_list_->Size();
- }
- }
- bool HasNext() const { return pos_ != size_; }
- void Next() { ++pos_; }
- const char* GetDescriptor() {
- uint32_t type_idx = type_list_->GetTypeItem(pos_).type_idx_;
- return raw_.dexStringByTypeIdx(type_idx);
- }
- private:
- const RawDexFile& raw_;
- const TypeList* type_list_;
- uint32_t size_;
- uint32_t pos_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterIterator);
- };
-
- ParameterIterator* GetParameterIterator(const ProtoId& proto_id) const {
- return new ParameterIterator(*this, proto_id);
- }
-
- const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const {
- return dexStringByTypeIdx(proto_id.return_type_idx_);
- }
-
- // Raw code_item.
- struct CodeItem {
- uint16_t registers_size_;
- uint16_t ins_size_;
- uint16_t outs_size_;
- uint16_t tries_size_;
- uint32_t debug_info_off_; // file offset to debug info stream
- uint32_t insns_size_; // size of the insns array, in 2 byte code units
- uint16_t insns_[1];
- };
-
- // Partially decoded form of class_data_item.
- struct ClassDataHeader {
- uint32_t static_fields_size_; // the number of static fields
- uint32_t instance_fields_size_; // the number of instance fields
- uint32_t direct_methods_size_; // the number of direct methods
- uint32_t virtual_methods_size_; // the number of virtual methods
- };
-
- // Decoded form of encoded_field.
- struct Field {
- uint32_t field_idx_; // index into the field_ids list for the identity of this field
- uint32_t access_flags_; // access flags for the field
- };
-
- // Decoded form of encoded_method.
- struct Method {
- uint32_t method_idx_;
- uint32_t access_flags_;
- uint32_t code_off_;
- };
-
- // Opens a .dex file from the file system.
- static RawDexFile* OpenFile(const char* filename);
-
- // Opens a .dex file from a new allocated pointer
- static RawDexFile* OpenPtr(byte* ptr, size_t length);
-
- // Closes a .dex file.
- virtual ~RawDexFile();
-
- const Header& GetHeader() {
- CHECK(header_ != NULL);
- return *header_;
- }
-
- // Looks up a class definition by its class descriptor.
- const ClassDef* FindClassDef(const StringPiece& descriptor) const;
-
- // Returns the number of string identifiers in the .dex file.
- size_t NumStringIds() const {
- CHECK(header_ != NULL);
- return header_->string_ids_size_;
- }
-
- // Returns the number of type identifiers in the .dex file.
- size_t NumTypeIds() const {
- CHECK(header_ != NULL);
- return header_->type_ids_size_;
- }
-
- // Returns the number of prototype identifiers in the .dex file.
- size_t NumProtoIds() const {
- CHECK(header_ != NULL);
- return header_->proto_ids_size_;
- }
-
- // Returns the number of field identifiers in the .dex file.
- size_t NumFieldIds() const {
- CHECK(header_ != NULL);
- return header_->field_ids_size_;
- }
-
- // Returns the number of method identifiers in the .dex file.
- size_t NumMethodIds() const {
- CHECK(header_ != NULL);
- return header_->method_ids_size_;
- }
-
- // Returns the number of class definitions in the .dex file.
- size_t NumClassDefs() const {
- CHECK(header_ != NULL);
- return header_->class_defs_size_;
- }
-
- // Returns a pointer to the memory mapped class data.
- // TODO: return a stream
- const byte* GetClassData(const ClassDef& class_def) const {
- if (class_def.class_data_off_ == 0) {
- return NULL;
- } else {
- return base_ + class_def.class_data_off_;
- }
- }
-
- // Decodes the header section from the raw class data bytes.
- ClassDataHeader ReadClassDataHeader(const byte** class_data) const {
- CHECK(class_data != NULL);
- ClassDataHeader header;
- memset(&header, 0, sizeof(ClassDataHeader));
- if (*class_data != NULL) {
- header.static_fields_size_ = DecodeUnsignedLeb128(class_data);
- header.instance_fields_size_ = DecodeUnsignedLeb128(class_data);
- header.direct_methods_size_ = DecodeUnsignedLeb128(class_data);
- header.virtual_methods_size_ = DecodeUnsignedLeb128(class_data);
- }
- return header;
- }
-
- // Returns the class descriptor string of a class definition.
- const char* GetClassDescriptor(const ClassDef& class_def) const {
- return dexStringByTypeIdx(class_def.class_idx_);
- }
-
- // Returns the StringId at the specified index.
- const StringId& GetStringId(uint32_t idx) const {
- CHECK_LT(idx, NumStringIds());
- return string_ids_[idx];
- }
-
- // Returns the TypeId at the specified index.
- const TypeId& GetTypeId(uint32_t idx) const {
- CHECK_LT(idx, NumTypeIds());
- return type_ids_[idx];
- }
-
- // Returns the FieldId at the specified index.
- const FieldId& GetFieldId(uint32_t idx) const {
- CHECK_LT(idx, NumFieldIds());
- return field_ids_[idx];
- }
-
- // Returns the MethodId at the specified index.
- const MethodId& GetMethodId(uint32_t idx) const {
- CHECK_LT(idx, NumMethodIds());
- return method_ids_[idx];
- }
-
- // Returns the ProtoId at the specified index.
- const ProtoId& GetProtoId(uint32_t idx) const {
- CHECK_LT(idx, NumProtoIds());
- return proto_ids_[idx];
- }
-
- // Returns the ClassDef at the specified index.
- const ClassDef& GetClassDef(uint32_t idx) const {
- CHECK_LT(idx, NumClassDefs());
- return class_defs_[idx];
- }
-
- const TypeList* GetInterfacesList(const ClassDef& class_def) const {
- if (class_def.interfaces_off_ == 0) {
- return NULL;
- } else {
- const byte* addr = base_ + class_def.interfaces_off_;
- return reinterpret_cast<const TypeList*>(addr);
- }
- }
-
- const CodeItem* GetCodeItem(const Method& method) const {
- if (method.code_off_ == 0) {
- return NULL; // native or abstract method
- } else {
- const byte* addr = base_ + method.code_off_;
- return reinterpret_cast<const CodeItem*>(addr);
- }
- }
-
- // Returns the short form method descriptor for the given prototype.
- const char* GetShorty(uint32_t proto_idx) const {
- const ProtoId& proto_id = GetProtoId(proto_idx);
- return dexStringById(proto_id.shorty_idx_);
- }
-
- const TypeList* GetProtoParameters(const ProtoId& proto_id) const {
- if (proto_id.parameters_off_ == 0) {
- return NULL;
- } else {
- const byte* addr = base_ + proto_id.parameters_off_;
- return reinterpret_cast<const TypeList*>(addr);
- }
- }
-
- const byte* GetEncodedArray(const ClassDef& class_def) const {
- if (class_def.static_values_off_ == 0) {
- return 0;
- } else {
- return base_ + class_def.static_values_off_;
- }
- }
-
- int32_t GetStringLength(const StringId& string_id) const {
- const byte* ptr = base_ + string_id.string_data_off_;
- return DecodeUnsignedLeb128(&ptr);
- }
-
- ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const;
-
- // From libdex...
-
- // Returns a pointer to the UTF-8 string data referred to by the
- // given string_id.
- const char* GetStringData(const StringId& string_id) const {
- const byte* ptr = base_ + string_id.string_data_off_;
- // Skip the uleb128 length.
- while (*(ptr++) > 0x7f) /* empty */ ;
- return (const char*) ptr;
- }
-
- // return the UTF-8 encoded string with the specified string_id index
- const char* dexStringById(uint32_t idx) const {
- const StringId& string_id = GetStringId(idx);
- return GetStringData(string_id);
- }
-
- // Get the descriptor string associated with a given type index.
- const char* dexStringByTypeIdx(uint32_t idx) const {
- const TypeId& type_id = GetTypeId(idx);
- return dexStringById(type_id.descriptor_idx_);
- }
-
- // TODO: encoded_field is actually a stream of bytes
- void dexReadClassDataField(const byte** encoded_field,
- RawDexFile::Field* field,
- uint32_t* last_idx) const {
- uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_field);
- field->access_flags_ = DecodeUnsignedLeb128(encoded_field);
- field->field_idx_ = idx;
- *last_idx = idx;
- }
-
- // TODO: encoded_method is actually a stream of bytes
- void dexReadClassDataMethod(const byte** encoded_method,
- RawDexFile::Method* method,
- uint32_t* last_idx) const {
- uint32_t idx = *last_idx + DecodeUnsignedLeb128(encoded_method);
- method->access_flags_ = DecodeUnsignedLeb128(encoded_method);
- method->code_off_ = DecodeUnsignedLeb128(encoded_method);
- method->method_idx_ = idx;
- *last_idx = idx;
- }
-
-
- // TODO: const reference
- uint32_t dexGetIndexForClassDef(const ClassDef* class_def) const {
- CHECK_GE(class_def, class_defs_);
- CHECK_LT(class_def, class_defs_ + header_->class_defs_size_);
- return class_def - class_defs_;
- }
-
- const char* dexGetSourceFile(const ClassDef& class_def) const {
- if (class_def.source_file_idx_ == 0xffffffff) {
- return NULL;
- } else {
- return dexStringById(class_def.source_file_idx_);
- }
- }
-
- private:
- // Helper class to deallocate underlying storage.
- class Closer {
- public:
- virtual ~Closer();
- };
-
- // Helper class to deallocate mmap-backed .dex files.
- class MmapCloser : public Closer {
- public:
- MmapCloser(void* addr, size_t length);
- virtual ~MmapCloser();
- private:
- void* addr_;
- size_t length_;
- };
-
- // Helper class for deallocating new/delete-backed .dex files.
- class PtrCloser : public Closer {
- public:
- PtrCloser(byte* addr);
- virtual ~PtrCloser();
- private:
- byte* addr_;
- };
-
- // Opens a .dex file at a the given address.
- static RawDexFile* Open(const byte* dex_file, size_t length, Closer* closer);
-
- RawDexFile(const byte* addr, size_t length, Closer* closer)
- : base_(addr),
- length_(length),
- closer_(closer),
- header_(0),
- string_ids_(0),
- type_ids_(0),
- field_ids_(0),
- method_ids_(0),
- proto_ids_(0),
- class_defs_(0) {}
-
- // Top-level initializer that calls other Init methods.
- bool Init();
-
- // Caches pointers into to the various file sections.
- void InitMembers();
-
- // Builds the index of descriptors to class definitions.
- void InitIndex();
-
- // Returns true if the byte string equals the magic value.
- bool CheckMagic(const byte* magic);
-
- // Returns true if the header magic is of the expected value.
- bool IsMagicValid();
-
- // The index of descriptors to class definitions.
- typedef std::map<const StringPiece, const RawDexFile::ClassDef*> Index;
- Index index_;
-
- // The base address of the memory mapping.
- const byte* base_;
-
- // The size of the underlying memory allocation in bytes.
- size_t length_;
-
- // Helper object to free the underlying allocation.
- scoped_ptr<Closer> closer_;
-
- // Points to the header section.
- const Header* header_;
-
- // Points to the base of the string identifier list.
- const StringId* string_ids_;
-
- // Points to the base of the type identifier list.
- const TypeId* type_ids_;
-
- // Points to the base of the field identifier list.
- const FieldId* field_ids_;
-
- // Points to the base of the method identifier list.
- const MethodId* method_ids_;
-
- // Points to the base of the prototype identifier list.
- const ProtoId* proto_ids_;
-
- // Points to the base of the class definition list.
- const ClassDef* class_defs_;
-};
-
-} // namespace art
-
-#endif // ART_SRC_RAW_DEX_FILE_H_
diff --git a/src/raw_dex_file_test.cc b/src/raw_dex_file_test.cc
deleted file mode 100644
index 4be9991..0000000
--- a/src/raw_dex_file_test.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
-#include "common_test.h"
-#include "dex_file.h"
-#include "raw_dex_file.h"
-#include "scoped_ptr.h"
-
-#include <stdio.h>
-#include "gtest/gtest.h"
-
-namespace art {
-
-TEST(RawDexFileTest, Open) {
- scoped_ptr<RawDexFile> raw(OpenRawDexFileBase64(kNestedDex));
- ASSERT_TRUE(raw != NULL);
-}
-
-TEST(RawDexFileTest, Header) {
- scoped_ptr<RawDexFile> raw(OpenRawDexFileBase64(kNestedDex));
- ASSERT_TRUE(raw != NULL);
-
- const RawDexFile::Header& header = raw->GetHeader();
- // TODO: header.magic_
- EXPECT_EQ(0x00d87910U, header.checksum_);
- // TODO: header.signature_
- EXPECT_EQ(904U, header.file_size_);
- EXPECT_EQ(112U, header.header_size_);
- EXPECT_EQ(0U, header.link_size_);
- EXPECT_EQ(0U, header.link_off_);
- EXPECT_EQ(15U, header.string_ids_size_);
- EXPECT_EQ(112U, header.string_ids_off_);
- EXPECT_EQ(7U, header.type_ids_size_);
- EXPECT_EQ(172U, header.type_ids_off_);
- EXPECT_EQ(2U, header.proto_ids_size_);
- EXPECT_EQ(200U, header.proto_ids_off_);
- EXPECT_EQ(1U, header.field_ids_size_);
- EXPECT_EQ(224U, header.field_ids_off_);
- EXPECT_EQ(3U, header.method_ids_size_);
- EXPECT_EQ(232U, header.method_ids_off_);
- EXPECT_EQ(2U, header.class_defs_size_);
- EXPECT_EQ(256U, header.class_defs_off_);
- EXPECT_EQ(584U, header.data_size_);
- EXPECT_EQ(320U, header.data_off_);
-}
-
-TEST(RawDexFileTest, ClassDefs) {
- scoped_ptr<RawDexFile> raw(OpenRawDexFileBase64(kNestedDex));
- ASSERT_TRUE(raw != NULL);
- EXPECT_EQ(2U, raw->NumClassDefs());
-
- const RawDexFile::ClassDef& c0 = raw->GetClassDef(0);
- EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c0));
-
- const RawDexFile::ClassDef& c1 = raw->GetClassDef(1);
- EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1));
-}
-
-} // namespace art
diff --git a/src/runtime.h b/src/runtime.h
index 69f6228..f697b4a 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -7,7 +7,7 @@
#include "globals.h"
#include "macros.h"
-#include "raw_dex_file.h"
+#include "dex_file.h"
#include "stringpiece.h"
namespace art {