diff options
| -rw-r--r-- | dexlayout/dex_ir_builder.cc | 60 | ||||
| -rw-r--r-- | dexlayout/dexlayout_test.cc | 15 | ||||
| -rw-r--r-- | libdexfile/dex/class_accessor.h | 4 | ||||
| -rw-r--r-- | libdexfile/dex/dex_file_verifier_test.cc | 55 |
4 files changed, 54 insertions, 80 deletions
diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc index a04a2349c4..a83a46b7e2 100644 --- a/dexlayout/dex_ir_builder.cc +++ b/dexlayout/dex_ir_builder.cc @@ -21,6 +21,7 @@ #include "dex_ir_builder.h" +#include "dex/class_accessor-inl.h" #include "dex/code_item_accessors-inl.h" #include "dex/dex_file_exception_helpers.h" #include "dexlayout.h" @@ -162,7 +163,7 @@ class BuilderMaps { const DexFile::CodeItem* disk_code_item, uint32_t offset, uint32_t dex_method_index); - ClassData* CreateClassData(const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset); + ClassData* CreateClassData(const DexFile& dex_file, const DexFile::ClassDef& class_def); void AddAnnotationsFromMapListSection(const DexFile& dex_file, uint32_t start_offset, @@ -197,7 +198,7 @@ class BuilderMaps { uint8_t length, EncodedValue* item); - MethodItem GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii); + MethodItem GenerateMethodItem(const DexFile& dex_file, const ClassAccessor::Method& method); ParameterAnnotation* GenerateParameterAnnotation( const DexFile& dex_file, @@ -488,8 +489,7 @@ void BuilderMaps::CreateClassDef(const DexFile& dex_file, uint32_t i) { const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def); EncodedArrayItem* static_values = CreateEncodedArrayItem(dex_file, static_data, disk_class_def.static_values_off_); - ClassData* class_data = CreateClassData( - dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_); + ClassData* class_data = CreateClassData(dex_file, disk_class_def); CreateAndAddIndexedItem(header_->ClassDefs(), header_->ClassDefs().GetOffset() + i * ClassDef::ItemSize(), i, @@ -894,36 +894,43 @@ CodeItem* BuilderMaps::DedupeOrCreateCodeItem(const DexFile& dex_file, return code_item; } -ClassData* BuilderMaps::CreateClassData( - const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) { +ClassData* BuilderMaps::CreateClassData(const DexFile& dex_file, + const DexFile::ClassDef& class_def) { // Read the fields and methods defined by the class, resolving the circular reference from those // to classes by setting class at the same time. + const uint32_t offset = class_def.class_data_off_; ClassData* class_data = class_datas_map_.GetExistingObject(offset); - if (class_data == nullptr && encoded_data != nullptr) { - ClassDataItemIterator cdii(dex_file, encoded_data); + if (class_data == nullptr && offset != 0u) { + ClassAccessor accessor(dex_file, class_def); // Static fields. FieldItemVector* static_fields = new FieldItemVector(); - for (; cdii.HasNextStaticField(); cdii.Next()) { - FieldId* field_item = header_->FieldIds()[cdii.GetMemberIndex()]; - uint32_t access_flags = cdii.GetRawMemberAccessFlags(); + for (const ClassAccessor::Field& field : accessor.GetStaticFields()) { + FieldId* field_item = header_->FieldIds()[field.GetIndex()]; + uint32_t access_flags = field.GetRawAccessFlags(); static_fields->emplace_back(access_flags, field_item); } - // Instance fields. FieldItemVector* instance_fields = new FieldItemVector(); - for (; cdii.HasNextInstanceField(); cdii.Next()) { - FieldId* field_item = header_->FieldIds()[cdii.GetMemberIndex()]; - uint32_t access_flags = cdii.GetRawMemberAccessFlags(); + for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) { + FieldId* field_item = header_->FieldIds()[field.GetIndex()]; + uint32_t access_flags = field.GetRawAccessFlags(); instance_fields->emplace_back(access_flags, field_item); } // Direct methods. MethodItemVector* direct_methods = new MethodItemVector(); - for (; cdii.HasNextDirectMethod(); cdii.Next()) { - direct_methods->push_back(GenerateMethodItem(dex_file, cdii)); + auto direct_methods_it = accessor.GetDirectMethods(); + for (auto it = direct_methods_it.begin(); it != direct_methods_it.end(); ++it) { + direct_methods->push_back(GenerateMethodItem(dex_file, *it)); } // Virtual methods. MethodItemVector* virtual_methods = new MethodItemVector(); - for (; cdii.HasNextVirtualMethod(); cdii.Next()) { - virtual_methods->push_back(GenerateMethodItem(dex_file, cdii)); + auto virtual_methods_it = accessor.GetVirtualMethods(); + const uint8_t* last_data_ptr; + for (auto it = virtual_methods_it.begin(); ; ++it) { + if (it == virtual_methods_it.end()) { + last_data_ptr = it->GetDataPointer(); + break; + } + virtual_methods->push_back(GenerateMethodItem(dex_file, *it)); } class_data = class_datas_map_.CreateAndAddItem(header_->ClassDatas(), eagerly_assign_offsets_, @@ -932,7 +939,7 @@ ClassData* BuilderMaps::CreateClassData( instance_fields, direct_methods, virtual_methods); - class_data->SetSize(cdii.EndDataPointer() - encoded_data); + class_data->SetSize(last_data_ptr - dex_file.GetClassData(class_def)); } return class_data; } @@ -1168,16 +1175,17 @@ void BuilderMaps::ReadEncodedValue(const DexFile& dex_file, } } -MethodItem BuilderMaps::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) { - MethodId* method_id = header_->MethodIds()[cdii.GetMemberIndex()]; - uint32_t access_flags = cdii.GetRawMemberAccessFlags(); - const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem(); +MethodItem BuilderMaps::GenerateMethodItem(const DexFile& dex_file, + const ClassAccessor::Method& method) { + MethodId* method_id = header_->MethodIds()[method.GetIndex()]; + uint32_t access_flags = method.GetRawAccessFlags(); + const DexFile::CodeItem* disk_code_item = method.GetCodeItem(); // Temporary hack to prevent incorrectly deduping code items if they have the same offset since // they may have different debug info streams. CodeItem* code_item = DedupeOrCreateCodeItem(dex_file, disk_code_item, - cdii.GetMethodCodeItemOffset(), - cdii.GetMemberIndex()); + method.GetCodeItemOffset(), + method.GetIndex()); return MethodItem(access_flags, method_id, code_item); } diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc index 2b1352db16..a20930b28b 100644 --- a/dexlayout/dexlayout_test.cc +++ b/dexlayout/dexlayout_test.cc @@ -26,6 +26,7 @@ #include "common_runtime_test.h" #include "dex/art_dex_file_loader.h" #include "dex/base64_test_util.h" +#include "dex/class_accessor-inl.h" #include "dex/code_item_accessors-inl.h" #include "dex/dex_file-inl.h" #include "dex/dex_file_loader.h" @@ -682,16 +683,9 @@ TEST_F(DexLayoutTest, CodeItemOverrun) { MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [] (DexFile* dex) { bool mutated_successfully = false; // Change the dex instructions to make an opcode that spans past the end of the code item. - for (size_t i = 0; i < dex->NumClassDefs(); ++i) { - const DexFile::ClassDef& def = dex->GetClassDef(i); - const uint8_t* data = dex->GetClassData(def); - if (data == nullptr) { - continue; - } - ClassDataItemIterator it(*dex, data); - it.SkipAllFields(); - while (it.HasNextMethod()) { - DexFile::CodeItem* item = const_cast<DexFile::CodeItem*>(it.GetMethodCodeItem()); + for (ClassAccessor accessor : dex->GetClasses()) { + for (const ClassAccessor::Method& method : accessor.GetMethods()) { + DexFile::CodeItem* item = const_cast<DexFile::CodeItem*>(method.GetCodeItem()); if (item != nullptr) { CodeItemInstructionAccessor instructions(*dex, item); if (instructions.begin() != instructions.end()) { @@ -714,7 +708,6 @@ TEST_F(DexLayoutTest, CodeItemOverrun) { } } } - it.Next(); } } CHECK(mutated_successfully) diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h index 896fcadb10..9b9ac87dee 100644 --- a/libdexfile/dex/class_accessor.h +++ b/libdexfile/dex/class_accessor.h @@ -61,6 +61,10 @@ class ClassAccessor { return dex_file_; } + const uint8_t* GetDataPointer() const { + return ptr_pos_; + } + protected: // Internal data pointer for reading. const DexFile& dex_file_; diff --git a/libdexfile/dex/dex_file_verifier_test.cc b/libdexfile/dex/dex_file_verifier_test.cc index 78b53a0bd4..a22a457dbe 100644 --- a/libdexfile/dex/dex_file_verifier_test.cc +++ b/libdexfile/dex/dex_file_verifier_test.cc @@ -25,6 +25,7 @@ #include "base/leb128.h" #include "base/macros.h" #include "base64_test_util.h" +#include "class_accessor-inl.h" #include "descriptors_names.h" #include "dex_file-inl.h" #include "dex_file_loader.h" @@ -238,27 +239,10 @@ static const char kMethodFlagsTestDex[] = static const uint8_t* FindMethodData(const DexFile* dex_file, const char* name, /*out*/ uint32_t* method_idx = nullptr) { - const DexFile::ClassDef& class_def = dex_file->GetClassDef(0); - const uint8_t* class_data = dex_file->GetClassData(class_def); - - ClassDataItemIterator it(*dex_file, class_data); - - const uint8_t* trailing = class_data; - // Need to manually decode the four entries. DataPointer() doesn't work for this, as the first - // element has already been loaded into the iterator. - DecodeUnsignedLeb128(&trailing); - DecodeUnsignedLeb128(&trailing); - DecodeUnsignedLeb128(&trailing); - DecodeUnsignedLeb128(&trailing); - - // Skip all fields. - while (it.HasNextStaticField() || it.HasNextInstanceField()) { - trailing = it.DataPointer(); - it.Next(); - } + ClassAccessor accessor(*dex_file, dex_file->GetClassDef(0)); - while (it.HasNextMethod()) { - uint32_t method_index = it.GetMemberIndex(); + for (const ClassAccessor::Method& method : accessor.GetMethods()) { + uint32_t method_index = method.GetIndex(); dex::StringIndex name_index = dex_file->GetMethodId(method_index).name_idx_; const DexFile::StringId& string_id = dex_file->GetStringId(name_index); const char* str = dex_file->GetStringData(string_id); @@ -266,12 +250,11 @@ static const uint8_t* FindMethodData(const DexFile* dex_file, if (method_idx != nullptr) { *method_idx = method_index; } - DecodeUnsignedLeb128(&trailing); + // Go back 2 lebs to the access flags. + const uint8_t* trailing = ReverseSearchUnsignedLeb128(method.GetDataPointer()); + trailing = ReverseSearchUnsignedLeb128(trailing); return trailing; } - - trailing = it.DataPointer(); - it.Next(); } return nullptr; @@ -849,31 +832,17 @@ TEST_F(DexFileVerifierTest, MethodAccessFlagsInterfaces) { // is to the access flags, so that the caller doesn't have to handle the leb128-encoded method-index // delta. static const uint8_t* FindFieldData(const DexFile* dex_file, const char* name) { - const DexFile::ClassDef& class_def = dex_file->GetClassDef(0); - const uint8_t* class_data = dex_file->GetClassData(class_def); - - ClassDataItemIterator it(*dex_file, class_data); + ClassAccessor accessor(*dex_file, dex_file->GetClassDef(0)); - const uint8_t* trailing = class_data; - // Need to manually decode the four entries. DataPointer() doesn't work for this, as the first - // element has already been loaded into the iterator. - DecodeUnsignedLeb128(&trailing); - DecodeUnsignedLeb128(&trailing); - DecodeUnsignedLeb128(&trailing); - DecodeUnsignedLeb128(&trailing); - - while (it.HasNextStaticField() || it.HasNextInstanceField()) { - uint32_t field_index = it.GetMemberIndex(); + for (const ClassAccessor::Field& field : accessor.GetFields()) { + uint32_t field_index = field.GetIndex(); dex::StringIndex name_index = dex_file->GetFieldId(field_index).name_idx_; const DexFile::StringId& string_id = dex_file->GetStringId(name_index); const char* str = dex_file->GetStringData(string_id); if (strcmp(name, str) == 0) { - DecodeUnsignedLeb128(&trailing); - return trailing; + // Go to the back of the access flags. + return ReverseSearchUnsignedLeb128(field.GetDataPointer()); } - - trailing = it.DataPointer(); - it.Next(); } return nullptr; |