Finish adding checks to dex ir verification.
Adds missing checks for class defs, annotations, class data, code, etc.
Bug: 36107940
Test: mm test-art-host
Change-Id: Ifaac07299cf237827160c29b4230b0dc0845dc41
diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h
index 96afb90..78ddde8 100644
--- a/dexlayout/dex_ir.h
+++ b/dexlayout/dex_ir.h
@@ -748,8 +748,7 @@
const TypeId* ClassType() const { return class_type_; }
uint32_t GetAccessFlags() const { return access_flags_; }
const TypeId* Superclass() const { return superclass_; }
- const TypeIdVector* Interfaces()
- { return interfaces_ == nullptr ? nullptr : interfaces_->GetTypeList(); }
+ const TypeList* Interfaces() { return interfaces_; }
uint32_t InterfacesOffset() { return interfaces_ == nullptr ? 0 : interfaces_->GetOffset(); }
const StringId* SourceFile() const { return source_file_; }
AnnotationsDirectoryItem* Annotations() const { return annotations_; }
@@ -781,7 +780,7 @@
uint32_t GetAddress() const { return address_; }
private:
- const TypeId* type_id_;
+ const TypeId* type_id_; // This can be nullptr.
uint32_t address_;
DISALLOW_COPY_AND_ASSIGN(TypeAddrPair);
diff --git a/dexlayout/dex_verify.cc b/dexlayout/dex_verify.cc
index aec1d0c..5458129 100644
--- a/dexlayout/dex_verify.cc
+++ b/dexlayout/dex_verify.cc
@@ -20,6 +20,8 @@
#include "dex_verify.h"
+#include <inttypes.h>
+
#include "android-base/stringprintf.h"
namespace art {
@@ -32,7 +34,7 @@
dex_ir::Collections& orig = orig_header->GetCollections();
dex_ir::Collections& output = output_header->GetCollections();
- // Compare all id sections.
+ // Compare all id sections. They have a defined order that can't be changed by dexlayout.
if (!VerifyIds(orig.StringIds(), output.StringIds(), "string ids", error_msg) ||
!VerifyIds(orig.TypeIds(), output.TypeIds(), "type ids", error_msg) ||
!VerifyIds(orig.ProtoIds(), output.ProtoIds(), "proto ids", error_msg) ||
@@ -40,6 +42,10 @@
!VerifyIds(orig.MethodIds(), output.MethodIds(), "method ids", error_msg)) {
return false;
}
+ // Compare class defs. The order may have been changed by dexlayout.
+ if (!VerifyClassDefs(orig.ClassDefs(), output.ClassDefs(), error_msg)) {
+ return false;
+ }
return true;
}
@@ -49,7 +55,7 @@
std::string* error_msg) {
if (orig.size() != output.size()) {
*error_msg = StringPrintf(
- "Mismatched size for %s section, %zu vs %zu.", section_name, orig.size(), output.size());
+ "Mismatched size for %s section: %zu vs %zu.", section_name, orig.size(), output.size());
return false;
}
for (size_t i = 0; i < orig.size(); ++i) {
@@ -62,7 +68,7 @@
bool VerifyId(dex_ir::StringId* orig, dex_ir::StringId* output, std::string* error_msg) {
if (strcmp(orig->Data(), output->Data()) != 0) {
- *error_msg = StringPrintf("Mismatched string data for string id %u @ orig offset %x, %s vs %s.",
+ *error_msg = StringPrintf("Mismatched string data for string id %u at offset %x: %s vs %s.",
orig->GetIndex(),
orig->GetOffset(),
orig->Data(),
@@ -74,7 +80,7 @@
bool VerifyId(dex_ir::TypeId* orig, dex_ir::TypeId* output, std::string* error_msg) {
if (orig->GetStringId()->GetIndex() != output->GetStringId()->GetIndex()) {
- *error_msg = StringPrintf("Mismatched string index for type id %u @ orig offset %x, %u vs %u.",
+ *error_msg = StringPrintf("Mismatched string index for type id %u at offset %x: %u vs %u.",
orig->GetIndex(),
orig->GetOffset(),
orig->GetStringId()->GetIndex(),
@@ -86,7 +92,7 @@
bool VerifyId(dex_ir::ProtoId* orig, dex_ir::ProtoId* output, std::string* error_msg) {
if (orig->Shorty()->GetIndex() != output->Shorty()->GetIndex()) {
- *error_msg = StringPrintf("Mismatched string index for proto id %u @ orig offset %x, %u vs %u.",
+ *error_msg = StringPrintf("Mismatched string index for proto id %u at offset %x: %u vs %u.",
orig->GetIndex(),
orig->GetOffset(),
orig->Shorty()->GetIndex(),
@@ -94,7 +100,7 @@
return false;
}
if (orig->ReturnType()->GetIndex() != output->ReturnType()->GetIndex()) {
- *error_msg = StringPrintf("Mismatched type index for proto id %u @ orig offset %x, %u vs %u.",
+ *error_msg = StringPrintf("Mismatched type index for proto id %u at offset %x: %u vs %u.",
orig->GetIndex(),
orig->GetOffset(),
orig->ReturnType()->GetIndex(),
@@ -102,7 +108,7 @@
return false;
}
if (!VerifyTypeList(orig->Parameters(), output->Parameters())) {
- *error_msg = StringPrintf("Mismatched type list for proto id %u @ orig offset %x.",
+ *error_msg = StringPrintf("Mismatched type list for proto id %u at offset %x.",
orig->GetIndex(),
orig->GetOffset());
}
@@ -112,7 +118,7 @@
bool VerifyId(dex_ir::FieldId* orig, dex_ir::FieldId* output, std::string* error_msg) {
if (orig->Class()->GetIndex() != output->Class()->GetIndex()) {
*error_msg =
- StringPrintf("Mismatched class type index for field id %u @ orig offset %x, %u vs %u.",
+ StringPrintf("Mismatched class type index for field id %u at offset %x: %u vs %u.",
orig->GetIndex(),
orig->GetOffset(),
orig->Class()->GetIndex(),
@@ -120,7 +126,7 @@
return false;
}
if (orig->Type()->GetIndex() != output->Type()->GetIndex()) {
- *error_msg = StringPrintf("Mismatched type index for field id %u @ orig offset %x, %u vs %u.",
+ *error_msg = StringPrintf("Mismatched type index for field id %u at offset %x: %u vs %u.",
orig->GetIndex(),
orig->GetOffset(),
orig->Class()->GetIndex(),
@@ -128,7 +134,7 @@
return false;
}
if (orig->Name()->GetIndex() != output->Name()->GetIndex()) {
- *error_msg = StringPrintf("Mismatched string index for field id %u @ orig offset %x, %u vs %u.",
+ *error_msg = StringPrintf("Mismatched string index for field id %u at offset %x: %u vs %u.",
orig->GetIndex(),
orig->GetOffset(),
orig->Name()->GetIndex(),
@@ -140,7 +146,7 @@
bool VerifyId(dex_ir::MethodId* orig, dex_ir::MethodId* output, std::string* error_msg) {
if (orig->Class()->GetIndex() != output->Class()->GetIndex()) {
- *error_msg = StringPrintf("Mismatched type index for method id %u @ orig offset %x, %u vs %u.",
+ *error_msg = StringPrintf("Mismatched type index for method id %u at offset %x: %u vs %u.",
orig->GetIndex(),
orig->GetOffset(),
orig->Class()->GetIndex(),
@@ -148,7 +154,7 @@
return false;
}
if (orig->Proto()->GetIndex() != output->Proto()->GetIndex()) {
- *error_msg = StringPrintf("Mismatched proto index for method id %u @ orig offset %x, %u vs %u.",
+ *error_msg = StringPrintf("Mismatched proto index for method id %u at offset %x: %u vs %u.",
orig->GetIndex(),
orig->GetOffset(),
orig->Class()->GetIndex(),
@@ -157,7 +163,7 @@
}
if (orig->Name()->GetIndex() != output->Name()->GetIndex()) {
*error_msg =
- StringPrintf("Mismatched string index for method id %u @ orig offset %x, %u vs %u.",
+ StringPrintf("Mismatched string index for method id %u at offset %x: %u vs %u.",
orig->GetIndex(),
orig->GetOffset(),
orig->Name()->GetIndex(),
@@ -167,6 +173,96 @@
return true;
}
+struct ClassDefCompare {
+ bool operator()(dex_ir::ClassDef* lhs, dex_ir::ClassDef* rhs) const {
+ return lhs->ClassType()->GetIndex() < rhs->ClassType()->GetIndex();
+ }
+};
+
+// The class defs may have a new order due to dexlayout. Use the class's class_idx to uniquely
+// identify them and sort them for comparison.
+bool VerifyClassDefs(std::vector<std::unique_ptr<dex_ir::ClassDef>>& orig,
+ std::vector<std::unique_ptr<dex_ir::ClassDef>>& output,
+ std::string* error_msg) {
+ if (orig.size() != output.size()) {
+ *error_msg = StringPrintf(
+ "Mismatched size for class defs section: %zu vs %zu.", orig.size(), output.size());
+ return false;
+ }
+ // Store the class defs into sets sorted by the class's type index.
+ std::set<dex_ir::ClassDef*, ClassDefCompare> orig_set;
+ std::set<dex_ir::ClassDef*, ClassDefCompare> output_set;
+ for (size_t i = 0; i < orig.size(); ++i) {
+ orig_set.insert(orig[i].get());
+ output_set.insert(output[i].get());
+ }
+ auto orig_iter = orig_set.begin();
+ auto output_iter = output_set.begin();
+ while (orig_iter != orig_set.end() && output_iter != output_set.end()) {
+ if (!VerifyClassDef(*orig_iter, *output_iter, error_msg)) {
+ return false;
+ }
+ orig_iter++;
+ output_iter++;
+ }
+ return true;
+}
+
+bool VerifyClassDef(dex_ir::ClassDef* orig, dex_ir::ClassDef* output, std::string* error_msg) {
+ if (orig->ClassType()->GetIndex() != output->ClassType()->GetIndex()) {
+ *error_msg =
+ StringPrintf("Mismatched class type index for class def %u at offset %x: %u vs %u.",
+ orig->GetIndex(),
+ orig->GetOffset(),
+ orig->ClassType()->GetIndex(),
+ output->ClassType()->GetIndex());
+ return false;
+ }
+ if (orig->GetAccessFlags() != output->GetAccessFlags()) {
+ *error_msg =
+ StringPrintf("Mismatched access flags for class def %u at offset %x: %x vs %x.",
+ orig->GetIndex(),
+ orig->GetOffset(),
+ orig->GetAccessFlags(),
+ output->GetAccessFlags());
+ return false;
+ }
+ uint32_t orig_super = orig->Superclass() == nullptr ? 0 : orig->Superclass()->GetIndex();
+ uint32_t output_super = output->Superclass() == nullptr ? 0 : output->Superclass()->GetIndex();
+ if (orig_super != output_super) {
+ *error_msg =
+ StringPrintf("Mismatched super class for class def %u at offset %x: %u vs %u.",
+ orig->GetIndex(),
+ orig->GetOffset(),
+ orig_super,
+ output_super);
+ return false;
+ }
+ if (!VerifyTypeList(orig->Interfaces(), output->Interfaces())) {
+ *error_msg = StringPrintf("Mismatched type list for class def %u at offset %x.",
+ orig->GetIndex(),
+ orig->GetOffset());
+ return false;
+ }
+ const char* orig_source = orig->SourceFile() == nullptr ? "" : orig->SourceFile()->Data();
+ const char* output_source = output->SourceFile() == nullptr ? "" : output->SourceFile()->Data();
+ if (strcmp(orig_source, output_source) != 0) {
+ *error_msg = StringPrintf("Mismatched source file for class def %u at offset %x: %s vs %s.",
+ orig->GetIndex(),
+ orig->GetOffset(),
+ orig_source,
+ output_source);
+ return false;
+ }
+ if (!VerifyAnnotationsDirectory(orig->Annotations(), output->Annotations(), error_msg)) {
+ return false;
+ }
+ if (!VerifyClassData(orig->GetClassData(), output->GetClassData(), error_msg)) {
+ return false;
+ }
+ return VerifyEncodedArray(orig->StaticValues(), output->StaticValues(), error_msg);
+}
+
bool VerifyTypeList(const dex_ir::TypeList* orig, const dex_ir::TypeList* output) {
if (orig == nullptr || output == nullptr) {
return orig == output;
@@ -184,4 +280,841 @@
return true;
}
+bool VerifyAnnotationsDirectory(dex_ir::AnnotationsDirectoryItem* orig,
+ dex_ir::AnnotationsDirectoryItem* output,
+ std::string* error_msg) {
+ if (orig == nullptr || output == nullptr) {
+ if (orig != output) {
+ *error_msg = "Found unexpected empty annotations directory.";
+ return false;
+ }
+ return true;
+ }
+ if (!VerifyAnnotationSet(orig->GetClassAnnotation(), output->GetClassAnnotation(), error_msg)) {
+ return false;
+ }
+ if (!VerifyFieldAnnotations(orig->GetFieldAnnotations(),
+ output->GetFieldAnnotations(),
+ orig->GetOffset(),
+ error_msg)) {
+ return false;
+ }
+ if (!VerifyMethodAnnotations(orig->GetMethodAnnotations(),
+ output->GetMethodAnnotations(),
+ orig->GetOffset(),
+ error_msg)) {
+ return false;
+ }
+ return VerifyParameterAnnotations(orig->GetParameterAnnotations(),
+ output->GetParameterAnnotations(),
+ orig->GetOffset(),
+ error_msg);
+}
+
+bool VerifyFieldAnnotations(dex_ir::FieldAnnotationVector* orig,
+ dex_ir::FieldAnnotationVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig == nullptr || output == nullptr) {
+ if (orig != output) {
+ *error_msg = StringPrintf(
+ "Found unexpected empty field annotations for annotations directory at offset %x.",
+ orig_offset);
+ return false;
+ }
+ return true;
+ }
+ if (orig->size() != output->size()) {
+ *error_msg = StringPrintf(
+ "Mismatched field annotations size for annotations directory at offset %x: %zu vs %zu.",
+ orig_offset,
+ orig->size(),
+ output->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig->size(); ++i) {
+ dex_ir::FieldAnnotation* orig_field = (*orig)[i].get();
+ dex_ir::FieldAnnotation* output_field = (*output)[i].get();
+ if (orig_field->GetFieldId()->GetIndex() != output_field->GetFieldId()->GetIndex()) {
+ *error_msg = StringPrintf(
+ "Mismatched field annotation index for annotations directory at offset %x: %u vs %u.",
+ orig_offset,
+ orig_field->GetFieldId()->GetIndex(),
+ output_field->GetFieldId()->GetIndex());
+ return false;
+ }
+ if (!VerifyAnnotationSet(orig_field->GetAnnotationSetItem(),
+ output_field->GetAnnotationSetItem(),
+ error_msg)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyMethodAnnotations(dex_ir::MethodAnnotationVector* orig,
+ dex_ir::MethodAnnotationVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig == nullptr || output == nullptr) {
+ if (orig != output) {
+ *error_msg = StringPrintf(
+ "Found unexpected empty method annotations for annotations directory at offset %x.",
+ orig_offset);
+ return false;
+ }
+ return true;
+ }
+ if (orig->size() != output->size()) {
+ *error_msg = StringPrintf(
+ "Mismatched method annotations size for annotations directory at offset %x: %zu vs %zu.",
+ orig_offset,
+ orig->size(),
+ output->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig->size(); ++i) {
+ dex_ir::MethodAnnotation* orig_method = (*orig)[i].get();
+ dex_ir::MethodAnnotation* output_method = (*output)[i].get();
+ if (orig_method->GetMethodId()->GetIndex() != output_method->GetMethodId()->GetIndex()) {
+ *error_msg = StringPrintf(
+ "Mismatched method annotation index for annotations directory at offset %x: %u vs %u.",
+ orig_offset,
+ orig_method->GetMethodId()->GetIndex(),
+ output_method->GetMethodId()->GetIndex());
+ return false;
+ }
+ if (!VerifyAnnotationSet(orig_method->GetAnnotationSetItem(),
+ output_method->GetAnnotationSetItem(),
+ error_msg)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyParameterAnnotations(dex_ir::ParameterAnnotationVector* orig,
+ dex_ir::ParameterAnnotationVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig == nullptr || output == nullptr) {
+ if (orig != output) {
+ *error_msg = StringPrintf(
+ "Found unexpected empty parameter annotations for annotations directory at offset %x.",
+ orig_offset);
+ return false;
+ }
+ return true;
+ }
+ if (orig->size() != output->size()) {
+ *error_msg = StringPrintf(
+ "Mismatched parameter annotations size for annotations directory at offset %x: %zu vs %zu.",
+ orig_offset,
+ orig->size(),
+ output->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig->size(); ++i) {
+ dex_ir::ParameterAnnotation* orig_param = (*orig)[i].get();
+ dex_ir::ParameterAnnotation* output_param = (*output)[i].get();
+ if (orig_param->GetMethodId()->GetIndex() != output_param->GetMethodId()->GetIndex()) {
+ *error_msg = StringPrintf(
+ "Mismatched parameter annotation index for annotations directory at offset %x: %u vs %u.",
+ orig_offset,
+ orig_param->GetMethodId()->GetIndex(),
+ output_param->GetMethodId()->GetIndex());
+ return false;
+ }
+ if (!VerifyAnnotationSetRefList(orig_param->GetAnnotations(),
+ output_param->GetAnnotations(),
+ error_msg)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyAnnotationSetRefList(dex_ir::AnnotationSetRefList* orig,
+ dex_ir::AnnotationSetRefList* output,
+ std::string* error_msg) {
+ std::vector<dex_ir::AnnotationSetItem*>* orig_items = orig->GetItems();
+ std::vector<dex_ir::AnnotationSetItem*>* output_items = output->GetItems();
+ if (orig_items->size() != output_items->size()) {
+ *error_msg = StringPrintf(
+ "Mismatched annotation set ref list size at offset %x: %zu vs %zu.",
+ orig->GetOffset(),
+ orig_items->size(),
+ output_items->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig_items->size(); ++i) {
+ if (!VerifyAnnotationSet((*orig_items)[i], (*output_items)[i], error_msg)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyAnnotationSet(dex_ir::AnnotationSetItem* orig,
+ dex_ir::AnnotationSetItem* output,
+ std::string* error_msg) {
+ if (orig == nullptr || output == nullptr) {
+ if (orig != output) {
+ *error_msg = "Found unexpected empty annotation set.";
+ return false;
+ }
+ return true;
+ }
+ std::vector<dex_ir::AnnotationItem*>* orig_items = orig->GetItems();
+ std::vector<dex_ir::AnnotationItem*>* output_items = output->GetItems();
+ if (orig_items->size() != output_items->size()) {
+ *error_msg = StringPrintf("Mismatched size for annotation set at offset %x: %zu vs %zu.",
+ orig->GetOffset(),
+ orig_items->size(),
+ output_items->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig_items->size(); ++i) {
+ if (!VerifyAnnotation((*orig_items)[i], (*output_items)[i], error_msg)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyAnnotation(dex_ir::AnnotationItem* orig,
+ dex_ir::AnnotationItem* output,
+ std::string* error_msg) {
+ if (orig->GetVisibility() != output->GetVisibility()) {
+ *error_msg = StringPrintf("Mismatched visibility for annotation at offset %x: %u vs %u.",
+ orig->GetOffset(),
+ orig->GetVisibility(),
+ output->GetVisibility());
+ return false;
+ }
+ return VerifyEncodedAnnotation(orig->GetAnnotation(),
+ output->GetAnnotation(),
+ orig->GetOffset(),
+ error_msg);
+}
+
+bool VerifyEncodedAnnotation(dex_ir::EncodedAnnotation* orig,
+ dex_ir::EncodedAnnotation* output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig->GetType()->GetIndex() != output->GetType()->GetIndex()) {
+ *error_msg = StringPrintf(
+ "Mismatched encoded annotation type for annotation at offset %x: %u vs %u.",
+ orig_offset,
+ orig->GetType()->GetIndex(),
+ output->GetType()->GetIndex());
+ return false;
+ }
+ dex_ir::AnnotationElementVector* orig_elements = orig->GetAnnotationElements();
+ dex_ir::AnnotationElementVector* output_elements = output->GetAnnotationElements();
+ if (orig_elements->size() != output_elements->size()) {
+ *error_msg = StringPrintf(
+ "Mismatched encoded annotation size for annotation at offset %x: %zu vs %zu.",
+ orig_offset,
+ orig_elements->size(),
+ output_elements->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig_elements->size(); ++i) {
+ if (!VerifyAnnotationElement((*orig_elements)[i].get(),
+ (*output_elements)[i].get(),
+ orig_offset,
+ error_msg)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyAnnotationElement(dex_ir::AnnotationElement* orig,
+ dex_ir::AnnotationElement* output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig->GetName()->GetIndex() != output->GetName()->GetIndex()) {
+ *error_msg = StringPrintf(
+ "Mismatched annotation element name for annotation at offset %x: %u vs %u.",
+ orig_offset,
+ orig->GetName()->GetIndex(),
+ output->GetName()->GetIndex());
+ return false;
+ }
+ return VerifyEncodedValue(orig->GetValue(), output->GetValue(), orig_offset, error_msg);
+}
+
+bool VerifyEncodedValue(dex_ir::EncodedValue* orig,
+ dex_ir::EncodedValue* output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig->Type() != output->Type()) {
+ *error_msg = StringPrintf(
+ "Mismatched encoded value type for annotation or encoded array at offset %x: %d vs %d.",
+ orig_offset,
+ orig->Type(),
+ output->Type());
+ return false;
+ }
+ switch (orig->Type()) {
+ case DexFile::kDexAnnotationByte:
+ if (orig->GetByte() != output->GetByte()) {
+ *error_msg = StringPrintf("Mismatched encoded byte for annotation at offset %x: %d vs %d.",
+ orig_offset,
+ orig->GetByte(),
+ output->GetByte());
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationShort:
+ if (orig->GetShort() != output->GetShort()) {
+ *error_msg = StringPrintf("Mismatched encoded short for annotation at offset %x: %d vs %d.",
+ orig_offset,
+ orig->GetShort(),
+ output->GetShort());
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationChar:
+ if (orig->GetChar() != output->GetChar()) {
+ *error_msg = StringPrintf("Mismatched encoded char for annotation at offset %x: %c vs %c.",
+ orig_offset,
+ orig->GetChar(),
+ output->GetChar());
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationInt:
+ if (orig->GetInt() != output->GetInt()) {
+ *error_msg = StringPrintf("Mismatched encoded int for annotation at offset %x: %d vs %d.",
+ orig_offset,
+ orig->GetInt(),
+ output->GetInt());
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationLong:
+ if (orig->GetLong() != output->GetLong()) {
+ *error_msg = StringPrintf(
+ "Mismatched encoded long for annotation at offset %x: %" PRId64 " vs %" PRId64 ".",
+ orig_offset,
+ orig->GetLong(),
+ output->GetLong());
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationFloat:
+ // The float value is encoded, so compare as if it's an int.
+ if (orig->GetInt() != output->GetInt()) {
+ *error_msg = StringPrintf(
+ "Mismatched encoded float for annotation at offset %x: %x (encoded) vs %x (encoded).",
+ orig_offset,
+ orig->GetInt(),
+ output->GetInt());
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationDouble:
+ // The double value is encoded, so compare as if it's a long.
+ if (orig->GetLong() != output->GetLong()) {
+ *error_msg = StringPrintf(
+ "Mismatched encoded double for annotation at offset %x: %" PRIx64
+ " (encoded) vs %" PRIx64 " (encoded).",
+ orig_offset,
+ orig->GetLong(),
+ output->GetLong());
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationString:
+ if (orig->GetStringId()->GetIndex() != output->GetStringId()->GetIndex()) {
+ *error_msg = StringPrintf(
+ "Mismatched encoded string for annotation at offset %x: %s vs %s.",
+ orig_offset,
+ orig->GetStringId()->Data(),
+ output->GetStringId()->Data());
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationType:
+ if (orig->GetTypeId()->GetIndex() != output->GetTypeId()->GetIndex()) {
+ *error_msg = StringPrintf("Mismatched encoded type for annotation at offset %x: %u vs %u.",
+ orig_offset,
+ orig->GetTypeId()->GetIndex(),
+ output->GetTypeId()->GetIndex());
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationField:
+ case DexFile::kDexAnnotationEnum:
+ if (orig->GetFieldId()->GetIndex() != output->GetFieldId()->GetIndex()) {
+ *error_msg = StringPrintf("Mismatched encoded field for annotation at offset %x: %u vs %u.",
+ orig_offset,
+ orig->GetFieldId()->GetIndex(),
+ output->GetFieldId()->GetIndex());
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationMethod:
+ if (orig->GetMethodId()->GetIndex() != output->GetMethodId()->GetIndex()) {
+ *error_msg = StringPrintf(
+ "Mismatched encoded method for annotation at offset %x: %u vs %u.",
+ orig_offset,
+ orig->GetMethodId()->GetIndex(),
+ output->GetMethodId()->GetIndex());
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationArray:
+ if (!VerifyEncodedArray(orig->GetEncodedArray(), output->GetEncodedArray(), error_msg)) {
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationAnnotation:
+ if (!VerifyEncodedAnnotation(orig->GetEncodedAnnotation(),
+ output->GetEncodedAnnotation(),
+ orig_offset,
+ error_msg)) {
+ return false;
+ }
+ break;
+ case DexFile::kDexAnnotationNull:
+ break;
+ case DexFile::kDexAnnotationBoolean:
+ if (orig->GetBoolean() != output->GetBoolean()) {
+ *error_msg = StringPrintf(
+ "Mismatched encoded boolean for annotation at offset %x: %d vs %d.",
+ orig_offset,
+ orig->GetBoolean(),
+ output->GetBoolean());
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+bool VerifyEncodedArray(dex_ir::EncodedArrayItem* orig,
+ dex_ir::EncodedArrayItem* output,
+ std::string* error_msg) {
+ if (orig == nullptr || output == nullptr) {
+ if (orig != output) {
+ *error_msg = "Found unexpected empty encoded array.";
+ return false;
+ }
+ return true;
+ }
+ dex_ir::EncodedValueVector* orig_vector = orig->GetEncodedValues();
+ dex_ir::EncodedValueVector* output_vector = output->GetEncodedValues();
+ if (orig_vector->size() != output_vector->size()) {
+ *error_msg = StringPrintf("Mismatched size for encoded array at offset %x: %zu vs %zu.",
+ orig->GetOffset(),
+ orig_vector->size(),
+ output_vector->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig_vector->size(); ++i) {
+ if (!VerifyEncodedValue((*orig_vector)[i].get(),
+ (*output_vector)[i].get(),
+ orig->GetOffset(),
+ error_msg)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyClassData(dex_ir::ClassData* orig, dex_ir::ClassData* output, std::string* error_msg) {
+ if (orig == nullptr || output == nullptr) {
+ if (orig != output) {
+ *error_msg = "Found unexpected empty class data.";
+ return false;
+ }
+ return true;
+ }
+ if (!VerifyFields(orig->StaticFields(), output->StaticFields(), orig->GetOffset(), error_msg)) {
+ return false;
+ }
+ if (!VerifyFields(orig->InstanceFields(),
+ output->InstanceFields(),
+ orig->GetOffset(),
+ error_msg)) {
+ return false;
+ }
+ if (!VerifyMethods(orig->DirectMethods(),
+ output->DirectMethods(),
+ orig->GetOffset(),
+ error_msg)) {
+ return false;
+ }
+ return VerifyMethods(orig->VirtualMethods(),
+ output->VirtualMethods(),
+ orig->GetOffset(),
+ error_msg);
+}
+
+bool VerifyFields(dex_ir::FieldItemVector* orig,
+ dex_ir::FieldItemVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig->size() != output->size()) {
+ *error_msg = StringPrintf("Mismatched fields size for class data at offset %x: %zu vs %zu.",
+ orig_offset,
+ orig->size(),
+ output->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig->size(); ++i) {
+ dex_ir::FieldItem* orig_field = (*orig)[i].get();
+ dex_ir::FieldItem* output_field = (*output)[i].get();
+ if (orig_field->GetFieldId()->GetIndex() != output_field->GetFieldId()->GetIndex()) {
+ *error_msg = StringPrintf("Mismatched field index for class data at offset %x: %u vs %u.",
+ orig_offset,
+ orig_field->GetFieldId()->GetIndex(),
+ output_field->GetFieldId()->GetIndex());
+ return false;
+ }
+ if (orig_field->GetAccessFlags() != output_field->GetAccessFlags()) {
+ *error_msg = StringPrintf(
+ "Mismatched field access flags for class data at offset %x: %u vs %u.",
+ orig_offset,
+ orig_field->GetAccessFlags(),
+ output_field->GetAccessFlags());
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyMethods(dex_ir::MethodItemVector* orig,
+ dex_ir::MethodItemVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig->size() != output->size()) {
+ *error_msg = StringPrintf("Mismatched methods size for class data at offset %x: %zu vs %zu.",
+ orig_offset,
+ orig->size(),
+ output->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig->size(); ++i) {
+ dex_ir::MethodItem* orig_method = (*orig)[i].get();
+ dex_ir::MethodItem* output_method = (*output)[i].get();
+ if (orig_method->GetMethodId()->GetIndex() != output_method->GetMethodId()->GetIndex()) {
+ *error_msg = StringPrintf("Mismatched method index for class data at offset %x: %u vs %u.",
+ orig_offset,
+ orig_method->GetMethodId()->GetIndex(),
+ output_method->GetMethodId()->GetIndex());
+ return false;
+ }
+ if (orig_method->GetAccessFlags() != output_method->GetAccessFlags()) {
+ *error_msg = StringPrintf(
+ "Mismatched method access flags for class data at offset %x: %u vs %u.",
+ orig_offset,
+ orig_method->GetAccessFlags(),
+ output_method->GetAccessFlags());
+ return false;
+ }
+ if (!VerifyCode(orig_method->GetCodeItem(), output_method->GetCodeItem(), error_msg)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyCode(dex_ir::CodeItem* orig, dex_ir::CodeItem* output, std::string* error_msg) {
+ if (orig == nullptr || output == nullptr) {
+ if (orig != output) {
+ *error_msg = "Found unexpected empty code item.";
+ return false;
+ }
+ return true;
+ }
+ if (orig->RegistersSize() != output->RegistersSize()) {
+ *error_msg = StringPrintf("Mismatched registers size for code item at offset %x: %u vs %u.",
+ orig->GetOffset(),
+ orig->RegistersSize(),
+ output->RegistersSize());
+ return false;
+ }
+ if (orig->InsSize() != output->InsSize()) {
+ *error_msg = StringPrintf("Mismatched ins size for code item at offset %x: %u vs %u.",
+ orig->GetOffset(),
+ orig->InsSize(),
+ output->InsSize());
+ return false;
+ }
+ if (orig->OutsSize() != output->OutsSize()) {
+ *error_msg = StringPrintf("Mismatched outs size for code item at offset %x: %u vs %u.",
+ orig->GetOffset(),
+ orig->OutsSize(),
+ output->OutsSize());
+ return false;
+ }
+ if (orig->TriesSize() != output->TriesSize()) {
+ *error_msg = StringPrintf("Mismatched tries size for code item at offset %x: %u vs %u.",
+ orig->GetOffset(),
+ orig->TriesSize(),
+ output->TriesSize());
+ return false;
+ }
+ if (!VerifyDebugInfo(orig->DebugInfo(), output->DebugInfo(), error_msg)) {
+ return false;
+ }
+ if (orig->InsnsSize() != output->InsnsSize()) {
+ *error_msg = StringPrintf("Mismatched insns size for code item at offset %x: %u vs %u.",
+ orig->GetOffset(),
+ orig->InsnsSize(),
+ output->InsnsSize());
+ return false;
+ }
+ if (memcmp(orig->Insns(), output->Insns(), orig->InsnsSize()) != 0) {
+ *error_msg = StringPrintf("Mismatched insns for code item at offset %x.",
+ orig->GetOffset());
+ return false;
+ }
+ if (!VerifyTries(orig->Tries(), output->Tries(), orig->GetOffset(), error_msg)) {
+ return false;
+ }
+ return VerifyHandlers(orig->Handlers(), output->Handlers(), orig->GetOffset(), error_msg);
+}
+
+bool VerifyDebugInfo(dex_ir::DebugInfoItem* orig,
+ dex_ir::DebugInfoItem* output,
+ std::string* error_msg) {
+ if (orig == nullptr || output == nullptr) {
+ if (orig != output) {
+ *error_msg = "Found unexpected empty debug info.";
+ return false;
+ }
+ return true;
+ }
+ if (!VerifyPositionInfo(orig->GetPositionInfo(),
+ output->GetPositionInfo(),
+ orig->GetOffset(),
+ error_msg)) {
+ return false;
+ }
+ return VerifyLocalInfo(orig->GetLocalInfo(),
+ output->GetLocalInfo(),
+ orig->GetOffset(),
+ error_msg);
+}
+
+bool VerifyPositionInfo(dex_ir::PositionInfoVector& orig,
+ dex_ir::PositionInfoVector& output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig.size() != output.size()) {
+ *error_msg = StringPrintf(
+ "Mismatched number of positions for debug info at offset %x: %zu vs %zu.",
+ orig_offset,
+ orig.size(),
+ output.size());
+ return false;
+ }
+ for (size_t i = 0; i < orig.size(); ++i) {
+ if (orig[i]->address_ != output[i]->address_) {
+ *error_msg = StringPrintf(
+ "Mismatched position address for debug info at offset %x: %u vs %u.",
+ orig_offset,
+ orig[i]->address_,
+ output[i]->address_);
+ return false;
+ }
+ if (orig[i]->line_ != output[i]->line_) {
+ *error_msg = StringPrintf("Mismatched position line for debug info at offset %x: %u vs %u.",
+ orig_offset,
+ orig[i]->line_,
+ output[i]->line_);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyLocalInfo(dex_ir::LocalInfoVector& orig,
+ dex_ir::LocalInfoVector& output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig.size() != output.size()) {
+ *error_msg = StringPrintf(
+ "Mismatched number of locals for debug info at offset %x: %zu vs %zu.",
+ orig_offset,
+ orig.size(),
+ output.size());
+ return false;
+ }
+ for (size_t i = 0; i < orig.size(); ++i) {
+ if (orig[i]->name_ != output[i]->name_) {
+ *error_msg = StringPrintf("Mismatched local name for debug info at offset %x: %s vs %s.",
+ orig_offset,
+ orig[i]->name_.c_str(),
+ output[i]->name_.c_str());
+ return false;
+ }
+ if (orig[i]->descriptor_ != output[i]->descriptor_) {
+ *error_msg = StringPrintf(
+ "Mismatched local descriptor for debug info at offset %x: %s vs %s.",
+ orig_offset,
+ orig[i]->descriptor_.c_str(),
+ output[i]->descriptor_.c_str());
+ return false;
+ }
+ if (orig[i]->signature_ != output[i]->signature_) {
+ *error_msg = StringPrintf("Mismatched local signature for debug info at offset %x: %s vs %s.",
+ orig_offset,
+ orig[i]->signature_.c_str(),
+ output[i]->signature_.c_str());
+ return false;
+ }
+ if (orig[i]->start_address_ != output[i]->start_address_) {
+ *error_msg = StringPrintf(
+ "Mismatched local start address for debug info at offset %x: %u vs %u.",
+ orig_offset,
+ orig[i]->start_address_,
+ output[i]->start_address_);
+ return false;
+ }
+ if (orig[i]->end_address_ != output[i]->end_address_) {
+ *error_msg = StringPrintf(
+ "Mismatched local end address for debug info at offset %x: %u vs %u.",
+ orig_offset,
+ orig[i]->end_address_,
+ output[i]->end_address_);
+ return false;
+ }
+ if (orig[i]->reg_ != output[i]->reg_) {
+ *error_msg = StringPrintf("Mismatched local reg for debug info at offset %x: %u vs %u.",
+ orig_offset,
+ orig[i]->reg_,
+ output[i]->reg_);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyTries(dex_ir::TryItemVector* orig,
+ dex_ir::TryItemVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig == nullptr || output == nullptr) {
+ if (orig != output) {
+ *error_msg = "Found unexpected empty try items.";
+ return false;
+ }
+ return true;
+ }
+ if (orig->size() != output->size()) {
+ *error_msg = StringPrintf("Mismatched tries size for code item at offset %x: %zu vs %zu.",
+ orig_offset,
+ orig->size(),
+ output->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig->size(); ++i) {
+ const dex_ir::TryItem* orig_try = (*orig)[i].get();
+ const dex_ir::TryItem* output_try = (*output)[i].get();
+ if (orig_try->StartAddr() != output_try->StartAddr()) {
+ *error_msg = StringPrintf(
+ "Mismatched try item start addr for code item at offset %x: %u vs %u.",
+ orig_offset,
+ orig_try->StartAddr(),
+ output_try->StartAddr());
+ return false;
+ }
+ if (orig_try->InsnCount() != output_try->InsnCount()) {
+ *error_msg = StringPrintf(
+ "Mismatched try item insn count for code item at offset %x: %u vs %u.",
+ orig_offset,
+ orig_try->InsnCount(),
+ output_try->InsnCount());
+ return false;
+ }
+ if (!VerifyHandler(orig_try->GetHandlers(),
+ output_try->GetHandlers(),
+ orig_offset,
+ error_msg)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyHandlers(dex_ir::CatchHandlerVector* orig,
+ dex_ir::CatchHandlerVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ if (orig == nullptr || output == nullptr) {
+ if (orig != output) {
+ *error_msg = "Found unexpected empty catch handlers.";
+ return false;
+ }
+ return true;
+ }
+ if (orig->size() != output->size()) {
+ *error_msg = StringPrintf(
+ "Mismatched catch handlers size for code item at offset %x: %zu vs %zu.",
+ orig_offset,
+ orig->size(),
+ output->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig->size(); ++i) {
+ if (!VerifyHandler((*orig)[i].get(), (*output)[i].get(), orig_offset, error_msg)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VerifyHandler(const dex_ir::CatchHandler* orig,
+ const dex_ir::CatchHandler* output,
+ uint32_t orig_offset,
+ std::string* error_msg) {
+ dex_ir::TypeAddrPairVector* orig_handlers = orig->GetHandlers();
+ dex_ir::TypeAddrPairVector* output_handlers = output->GetHandlers();
+ if (orig_handlers->size() != output_handlers->size()) {
+ *error_msg = StringPrintf(
+ "Mismatched number of catch handlers for code item at offset %x: %zu vs %zu.",
+ orig_offset,
+ orig_handlers->size(),
+ output_handlers->size());
+ return false;
+ }
+ for (size_t i = 0; i < orig_handlers->size(); ++i) {
+ const dex_ir::TypeAddrPair* orig_handler = (*orig_handlers)[i].get();
+ const dex_ir::TypeAddrPair* output_handler = (*output_handlers)[i].get();
+ if (orig_handler->GetTypeId() == nullptr || output_handler->GetTypeId() == nullptr) {
+ if (orig_handler->GetTypeId() != output_handler->GetTypeId()) {
+ *error_msg = StringPrintf(
+ "Found unexpected catch all catch handler for code item at offset %x.",
+ orig_offset);
+ return false;
+ }
+ } else if (orig_handler->GetTypeId()->GetIndex() != output_handler->GetTypeId()->GetIndex()) {
+ *error_msg = StringPrintf(
+ "Mismatched catch handler type for code item at offset %x: %u vs %u.",
+ orig_offset,
+ orig_handler->GetTypeId()->GetIndex(),
+ output_handler->GetTypeId()->GetIndex());
+ return false;
+ }
+ if (orig_handler->GetAddress() != output_handler->GetAddress()) {
+ *error_msg = StringPrintf(
+ "Mismatched catch handler address for code item at offset %x: %u vs %u.",
+ orig_offset,
+ orig_handler->GetAddress(),
+ output_handler->GetAddress());
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace art
diff --git a/dexlayout/dex_verify.h b/dexlayout/dex_verify.h
index a19431c..58c95d6 100644
--- a/dexlayout/dex_verify.h
+++ b/dexlayout/dex_verify.h
@@ -24,12 +24,12 @@
#include "dex_ir.h"
namespace art {
-
// Check that the output dex file contains the same data as the original.
// Compares the dex IR of both dex files. Allows the dex files to have different layouts.
bool VerifyOutputDexFile(dex_ir::Header* orig_header,
dex_ir::Header* output_header,
std::string* error_msg);
+
template<class T> bool VerifyIds(std::vector<std::unique_ptr<T>>& orig,
std::vector<std::unique_ptr<T>>& output,
const char* section_name,
@@ -39,8 +39,87 @@
bool VerifyId(dex_ir::ProtoId* orig, dex_ir::ProtoId* output, std::string* error_msg);
bool VerifyId(dex_ir::FieldId* orig, dex_ir::FieldId* output, std::string* error_msg);
bool VerifyId(dex_ir::MethodId* orig, dex_ir::MethodId* output, std::string* error_msg);
+
+bool VerifyClassDefs(std::vector<std::unique_ptr<dex_ir::ClassDef>>& orig,
+ std::vector<std::unique_ptr<dex_ir::ClassDef>>& output,
+ std::string* error_msg);
+bool VerifyClassDef(dex_ir::ClassDef* orig, dex_ir::ClassDef* output, std::string* error_msg);
+
bool VerifyTypeList(const dex_ir::TypeList* orig, const dex_ir::TypeList* output);
+bool VerifyAnnotationsDirectory(dex_ir::AnnotationsDirectoryItem* orig,
+ dex_ir::AnnotationsDirectoryItem* output,
+ std::string* error_msg);
+bool VerifyFieldAnnotations(dex_ir::FieldAnnotationVector* orig,
+ dex_ir::FieldAnnotationVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyMethodAnnotations(dex_ir::MethodAnnotationVector* orig,
+ dex_ir::MethodAnnotationVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyParameterAnnotations(dex_ir::ParameterAnnotationVector* orig,
+ dex_ir::ParameterAnnotationVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyAnnotationSetRefList(dex_ir::AnnotationSetRefList* orig,
+ dex_ir::AnnotationSetRefList* output,
+ std::string* error_msg);
+bool VerifyAnnotationSet(dex_ir::AnnotationSetItem* orig,
+ dex_ir::AnnotationSetItem* output,
+ std::string* error_msg);
+bool VerifyAnnotation(dex_ir::AnnotationItem* orig,
+ dex_ir::AnnotationItem* output,
+ std::string* error_msg);
+bool VerifyEncodedAnnotation(dex_ir::EncodedAnnotation* orig,
+ dex_ir::EncodedAnnotation* output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyAnnotationElement(dex_ir::AnnotationElement* orig,
+ dex_ir::AnnotationElement* output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyEncodedValue(dex_ir::EncodedValue* orig,
+ dex_ir::EncodedValue* output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyEncodedArray(dex_ir::EncodedArrayItem* orig,
+ dex_ir::EncodedArrayItem* output,
+ std::string* error_msg);
+
+bool VerifyClassData(dex_ir::ClassData* orig, dex_ir::ClassData* output, std::string* error_msg);
+bool VerifyFields(dex_ir::FieldItemVector* orig,
+ dex_ir::FieldItemVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyMethods(dex_ir::MethodItemVector* orig,
+ dex_ir::MethodItemVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyCode(dex_ir::CodeItem* orig, dex_ir::CodeItem* output, std::string* error_msg);
+bool VerifyDebugInfo(dex_ir::DebugInfoItem* orig,
+ dex_ir::DebugInfoItem* output,
+ std::string* error_msg);
+bool VerifyPositionInfo(dex_ir::PositionInfoVector& orig,
+ dex_ir::PositionInfoVector& output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyLocalInfo(dex_ir::LocalInfoVector& orig,
+ dex_ir::LocalInfoVector& output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyTries(dex_ir::TryItemVector* orig,
+ dex_ir::TryItemVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyHandlers(dex_ir::CatchHandlerVector* orig,
+ dex_ir::CatchHandlerVector* output,
+ uint32_t orig_offset,
+ std::string* error_msg);
+bool VerifyHandler(const dex_ir::CatchHandler* orig,
+ const dex_ir::CatchHandler* output,
+ uint32_t orig_offset,
+ std::string* error_msg);
} // namespace art
#endif // ART_DEXLAYOUT_DEX_VERIFY_H_
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index a310424..615bcf9 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -1369,10 +1369,11 @@
}
// Interfaces.
- const dex_ir::TypeIdVector* interfaces = class_def->Interfaces();
+ const dex_ir::TypeList* interfaces = class_def->Interfaces();
if (interfaces != nullptr) {
- for (uint32_t i = 0; i < interfaces->size(); i++) {
- DumpInterface((*interfaces)[i], i);
+ const dex_ir::TypeIdVector* interfaces_vector = interfaces->GetTypeList();
+ for (uint32_t i = 0; i < interfaces_vector->size(); i++) {
+ DumpInterface((*interfaces_vector)[i], i);
} // for
}