Give an example of walking TypeIds in a DexFile
Also prevent accidentally copying of DexFile structures
Change-Id: I293bdfe073ce1e1a54f6de2e0abadac312503016
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 0999788..c28fc65 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -633,7 +633,6 @@
// Load instance fields.
DCHECK(klass->ifields_ == NULL);
if (num_instance_fields != 0) {
- // TODO: allocate on the object heap.
klass->ifields_ = AllocObjectArray<Field>(num_instance_fields);
uint32_t last_idx = 0;
for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index ce08b1b..e2b9a2b 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -23,7 +23,10 @@
}
void AssertPrimitiveClass(const StringPiece& descriptor) {
- Class* primitive = class_linker_->FindSystemClass(descriptor);
+ AssertPrimitiveClass(descriptor, class_linker_->FindSystemClass(descriptor));
+ }
+
+ void AssertPrimitiveClass(const StringPiece& descriptor, const Class* primitive) {
ASSERT_TRUE(primitive != NULL);
ASSERT_TRUE(primitive->GetClass() != NULL);
ASSERT_EQ(primitive->GetClass(), primitive->GetClass()->GetClass());
@@ -56,6 +59,13 @@
const StringPiece& component_type,
ClassLoader* class_loader) {
Class* array = class_linker_->FindClass(array_descriptor, class_loader);
+ EXPECT_EQ(array_rank, array->array_rank_);
+ EXPECT_TRUE(array->GetComponentType()->GetDescriptor()->Equals(component_type));
+ EXPECT_EQ(class_loader, array->GetClassLoader());
+ AssertArrayClass(array_descriptor, array);
+ }
+
+ void AssertArrayClass(const StringPiece& array_descriptor, Class* array) {
ASSERT_TRUE(array != NULL);
ASSERT_TRUE(array->GetClass() != NULL);
ASSERT_EQ(array->GetClass(), array->GetClass()->GetClass());
@@ -64,16 +74,14 @@
EXPECT_TRUE(array->GetSuperClass() != NULL);
EXPECT_EQ(class_linker_->FindSystemClass("Ljava/lang/Object;"), array->GetSuperClass());
EXPECT_TRUE(array->HasSuperClass());
- EXPECT_EQ(class_loader, array->GetClassLoader());
ASSERT_TRUE(array->GetComponentType() != NULL);
ASSERT_TRUE(array->GetComponentType()->GetDescriptor() != NULL);
- EXPECT_TRUE(array->GetComponentType()->GetDescriptor()->Equals(component_type));
EXPECT_TRUE(array->GetStatus() == Class::kStatusInitialized);
EXPECT_FALSE(array->IsErroneous());
EXPECT_TRUE(array->IsVerified());
EXPECT_TRUE(array->IsLinked());
EXPECT_TRUE(array->IsArray());
- EXPECT_EQ(array_rank, array->array_rank_);
+ EXPECT_LE(1, array->array_rank_);
EXPECT_FALSE(array->IsInterface());
EXPECT_EQ(array->GetComponentType()->IsPublic(), array->IsPublic());
EXPECT_TRUE(array->IsFinal());
@@ -86,7 +94,7 @@
EXPECT_EQ(2U, array->NumInterfaces());
}
- void AssertDexFileMethod(Class* klass, Method* method) {
+ void AssertMethod(Class* klass, Method* method) {
EXPECT_TRUE(method != NULL);
EXPECT_TRUE(method->GetName() != NULL);
EXPECT_TRUE(method->GetSignature() != NULL);
@@ -101,17 +109,14 @@
EXPECT_EQ(method->declaring_class_->dex_cache_->GetFields(), method->dex_cache_fields_);
}
- void AssertDexFileField(Class* klass, Field* field) {
+ void AssertField(Class* klass, Field* field) {
EXPECT_TRUE(field != NULL);
EXPECT_EQ(klass, field->GetDeclaringClass());
EXPECT_TRUE(field->GetName() != NULL);
EXPECT_TRUE(field->GetDescriptor() != NULL);
}
- void AssertDexFileClass(ClassLoader* class_loader, const char* descriptor) {
- ASSERT_TRUE(descriptor != NULL);
- Class* klass = class_linker_->FindSystemClass(descriptor);
- ASSERT_TRUE(klass != NULL);
+ void AssertClass(const StringPiece& descriptor, Class* klass) {
EXPECT_TRUE(klass->GetDescriptor()->Equals(descriptor));
if (klass->descriptor_->Equals(String::AllocFromModifiedUtf8("Ljava/lang/Object;"))) {
EXPECT_FALSE(klass->HasSuperClass());
@@ -119,7 +124,6 @@
EXPECT_TRUE(klass->HasSuperClass());
EXPECT_TRUE(klass->GetSuperClass() != NULL);
}
- EXPECT_EQ(class_loader, klass->GetClassLoader());
EXPECT_TRUE(klass->GetDexCache() != NULL);
EXPECT_TRUE(klass->GetComponentType() == NULL);
EXPECT_TRUE(klass->GetComponentType() == NULL);
@@ -161,25 +165,25 @@
for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
Method* method = klass->GetDirectMethod(i);
- AssertDexFileMethod(klass, method);
+ AssertMethod(klass, method);
EXPECT_EQ(klass, method->GetDeclaringClass());
}
for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
Method* method = klass->GetVirtualMethod(i);
- AssertDexFileMethod(klass, method);
+ AssertMethod(klass, method);
EXPECT_TRUE(method->GetDeclaringClass()->IsAssignableFrom(klass));
}
for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
Field* field = klass->GetInstanceField(i);
- AssertDexFileField(klass, field);
+ AssertField(klass, field);
EXPECT_FALSE(field->IsStatic());
}
for (size_t i = 0; i < klass->NumStaticFields(); i++) {
Field* field = klass->GetStaticField(i);
- AssertDexFileField(klass, field);
+ AssertField(klass, field);
EXPECT_TRUE(field->IsStatic());
}
@@ -187,13 +191,15 @@
EXPECT_GE(klass->NumInstanceFields(), klass->NumReferenceInstanceFields());
for (size_t i = 0; i < klass->NumReferenceInstanceFields(); i++) {
Field* field = klass->GetInstanceField(i);
- Class* field_type = class_linker_->FindClass(field->GetDescriptor(), class_loader);
+ Class* field_type = class_linker_->FindClass(field->GetDescriptor(),
+ klass->GetClassLoader());
ASSERT_TRUE(field_type != NULL);
EXPECT_FALSE(field_type->IsPrimitive());
}
for (size_t i = klass->NumReferenceInstanceFields(); i < klass->NumInstanceFields(); i++) {
Field* field = klass->GetInstanceField(i);
- Class* field_type = class_linker_->FindClass(field->GetDescriptor(), class_loader);
+ Class* field_type = class_linker_->FindClass(field->GetDescriptor(),
+ klass->GetClassLoader());
ASSERT_TRUE(field_type != NULL);
EXPECT_TRUE(field_type->IsPrimitive());
}
@@ -208,19 +214,41 @@
total_num_reference_instance_fields == 0);
}
- static void TestRootVisitor(Object* root, void* arg) {
- EXPECT_TRUE(root != NULL);
+ void AssertDexFileClass(ClassLoader* class_loader, const StringPiece& descriptor) {
+ ASSERT_TRUE(descriptor != NULL);
+ Class* klass = class_linker_->FindSystemClass(descriptor);
+ ASSERT_TRUE(klass != NULL);
+ EXPECT_TRUE(klass->GetDescriptor()->Equals(descriptor));
+ EXPECT_EQ(class_loader, klass->GetClassLoader());
+ if (klass->IsPrimitive()) {
+ AssertPrimitiveClass(descriptor, klass);
+ } else if (klass->IsArray()) {
+ AssertArrayClass(descriptor, klass);
+ } else {
+ AssertClass(descriptor, klass);
+ }
}
void AssertDexFile(const DexFile* dex, ClassLoader* class_loader) {
ASSERT_TRUE(dex != NULL);
+ // Verify all the classes defined in this file
for (size_t i = 0; i < dex->NumClassDefs(); i++) {
- const DexFile::ClassDef class_def = dex->GetClassDef(i);
+ const DexFile::ClassDef& class_def = dex->GetClassDef(i);
const char* descriptor = dex->GetClassDescriptor(class_def);
AssertDexFileClass(class_loader, descriptor);
}
+ // Verify all the types referened by this file
+ for (size_t i = 0; i < dex->NumTypeIds(); i++) {
+ const DexFile::TypeId& type_id = dex->GetTypeId(i);
+ const char* descriptor = dex->GetTypeDescriptor(type_id);
+ AssertDexFileClass(class_loader, descriptor);
+ }
class_linker_->VisitRoots(TestRootVisitor, NULL);
}
+
+ static void TestRootVisitor(Object* root, void* arg) {
+ EXPECT_TRUE(root != NULL);
+ }
};
TEST_F(ClassLinkerTest, FindClassNonexistent) {
diff --git a/src/dex_file.h b/src/dex_file.h
index 51f5d08..1431f1e 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -77,16 +77,22 @@
uint32_t class_defs_off_;
uint32_t data_size_;
uint32_t data_off_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Header);
};
// Raw string_id_item.
struct StringId {
uint32_t string_data_off_; // offset in bytes from the base address
+ private:
+ DISALLOW_COPY_AND_ASSIGN(StringId);
};
// Raw type_id_item.
struct TypeId {
uint32_t descriptor_idx_; // index into string_ids
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TypeId);
};
// Raw field_id_item.
@@ -94,6 +100,8 @@
uint16_t class_idx_; // index into type_ids_ list for defining class
uint16_t type_idx_; // index into type_ids_ for field type
uint32_t name_idx_; // index into string_ids_ for field name
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FieldId);
};
// Raw method_id_item.
@@ -101,6 +109,8 @@
uint16_t class_idx_; // index into type_ids_ list for defining class
uint16_t proto_idx_; // index into proto_ids_ for method prototype
uint32_t name_idx_; // index into string_ids_ for method name
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MethodId);
};
// Raw proto_id_item.
@@ -108,6 +118,8 @@
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
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ProtoId);
};
// Raw class_def_item.
@@ -120,11 +132,15 @@
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
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ClassDef);
};
// Raw type_item.
struct TypeItem {
uint16_t type_idx_; // index into type_ids section
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TypeItem);
};
// Raw type_list.
@@ -142,6 +158,7 @@
private:
uint32_t size_; // size of the list, in entries
TypeItem list_[1]; // elements of the list
+ DISALLOW_COPY_AND_ASSIGN(TypeList);
};
class ParameterIterator { // TODO: stream
@@ -184,6 +201,8 @@
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];
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CodeItem);
};
struct CatchHandlerItem {
@@ -196,6 +215,8 @@
uint32_t start_addr_;
uint16_t insn_count_;
uint16_t handler_off_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TryItem);
};
class CatchHandlerIterator {
@@ -268,6 +289,9 @@
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
+ Field() {};
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Field);
};
// Decoded form of encoded_method.
@@ -275,6 +299,9 @@
uint32_t method_idx_;
uint32_t access_flags_;
uint32_t code_off_;
+ Method() {};
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Method);
};
typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
@@ -377,6 +404,11 @@
return dexStringByTypeIdx(class_def.class_idx_);
}
+ // Returns the type descriptor string of a type id.
+ const char* GetTypeDescriptor(const TypeId& type_id) const {
+ return dexStringById(type_id.descriptor_idx_);
+ }
+
// Returns the StringId at the specified index.
const StringId& GetStringId(uint32_t idx) const {
CHECK_LT(idx, NumStringIds());
@@ -691,6 +723,9 @@
// Is the local defined and live.
bool is_live_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LocalInfo);
};
struct LineNumFromPcContext {
@@ -698,6 +733,8 @@
address_(address), line_num_(line_num) {}
uint32_t address_;
uint32_t line_num_;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LineNumFromPcContext);
};
void InvokeLocalCbIfLive(void *cnxt, int reg, uint32_t end_address,
diff --git a/src/image_test.cc b/src/image_test.cc
index 7c1312b..54c2c75 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -17,7 +17,7 @@
// TODO: move the touching of classes and GC to the ImageWriter proper
for (size_t i = 0; i < java_lang_dex_file_->NumClassDefs(); i++) {
- const DexFile::ClassDef class_def = java_lang_dex_file_->GetClassDef(i);
+ const DexFile::ClassDef& class_def = java_lang_dex_file_->GetClassDef(i);
const char* descriptor = java_lang_dex_file_->GetClassDescriptor(class_def);
Class* klass = class_linker_->FindSystemClass(descriptor);
ASSERT_TRUE(klass != NULL) << descriptor;
@@ -81,7 +81,7 @@
byte* boot_base = boot_space->GetBase();
byte* boot_limit = boot_space->GetLimit();
for (size_t i = 0; i < dex->NumClassDefs(); i++) {
- const DexFile::ClassDef class_def = dex->GetClassDef(i);
+ const DexFile::ClassDef& class_def = dex->GetClassDef(i);
const char* descriptor = dex->GetClassDescriptor(class_def);
Class* klass = class_linker_->FindSystemClass(descriptor);
EXPECT_TRUE(klass != NULL) << descriptor;