Refactor ownership in dex_ir
Remove some unnecessary generality, consolidating and simplifying the
interface to Header and moving all the construction code out of dex_ir.
This makes item ownership exclusively controlled by the collections
themselves, preparing for in-place construction.
Bug: 33017139
Test: make -j 40 test-art-host-gtest
Change-Id: Ice461ae89ef9f8bed3350780e8dd6283bc6eca1b
diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc
index 3f5dbcf..00fb0af 100644
--- a/dexlayout/compact_dex_writer.cc
+++ b/dexlayout/compact_dex_writer.cc
@@ -40,9 +40,8 @@
uint32_t CompactDexWriter::WriteDebugInfoOffsetTable(Stream* stream) {
const uint32_t start_offset = stream->Tell();
- const dex_ir::Collections& collections = header_->GetCollections();
// Debug offsets for method indexes. 0 means no debug info.
- std::vector<uint32_t> debug_info_offsets(collections.MethodIdsSize(), 0u);
+ std::vector<uint32_t> debug_info_offsets(header_->MethodIds().Size(), 0u);
static constexpr InvokeType invoke_types[] = {
kDirect,
@@ -50,7 +49,7 @@
};
for (InvokeType invoke_type : invoke_types) {
- for (const std::unique_ptr<dex_ir::ClassDef>& class_def : collections.ClassDefs()) {
+ for (auto& class_def : header_->ClassDefs()) {
// Skip classes that are not defined in this dex file.
dex_ir::ClassData* class_data = class_def->GetClassData();
if (class_data == nullptr) {
@@ -232,14 +231,13 @@
}
void CompactDexWriter::SortDebugInfosByMethodIndex() {
- dex_ir::Collections& collections = header_->GetCollections();
static constexpr InvokeType invoke_types[] = {
kDirect,
kVirtual
};
std::map<const dex_ir::DebugInfoItem*, uint32_t> method_idx_map;
for (InvokeType invoke_type : invoke_types) {
- for (std::unique_ptr<dex_ir::ClassDef>& class_def : collections.ClassDefs()) {
+ for (auto& class_def : header_->ClassDefs()) {
// Skip classes that are not defined in this dex file.
dex_ir::ClassData* class_data = class_def->GetClassData();
if (class_data == nullptr) {
@@ -257,8 +255,8 @@
}
}
}
- std::sort(collections.DebugInfoItems().begin(),
- collections.DebugInfoItems().end(),
+ std::sort(header_->DebugInfoItems().begin(),
+ header_->DebugInfoItems().end(),
[&](const std::unique_ptr<dex_ir::DebugInfoItem>& a,
const std::unique_ptr<dex_ir::DebugInfoItem>& b) {
auto it_a = method_idx_map.find(a.get());
@@ -282,20 +280,19 @@
header.endian_tag_ = header_->EndianTag();
header.link_size_ = header_->LinkSize();
header.link_off_ = header_->LinkOffset();
- const dex_ir::Collections& collections = header_->GetCollections();
- header.map_off_ = collections.MapListOffset();
- header.string_ids_size_ = collections.StringIdsSize();
- header.string_ids_off_ = collections.StringIdsOffset();
- header.type_ids_size_ = collections.TypeIdsSize();
- header.type_ids_off_ = collections.TypeIdsOffset();
- header.proto_ids_size_ = collections.ProtoIdsSize();
- header.proto_ids_off_ = collections.ProtoIdsOffset();
- header.field_ids_size_ = collections.FieldIdsSize();
- header.field_ids_off_ = collections.FieldIdsOffset();
- header.method_ids_size_ = collections.MethodIdsSize();
- header.method_ids_off_ = collections.MethodIdsOffset();
- header.class_defs_size_ = collections.ClassDefsSize();
- header.class_defs_off_ = collections.ClassDefsOffset();
+ header.map_off_ = header_->MapListOffset();
+ header.string_ids_size_ = header_->StringIds().Size();
+ header.string_ids_off_ = header_->StringIds().GetOffset();
+ header.type_ids_size_ = header_->TypeIds().Size();
+ header.type_ids_off_ = header_->TypeIds().GetOffset();
+ header.proto_ids_size_ = header_->ProtoIds().Size();
+ header.proto_ids_off_ = header_->ProtoIds().GetOffset();
+ header.field_ids_size_ = header_->FieldIds().Size();
+ header.field_ids_off_ = header_->FieldIds().GetOffset();
+ header.method_ids_size_ = header_->MethodIds().Size();
+ header.method_ids_off_ = header_->MethodIds().GetOffset();
+ header.class_defs_size_ = header_->ClassDefs().Size();
+ header.class_defs_off_ = header_->ClassDefs().GetOffset();
header.data_size_ = header_->DataSize();
header.data_off_ = header_->DataOffset();
header.owned_data_begin_ = owned_data_begin_;
@@ -332,16 +329,15 @@
}
bool CompactDexWriter::CanGenerateCompactDex(std::string* error_msg) {
- dex_ir::Collections& collections = header_->GetCollections();
static constexpr InvokeType invoke_types[] = {
kDirect,
kVirtual
};
- std::vector<bool> saw_method_id(collections.MethodIdsSize(), false);
- std::vector<dex_ir::CodeItem*> method_id_code_item(collections.MethodIdsSize(), nullptr);
- std::vector<dex_ir::DebugInfoItem*> method_id_debug_info(collections.MethodIdsSize(), nullptr);
+ std::vector<bool> saw_method_id(header_->MethodIds().Size(), false);
+ std::vector<dex_ir::CodeItem*> method_id_code_item(header_->MethodIds().Size(), nullptr);
+ std::vector<dex_ir::DebugInfoItem*> method_id_debug_info(header_->MethodIds().Size(), nullptr);
for (InvokeType invoke_type : invoke_types) {
- for (std::unique_ptr<dex_ir::ClassDef>& class_def : collections.ClassDefs()) {
+ for (auto& class_def : header_->ClassDefs()) {
// Skip classes that are not defined in this dex file.
dex_ir::ClassData* class_data = class_def->GetClassData();
if (class_data == nullptr) {
@@ -407,8 +403,6 @@
// Starting offset is right after the header.
main_stream->Seek(GetHeaderSize());
- dex_ir::Collections& collection = header_->GetCollections();
-
// Based on: https://source.android.com/devices/tech/dalvik/dex-format
// Since the offsets may not be calculated already, the writing must be done in the correct order.
const uint32_t string_ids_offset = main_stream->Tell();
@@ -469,16 +463,16 @@
// Write the map list.
if (compute_offsets_) {
data_stream->AlignTo(SectionAlignment(DexFile::kDexTypeMapList));
- collection.SetMapListOffset(data_stream->Tell());
+ header_->SetMapListOffset(data_stream->Tell());
} else {
- data_stream->Seek(collection.MapListOffset());
+ data_stream->Seek(header_->MapListOffset());
}
// Map items are included in the data section.
GenerateAndWriteMapItems(data_stream);
// Write link data if it exists.
- const std::vector<uint8_t>& link_data = collection.LinkData();
+ const std::vector<uint8_t>& link_data = header_->LinkData();
if (link_data.size() > 0) {
CHECK_EQ(header_->LinkSize(), static_cast<uint32_t>(link_data.size()));
if (compute_offsets_) {
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index 15e3baf..3917847 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -30,873 +30,11 @@
namespace art {
namespace dex_ir {
-static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) {
- uint64_t value = 0;
- for (uint32_t i = 0; i <= length; i++) {
- value |= static_cast<uint64_t>(*(*data)++) << (i * 8);
- }
- if (sign_extend) {
- int shift = (7 - length) * 8;
- return (static_cast<int64_t>(value) << shift) >> shift;
- }
- return value;
-}
-
-static uint32_t GetDebugInfoStreamSize(const uint8_t* debug_info_stream) {
- const uint8_t* stream = debug_info_stream;
- DecodeUnsignedLeb128(&stream); // line_start
- uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
- for (uint32_t i = 0; i < parameters_size; ++i) {
- DecodeUnsignedLeb128P1(&stream); // Parameter name.
- }
-
- for (;;) {
- uint8_t opcode = *stream++;
- switch (opcode) {
- case DexFile::DBG_END_SEQUENCE:
- return stream - debug_info_stream; // end of stream.
- case DexFile::DBG_ADVANCE_PC:
- DecodeUnsignedLeb128(&stream); // addr_diff
- break;
- case DexFile::DBG_ADVANCE_LINE:
- DecodeSignedLeb128(&stream); // line_diff
- break;
- case DexFile::DBG_START_LOCAL:
- DecodeUnsignedLeb128(&stream); // register_num
- DecodeUnsignedLeb128P1(&stream); // name_idx
- DecodeUnsignedLeb128P1(&stream); // type_idx
- break;
- case DexFile::DBG_START_LOCAL_EXTENDED:
- DecodeUnsignedLeb128(&stream); // register_num
- DecodeUnsignedLeb128P1(&stream); // name_idx
- DecodeUnsignedLeb128P1(&stream); // type_idx
- DecodeUnsignedLeb128P1(&stream); // sig_idx
- break;
- case DexFile::DBG_END_LOCAL:
- case DexFile::DBG_RESTART_LOCAL:
- DecodeUnsignedLeb128(&stream); // register_num
- break;
- case DexFile::DBG_SET_PROLOGUE_END:
- case DexFile::DBG_SET_EPILOGUE_BEGIN:
- break;
- case DexFile::DBG_SET_FILE: {
- DecodeUnsignedLeb128P1(&stream); // name_idx
- break;
- }
- default: {
- break;
- }
- }
- }
-}
-
-static bool GetIdFromInstruction(Collections& collections,
- const Instruction* dec_insn,
- std::vector<TypeId*>* type_ids,
- std::vector<StringId*>* string_ids,
- std::vector<MethodId*>* method_ids,
- std::vector<FieldId*>* field_ids) {
- // Determine index and width of the string.
- uint32_t index = 0;
- switch (Instruction::FormatOf(dec_insn->Opcode())) {
- // SOME NOT SUPPORTED:
- // case Instruction::k20bc:
- case Instruction::k21c:
- case Instruction::k35c:
- // case Instruction::k35ms:
- case Instruction::k3rc:
- // case Instruction::k3rms:
- // case Instruction::k35mi:
- // case Instruction::k3rmi:
- case Instruction::k45cc:
- case Instruction::k4rcc:
- index = dec_insn->VRegB();
- break;
- case Instruction::k31c:
- index = dec_insn->VRegB();
- break;
- case Instruction::k22c:
- // case Instruction::k22cs:
- index = dec_insn->VRegC();
- break;
- default:
- break;
- } // switch
-
- // Determine index type, and add reference to the appropriate collection.
- switch (Instruction::IndexTypeOf(dec_insn->Opcode())) {
- case Instruction::kIndexTypeRef:
- if (index < collections.TypeIdsSize()) {
- type_ids->push_back(collections.GetTypeId(index));
- return true;
- }
- break;
- case Instruction::kIndexStringRef:
- if (index < collections.StringIdsSize()) {
- string_ids->push_back(collections.GetStringId(index));
- return true;
- }
- break;
- case Instruction::kIndexMethodRef:
- case Instruction::kIndexMethodAndProtoRef:
- if (index < collections.MethodIdsSize()) {
- method_ids->push_back(collections.GetMethodId(index));
- return true;
- }
- break;
- case Instruction::kIndexFieldRef:
- if (index < collections.FieldIdsSize()) {
- field_ids->push_back(collections.GetFieldId(index));
- return true;
- }
- break;
- case Instruction::kIndexUnknown:
- case Instruction::kIndexNone:
- case Instruction::kIndexVtableOffset:
- case Instruction::kIndexFieldOffset:
- default:
- break;
- } // switch
- return false;
-}
-
-/*
- * Get all the types, strings, methods, and fields referred to from bytecode.
- */
-static bool GetIdsFromByteCode(Collections& collections,
- const CodeItem* code,
- std::vector<TypeId*>* type_ids,
- std::vector<StringId*>* string_ids,
- std::vector<MethodId*>* method_ids,
- std::vector<FieldId*>* field_ids) {
- bool has_id = false;
- IterationRange<DexInstructionIterator> instructions = code->Instructions();
- SafeDexInstructionIterator it(instructions.begin(), instructions.end());
- for (; !it.IsErrorState() && it < instructions.end(); ++it) {
- // In case the instruction goes past the end of the code item, make sure to not process it.
- SafeDexInstructionIterator next = it;
- ++next;
- if (next.IsErrorState()) {
- break;
- }
- has_id |= GetIdFromInstruction(collections,
- &it.Inst(),
- type_ids,
- string_ids,
- method_ids,
- field_ids);
- } // for
- return has_id;
-}
-
-EncodedValue* Collections::ReadEncodedValue(const DexFile& dex_file, const uint8_t** data) {
- const uint8_t encoded_value = *(*data)++;
- const uint8_t type = encoded_value & 0x1f;
- EncodedValue* item = new EncodedValue(type);
- ReadEncodedValue(dex_file, data, type, encoded_value >> 5, item);
- return item;
-}
-
-EncodedValue* Collections::ReadEncodedValue(const DexFile& dex_file,
- const uint8_t** data,
- uint8_t type,
- uint8_t length) {
- EncodedValue* item = new EncodedValue(type);
- ReadEncodedValue(dex_file, data, type, length, item);
- return item;
-}
-
-void Collections::ReadEncodedValue(const DexFile& dex_file,
- const uint8_t** data,
- uint8_t type,
- uint8_t length,
- EncodedValue* item) {
- switch (type) {
- case DexFile::kDexAnnotationByte:
- item->SetByte(static_cast<int8_t>(ReadVarWidth(data, length, false)));
- break;
- case DexFile::kDexAnnotationShort:
- item->SetShort(static_cast<int16_t>(ReadVarWidth(data, length, true)));
- break;
- case DexFile::kDexAnnotationChar:
- item->SetChar(static_cast<uint16_t>(ReadVarWidth(data, length, false)));
- break;
- case DexFile::kDexAnnotationInt:
- item->SetInt(static_cast<int32_t>(ReadVarWidth(data, length, true)));
- break;
- case DexFile::kDexAnnotationLong:
- item->SetLong(static_cast<int64_t>(ReadVarWidth(data, length, true)));
- break;
- case DexFile::kDexAnnotationFloat: {
- // Fill on right.
- union {
- float f;
- uint32_t data;
- } conv;
- conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
- item->SetFloat(conv.f);
- break;
- }
- case DexFile::kDexAnnotationDouble: {
- // Fill on right.
- union {
- double d;
- uint64_t data;
- } conv;
- conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
- item->SetDouble(conv.d);
- break;
- }
- case DexFile::kDexAnnotationMethodType: {
- const uint32_t proto_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
- item->SetProtoId(GetProtoId(proto_index));
- break;
- }
- case DexFile::kDexAnnotationMethodHandle: {
- const uint32_t method_handle_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
- item->SetMethodHandle(GetMethodHandle(method_handle_index));
- break;
- }
- case DexFile::kDexAnnotationString: {
- const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
- item->SetStringId(GetStringId(string_index));
- break;
- }
- case DexFile::kDexAnnotationType: {
- const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
- item->SetTypeId(GetTypeId(string_index));
- break;
- }
- case DexFile::kDexAnnotationField:
- case DexFile::kDexAnnotationEnum: {
- const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
- item->SetFieldId(GetFieldId(field_index));
- break;
- }
- case DexFile::kDexAnnotationMethod: {
- const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
- item->SetMethodId(GetMethodId(method_index));
- break;
- }
- case DexFile::kDexAnnotationArray: {
- EncodedValueVector* values = new EncodedValueVector();
- const uint32_t offset = *data - dex_file.DataBegin();
- const uint32_t size = DecodeUnsignedLeb128(data);
- // Decode all elements.
- for (uint32_t i = 0; i < size; i++) {
- values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, data)));
- }
- EncodedArrayItem* array_item = new EncodedArrayItem(values);
- if (eagerly_assign_offsets_) {
- array_item->SetOffset(offset);
- }
- item->SetEncodedArray(array_item);
- break;
- }
- case DexFile::kDexAnnotationAnnotation: {
- AnnotationElementVector* elements = new AnnotationElementVector();
- const uint32_t type_idx = DecodeUnsignedLeb128(data);
- const uint32_t size = DecodeUnsignedLeb128(data);
- // Decode all name=value pairs.
- for (uint32_t i = 0; i < size; i++) {
- const uint32_t name_index = DecodeUnsignedLeb128(data);
- elements->push_back(std::unique_ptr<AnnotationElement>(
- new AnnotationElement(GetStringId(name_index), ReadEncodedValue(dex_file, data))));
- }
- item->SetEncodedAnnotation(new EncodedAnnotation(GetTypeId(type_idx), elements));
- break;
- }
- case DexFile::kDexAnnotationNull:
- break;
- case DexFile::kDexAnnotationBoolean:
- item->SetBoolean(length != 0);
- break;
- default:
- break;
- }
-}
-
-void Collections::CreateStringId(const DexFile& dex_file, uint32_t i) {
- const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i));
- StringData* string_data = CreateAndAddItem(string_datas_map_,
- string_datas_,
- disk_string_id.string_data_off_,
- dex_file.GetStringData(disk_string_id));
- CreateAndAddIndexedItem(string_ids_,
- StringIdsOffset() + i * StringId::ItemSize(),
- i,
- string_data);
-}
-
-void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) {
- const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i));
- CreateAndAddIndexedItem(type_ids_,
- TypeIdsOffset() + i * TypeId::ItemSize(),
- i,
- GetStringId(disk_type_id.descriptor_idx_.index_));
-}
-
-void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) {
- const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(dex::ProtoIndex(i));
- const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
- TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_);
-
- CreateAndAddIndexedItem(proto_ids_,
- ProtoIdsOffset() + i * ProtoId::ItemSize(),
- i,
- GetStringId(disk_proto_id.shorty_idx_.index_),
- GetTypeId(disk_proto_id.return_type_idx_.index_),
- parameter_type_list);
-}
-
-void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) {
- const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
- CreateAndAddIndexedItem(field_ids_,
- FieldIdsOffset() + i * FieldId::ItemSize(),
- i,
- GetTypeId(disk_field_id.class_idx_.index_),
- GetTypeId(disk_field_id.type_idx_.index_),
- GetStringId(disk_field_id.name_idx_.index_));
-}
-
-void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) {
- const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
- CreateAndAddIndexedItem(method_ids_,
- MethodIdsOffset() + i * MethodId::ItemSize(),
- i,
- GetTypeId(disk_method_id.class_idx_.index_),
- GetProtoId(disk_method_id.proto_idx_.index_),
- GetStringId(disk_method_id.name_idx_.index_));
-}
-
-void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) {
- const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
- const TypeId* class_type = GetTypeId(disk_class_def.class_idx_.index_);
- uint32_t access_flags = disk_class_def.access_flags_;
- const TypeId* superclass = GetTypeIdOrNullPtr(disk_class_def.superclass_idx_.index_);
-
- const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
- TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_);
-
- const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_.index_);
- // Annotations.
- AnnotationsDirectoryItem* annotations = nullptr;
- const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
- dex_file.GetAnnotationsDirectory(disk_class_def);
- if (disk_annotations_directory_item != nullptr) {
- annotations = CreateAnnotationsDirectoryItem(
- dex_file, disk_annotations_directory_item, disk_class_def.annotations_off_);
- }
- // Static field initializers.
- 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_);
- CreateAndAddIndexedItem(class_defs_,
- ClassDefsOffset() + i * ClassDef::ItemSize(),
- i,
- class_type,
- access_flags,
- superclass,
- interfaces_type_list,
- source_file,
- annotations,
- static_values,
- class_data);
-}
-
-TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) {
- if (dex_type_list == nullptr) {
- return nullptr;
- }
- TypeList* type_list = type_lists_map_.GetExistingObject(offset);
- if (type_list == nullptr) {
- TypeIdVector* type_vector = new TypeIdVector();
- uint32_t size = dex_type_list->Size();
- for (uint32_t index = 0; index < size; ++index) {
- type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_.index_));
- }
- type_list = CreateAndAddItem(type_lists_map_, type_lists_, offset, type_vector);
- }
- return type_list;
-}
-
-EncodedArrayItem* Collections::CreateEncodedArrayItem(const DexFile& dex_file,
- const uint8_t* static_data,
- uint32_t offset) {
- if (static_data == nullptr) {
- return nullptr;
- }
- EncodedArrayItem* encoded_array_item = encoded_array_items_map_.GetExistingObject(offset);
- if (encoded_array_item == nullptr) {
- uint32_t size = DecodeUnsignedLeb128(&static_data);
- EncodedValueVector* values = new EncodedValueVector();
- for (uint32_t i = 0; i < size; ++i) {
- values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, &static_data)));
- }
- // TODO: Calculate the size of the encoded array.
- encoded_array_item = CreateAndAddItem(encoded_array_items_map_,
- encoded_array_items_,
- offset,
- values);
- }
- return encoded_array_item;
-}
-
-void Collections::AddAnnotationsFromMapListSection(const DexFile& dex_file,
- uint32_t start_offset,
- uint32_t count) {
- uint32_t current_offset = start_offset;
- for (size_t i = 0; i < count; ++i) {
- // Annotation that we didn't process already, add it to the set.
- const DexFile::AnnotationItem* annotation = dex_file.GetAnnotationItemAtOffset(current_offset);
- AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation);
- DCHECK(annotation_item != nullptr);
- current_offset += annotation_item->GetSize();
- }
-}
-
-AnnotationItem* Collections::CreateAnnotationItem(const DexFile& dex_file,
- const DexFile::AnnotationItem* annotation) {
- const uint8_t* const start_data = reinterpret_cast<const uint8_t*>(annotation);
- const uint32_t offset = start_data - dex_file.DataBegin();
- AnnotationItem* annotation_item = annotation_items_map_.GetExistingObject(offset);
- if (annotation_item == nullptr) {
- uint8_t visibility = annotation->visibility_;
- const uint8_t* annotation_data = annotation->annotation_;
- std::unique_ptr<EncodedValue> encoded_value(
- ReadEncodedValue(dex_file, &annotation_data, DexFile::kDexAnnotationAnnotation, 0));
- annotation_item = CreateAndAddItem(annotation_items_map_,
- annotation_items_,
- offset,
- visibility,
- encoded_value->ReleaseEncodedAnnotation());
- annotation_item->SetSize(annotation_data - start_data);
- }
- return annotation_item;
-}
-
-
-AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file,
- const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset) {
- if (disk_annotations_item == nullptr || (disk_annotations_item->size_ == 0 && offset == 0)) {
- return nullptr;
- }
- AnnotationSetItem* annotation_set_item = annotation_set_items_map_.GetExistingObject(offset);
- if (annotation_set_item == nullptr) {
- std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
- for (uint32_t i = 0; i < disk_annotations_item->size_; ++i) {
- const DexFile::AnnotationItem* annotation =
- dex_file.GetAnnotationItem(disk_annotations_item, i);
- if (annotation == nullptr) {
- continue;
- }
- AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation);
- items->push_back(annotation_item);
- }
- annotation_set_item = CreateAndAddItem(annotation_set_items_map_,
- annotation_set_items_,
- offset,
- items);
- }
- return annotation_set_item;
-}
-
-AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
- const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
- AnnotationsDirectoryItem* annotations_directory_item =
- annotations_directory_items_map_.GetExistingObject(offset);
- if (annotations_directory_item != nullptr) {
- return annotations_directory_item;
- }
- const DexFile::AnnotationSetItem* class_set_item =
- dex_file.GetClassAnnotationSet(disk_annotations_item);
- AnnotationSetItem* class_annotation = nullptr;
- if (class_set_item != nullptr) {
- uint32_t item_offset = disk_annotations_item->class_annotations_off_;
- class_annotation = CreateAnnotationSetItem(dex_file, class_set_item, item_offset);
- }
- const DexFile::FieldAnnotationsItem* fields =
- dex_file.GetFieldAnnotations(disk_annotations_item);
- FieldAnnotationVector* field_annotations = nullptr;
- if (fields != nullptr) {
- field_annotations = new FieldAnnotationVector();
- for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
- FieldId* field_id = GetFieldId(fields[i].field_idx_);
- const DexFile::AnnotationSetItem* field_set_item =
- dex_file.GetFieldAnnotationSetItem(fields[i]);
- uint32_t annotation_set_offset = fields[i].annotations_off_;
- AnnotationSetItem* annotation_set_item =
- CreateAnnotationSetItem(dex_file, field_set_item, annotation_set_offset);
- field_annotations->push_back(std::unique_ptr<FieldAnnotation>(
- new FieldAnnotation(field_id, annotation_set_item)));
- }
- }
- const DexFile::MethodAnnotationsItem* methods =
- dex_file.GetMethodAnnotations(disk_annotations_item);
- MethodAnnotationVector* method_annotations = nullptr;
- if (methods != nullptr) {
- method_annotations = new MethodAnnotationVector();
- for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
- MethodId* method_id = GetMethodId(methods[i].method_idx_);
- const DexFile::AnnotationSetItem* method_set_item =
- dex_file.GetMethodAnnotationSetItem(methods[i]);
- uint32_t annotation_set_offset = methods[i].annotations_off_;
- AnnotationSetItem* annotation_set_item =
- CreateAnnotationSetItem(dex_file, method_set_item, annotation_set_offset);
- method_annotations->push_back(std::unique_ptr<MethodAnnotation>(
- new MethodAnnotation(method_id, annotation_set_item)));
- }
- }
- const DexFile::ParameterAnnotationsItem* parameters =
- dex_file.GetParameterAnnotations(disk_annotations_item);
- ParameterAnnotationVector* parameter_annotations = nullptr;
- if (parameters != nullptr) {
- parameter_annotations = new ParameterAnnotationVector();
- for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
- MethodId* method_id = GetMethodId(parameters[i].method_idx_);
- const DexFile::AnnotationSetRefList* list =
- dex_file.GetParameterAnnotationSetRefList(¶meters[i]);
- parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
- GenerateParameterAnnotation(dex_file, method_id, list, parameters[i].annotations_off_)));
- }
- }
- // TODO: Calculate the size of the annotations directory.
- return CreateAndAddItem(annotations_directory_items_map_,
- annotations_directory_items_,
- offset,
- class_annotation,
- field_annotations,
- method_annotations,
- parameter_annotations);
-}
-
-ParameterAnnotation* Collections::GenerateParameterAnnotation(
- const DexFile& dex_file, MethodId* method_id,
- const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) {
- AnnotationSetRefList* set_ref_list = annotation_set_ref_lists_map_.GetExistingObject(offset);
- if (set_ref_list == nullptr) {
- std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
- for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
- const DexFile::AnnotationSetItem* annotation_set_item =
- dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
- uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
- annotations->push_back(CreateAnnotationSetItem(dex_file, annotation_set_item, set_offset));
- }
- set_ref_list = CreateAndAddItem(annotation_set_ref_lists_map_,
- annotation_set_ref_lists_,
- offset,
- annotations);
- }
- return new ParameterAnnotation(method_id, set_ref_list);
-}
-
-CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file,
- const DexFile::CodeItem* disk_code_item,
- uint32_t offset,
- uint32_t dex_method_index) {
- if (disk_code_item == nullptr) {
- return nullptr;
- }
- CodeItemDebugInfoAccessor accessor(dex_file, disk_code_item, dex_method_index);
- const uint32_t debug_info_offset = accessor.DebugInfoOffset();
-
- // Create the offsets pair and dedupe based on it.
- std::pair<uint32_t, uint32_t> offsets_pair(offset, debug_info_offset);
- auto existing = code_items_map_.find(offsets_pair);
- if (existing != code_items_map_.end()) {
- return existing->second;
- }
-
- const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(debug_info_offset);
- DebugInfoItem* debug_info = nullptr;
- if (debug_info_stream != nullptr) {
- debug_info = debug_info_items_map_.GetExistingObject(debug_info_offset);
- if (debug_info == nullptr) {
- uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream);
- uint8_t* debug_info_buffer = new uint8_t[debug_info_size];
- memcpy(debug_info_buffer, debug_info_stream, debug_info_size);
- debug_info = CreateAndAddItem(debug_info_items_map_,
- debug_info_items_,
- debug_info_offset,
- debug_info_size,
- debug_info_buffer);
- }
- }
-
- uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
- uint16_t* insns = new uint16_t[insns_size];
- memcpy(insns, accessor.Insns(), insns_size * sizeof(uint16_t));
-
- TryItemVector* tries = nullptr;
- CatchHandlerVector* handler_list = nullptr;
- if (accessor.TriesSize() > 0) {
- tries = new TryItemVector();
- handler_list = new CatchHandlerVector();
- for (const DexFile::TryItem& disk_try_item : accessor.TryItems()) {
- uint32_t start_addr = disk_try_item.start_addr_;
- uint16_t insn_count = disk_try_item.insn_count_;
- uint16_t handler_off = disk_try_item.handler_off_;
- const CatchHandler* handlers = nullptr;
- for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
- if (handler_off == existing_handlers->GetListOffset()) {
- handlers = existing_handlers.get();
- break;
- }
- }
- if (handlers == nullptr) {
- bool catch_all = false;
- TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
- for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) {
- const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
- const TypeId* type_id = GetTypeIdOrNullPtr(type_index.index_);
- catch_all |= type_id == nullptr;
- addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>(
- new TypeAddrPair(type_id, it.GetHandlerAddress())));
- }
- handlers = new CatchHandler(catch_all, handler_off, addr_pairs);
- handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers));
- }
- TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
- tries->push_back(std::unique_ptr<const TryItem>(try_item));
- }
- // Manually walk catch handlers list and add any missing handlers unreferenced by try items.
- const uint8_t* handlers_base = accessor.GetCatchHandlerData();
- const uint8_t* handlers_data = handlers_base;
- uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data);
- while (handlers_size > handler_list->size()) {
- bool already_added = false;
- uint16_t handler_off = handlers_data - handlers_base;
- for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
- if (handler_off == existing_handlers->GetListOffset()) {
- already_added = true;
- break;
- }
- }
- int32_t size = DecodeSignedLeb128(&handlers_data);
- bool has_catch_all = size <= 0;
- if (has_catch_all) {
- size = -size;
- }
- if (already_added) {
- for (int32_t i = 0; i < size; i++) {
- DecodeUnsignedLeb128(&handlers_data);
- DecodeUnsignedLeb128(&handlers_data);
- }
- if (has_catch_all) {
- DecodeUnsignedLeb128(&handlers_data);
- }
- continue;
- }
- TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
- for (int32_t i = 0; i < size; i++) {
- const TypeId* type_id = GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data));
- uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
- addr_pairs->push_back(
- std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr)));
- }
- if (has_catch_all) {
- uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
- addr_pairs->push_back(
- std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr)));
- }
- const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs);
- handler_list->push_back(std::unique_ptr<const CatchHandler>(handler));
- }
- }
-
- uint32_t size = dex_file.GetCodeItemSize(*disk_code_item);
- CodeItem* code_item = code_items_.CreateAndAddItem(accessor.RegistersSize(),
- accessor.InsSize(),
- accessor.OutsSize(),
- debug_info,
- insns_size,
- insns,
- tries,
- handler_list);
- code_item->SetSize(size);
-
- // Add the code item to the map.
- DCHECK(!code_item->OffsetAssigned());
- if (eagerly_assign_offsets_) {
- code_item->SetOffset(offset);
- }
- code_items_map_.emplace(offsets_pair, code_item);
-
- // Add "fixup" references to types, strings, methods, and fields.
- // This is temporary, as we will probably want more detailed parsing of the
- // instructions here.
- std::vector<TypeId*> type_ids;
- std::vector<StringId*> string_ids;
- std::vector<MethodId*> method_ids;
- std::vector<FieldId*> field_ids;
- if (GetIdsFromByteCode(*this,
- code_item,
- /*out*/ &type_ids,
- /*out*/ &string_ids,
- /*out*/ &method_ids,
- /*out*/ &field_ids)) {
- CodeFixups* fixups = new CodeFixups(std::move(type_ids),
- std::move(string_ids),
- std::move(method_ids),
- std::move(field_ids));
- code_item->SetCodeFixups(fixups);
- }
-
- return code_item;
-}
-
-MethodItem Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
- MethodId* method_id = GetMethodId(cdii.GetMemberIndex());
- uint32_t access_flags = cdii.GetRawMemberAccessFlags();
- const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
- // 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());
- return MethodItem(access_flags, method_id, code_item);
-}
-
-ClassData* Collections::CreateClassData(
- const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
- // Read the fields and methods defined by the class, resolving the circular reference from those
- // to classes by setting class at the same time.
- ClassData* class_data = class_datas_map_.GetExistingObject(offset);
- if (class_data == nullptr && encoded_data != nullptr) {
- ClassDataItemIterator cdii(dex_file, encoded_data);
- // Static fields.
- FieldItemVector* static_fields = new FieldItemVector();
- for (; cdii.HasNextStaticField(); cdii.Next()) {
- FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
- uint32_t access_flags = cdii.GetRawMemberAccessFlags();
- static_fields->emplace_back(access_flags, field_item);
- }
- // Instance fields.
- FieldItemVector* instance_fields = new FieldItemVector();
- for (; cdii.HasNextInstanceField(); cdii.Next()) {
- FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
- uint32_t access_flags = cdii.GetRawMemberAccessFlags();
- 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));
- }
- // Virtual methods.
- MethodItemVector* virtual_methods = new MethodItemVector();
- for (; cdii.HasNextVirtualMethod(); cdii.Next()) {
- virtual_methods->push_back(GenerateMethodItem(dex_file, cdii));
- }
- class_data = CreateAndAddItem(class_datas_map_,
- class_datas_,
- offset,
- static_fields,
- instance_fields,
- direct_methods,
- virtual_methods);
- class_data->SetSize(cdii.EndDataPointer() - encoded_data);
- }
- return class_data;
-}
-
-void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
- // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems.
- const DexFile::MapList* map = dex_file.GetMapList();
- for (uint32_t i = 0; i < map->size_; ++i) {
- const DexFile::MapItem* item = map->list_ + i;
- switch (item->type_) {
- case DexFile::kDexTypeCallSiteIdItem:
- SetCallSiteIdsOffset(item->offset_);
- break;
- case DexFile::kDexTypeMethodHandleItem:
- SetMethodHandleItemsOffset(item->offset_);
- break;
- default:
- break;
- }
- }
- // Populate MethodHandleItems first (CallSiteIds may depend on them).
- for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) {
- CreateMethodHandleItem(dex_file, i);
- }
- // Populate CallSiteIds.
- for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) {
- CreateCallSiteId(dex_file, i);
- }
-}
-
-void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
- const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i);
- const uint8_t* disk_call_item_ptr = dex_file.DataBegin() + disk_call_site_id.data_off_;
- EncodedArrayItem* call_site_item =
- CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_);
-
- CreateAndAddIndexedItem(call_site_ids_,
- CallSiteIdsOffset() + i * CallSiteId::ItemSize(),
- i,
- call_site_item);
-}
-
-void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
- const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i);
- uint16_t index = disk_method_handle.field_or_method_idx_;
- DexFile::MethodHandleType type =
- static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_);
- bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic ||
- type == DexFile::MethodHandleType::kInvokeInstance ||
- type == DexFile::MethodHandleType::kInvokeConstructor ||
- type == DexFile::MethodHandleType::kInvokeDirect ||
- type == DexFile::MethodHandleType::kInvokeInterface;
- static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeInterface,
- "Unexpected method handle types.");
- IndexedItem* field_or_method_id;
- if (is_invoke) {
- field_or_method_id = GetMethodId(index);
- } else {
- field_or_method_id = GetFieldId(index);
- }
- CreateAndAddIndexedItem(method_handle_items_,
- MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(),
- i,
- type,
- field_or_method_id);
-}
-
-void Collections::SortVectorsByMapOrder() {
- string_datas_.SortByMapOrder(string_datas_map_.Collection());
- type_lists_.SortByMapOrder(type_lists_map_.Collection());
- encoded_array_items_.SortByMapOrder(encoded_array_items_map_.Collection());
- annotation_items_.SortByMapOrder(annotation_items_map_.Collection());
- annotation_set_items_.SortByMapOrder(annotation_set_items_map_.Collection());
- annotation_set_ref_lists_.SortByMapOrder(annotation_set_ref_lists_map_.Collection());
- annotations_directory_items_.SortByMapOrder(annotations_directory_items_map_.Collection());
- debug_info_items_.SortByMapOrder(debug_info_items_map_.Collection());
- code_items_.SortByMapOrder(code_items_map_);
- class_datas_.SortByMapOrder(class_datas_map_.Collection());
-}
-
-void Collections::ClearMaps() {
- string_datas_map_.Collection().clear();
- type_lists_map_.Collection().clear();
- encoded_array_items_map_.Collection().clear();
- annotation_items_map_.Collection().clear();
- annotation_set_items_map_.Collection().clear();
- annotation_set_ref_lists_map_.Collection().clear();
- annotations_directory_items_map_.Collection().clear();
- debug_info_items_map_.Collection().clear();
- code_items_map_.clear();
- class_datas_map_.Collection().clear();
-}
-
-static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
+static uint32_t HeaderOffset(const dex_ir::Header* header ATTRIBUTE_UNUSED) {
return 0;
}
-static uint32_t HeaderSize(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
+static uint32_t HeaderSize(const dex_ir::Header* header ATTRIBUTE_UNUSED) {
// Size is in elements, so there is only one header.
return 1;
}
@@ -907,9 +45,9 @@
std::string name;
uint16_t type;
// A function that when applied to a collection object, gives the size of the section.
- std::function<uint32_t(const dex_ir::Collections&)> size_fn;
+ std::function<uint32_t(dex_ir::Header*)> size_fn;
// A function that when applied to a collection object, gives the offset of the section.
- std::function<uint32_t(const dex_ir::Collections&)> offset_fn;
+ std::function<uint32_t(dex_ir::Header*)> offset_fn;
};
static const FileSectionDescriptor kFileSectionDescriptors[] = {
@@ -921,106 +59,105 @@
}, {
"StringId",
DexFile::kDexTypeStringIdItem,
- &dex_ir::Collections::StringIdsSize,
- &dex_ir::Collections::StringIdsOffset
+ [](const dex_ir::Header* h) { return h->StringIds().Size(); },
+ [](const dex_ir::Header* h) { return h->StringIds().GetOffset(); }
}, {
"TypeId",
DexFile::kDexTypeTypeIdItem,
- &dex_ir::Collections::TypeIdsSize,
- &dex_ir::Collections::TypeIdsOffset
+ [](const dex_ir::Header* h) { return h->TypeIds().Size(); },
+ [](const dex_ir::Header* h) { return h->TypeIds().GetOffset(); }
}, {
"ProtoId",
DexFile::kDexTypeProtoIdItem,
- &dex_ir::Collections::ProtoIdsSize,
- &dex_ir::Collections::ProtoIdsOffset
+ [](const dex_ir::Header* h) { return h->ProtoIds().Size(); },
+ [](const dex_ir::Header* h) { return h->ProtoIds().GetOffset(); }
}, {
"FieldId",
DexFile::kDexTypeFieldIdItem,
- &dex_ir::Collections::FieldIdsSize,
- &dex_ir::Collections::FieldIdsOffset
+ [](const dex_ir::Header* h) { return h->FieldIds().Size(); },
+ [](const dex_ir::Header* h) { return h->FieldIds().GetOffset(); }
}, {
"MethodId",
DexFile::kDexTypeMethodIdItem,
- &dex_ir::Collections::MethodIdsSize,
- &dex_ir::Collections::MethodIdsOffset
+ [](const dex_ir::Header* h) { return h->MethodIds().Size(); },
+ [](const dex_ir::Header* h) { return h->MethodIds().GetOffset(); }
}, {
"ClassDef",
DexFile::kDexTypeClassDefItem,
- &dex_ir::Collections::ClassDefsSize,
- &dex_ir::Collections::ClassDefsOffset
+ [](const dex_ir::Header* h) { return h->ClassDefs().Size(); },
+ [](const dex_ir::Header* h) { return h->ClassDefs().GetOffset(); }
}, {
"CallSiteId",
DexFile::kDexTypeCallSiteIdItem,
- &dex_ir::Collections::CallSiteIdsSize,
- &dex_ir::Collections::CallSiteIdsOffset
+ [](const dex_ir::Header* h) { return h->CallSiteIds().Size(); },
+ [](const dex_ir::Header* h) { return h->CallSiteIds().GetOffset(); }
}, {
"MethodHandle",
DexFile::kDexTypeMethodHandleItem,
- &dex_ir::Collections::MethodHandleItemsSize,
- &dex_ir::Collections::MethodHandleItemsOffset
+ [](const dex_ir::Header* h) { return h->MethodHandleItems().Size(); },
+ [](const dex_ir::Header* h) { return h->MethodHandleItems().GetOffset(); }
}, {
"StringData",
DexFile::kDexTypeStringDataItem,
- &dex_ir::Collections::StringDatasSize,
- &dex_ir::Collections::StringDatasOffset
+ [](const dex_ir::Header* h) { return h->StringDatas().Size(); },
+ [](const dex_ir::Header* h) { return h->StringDatas().GetOffset(); }
}, {
"TypeList",
DexFile::kDexTypeTypeList,
- &dex_ir::Collections::TypeListsSize,
- &dex_ir::Collections::TypeListsOffset
+ [](const dex_ir::Header* h) { return h->TypeLists().Size(); },
+ [](const dex_ir::Header* h) { return h->TypeLists().GetOffset(); }
}, {
"EncArr",
DexFile::kDexTypeEncodedArrayItem,
- &dex_ir::Collections::EncodedArrayItemsSize,
- &dex_ir::Collections::EncodedArrayItemsOffset
+ [](const dex_ir::Header* h) { return h->EncodedArrayItems().Size(); },
+ [](const dex_ir::Header* h) { return h->EncodedArrayItems().GetOffset(); }
}, {
"Annotation",
DexFile::kDexTypeAnnotationItem,
- &dex_ir::Collections::AnnotationItemsSize,
- &dex_ir::Collections::AnnotationItemsOffset
+ [](const dex_ir::Header* h) { return h->AnnotationItems().Size(); },
+ [](const dex_ir::Header* h) { return h->AnnotationItems().GetOffset(); }
}, {
"AnnoSet",
DexFile::kDexTypeAnnotationSetItem,
- &dex_ir::Collections::AnnotationSetItemsSize,
- &dex_ir::Collections::AnnotationSetItemsOffset
+ [](const dex_ir::Header* h) { return h->AnnotationSetItems().Size(); },
+ [](const dex_ir::Header* h) { return h->AnnotationSetItems().GetOffset(); }
}, {
"AnnoSetRL",
DexFile::kDexTypeAnnotationSetRefList,
- &dex_ir::Collections::AnnotationSetRefListsSize,
- &dex_ir::Collections::AnnotationSetRefListsOffset
+ [](const dex_ir::Header* h) { return h->AnnotationSetRefLists().Size(); },
+ [](const dex_ir::Header* h) { return h->AnnotationSetRefLists().GetOffset(); }
}, {
"AnnoDir",
DexFile::kDexTypeAnnotationsDirectoryItem,
- &dex_ir::Collections::AnnotationsDirectoryItemsSize,
- &dex_ir::Collections::AnnotationsDirectoryItemsOffset
+ [](const dex_ir::Header* h) { return h->AnnotationsDirectoryItems().Size(); },
+ [](const dex_ir::Header* h) { return h->AnnotationsDirectoryItems().GetOffset(); }
}, {
"DebugInfo",
DexFile::kDexTypeDebugInfoItem,
- &dex_ir::Collections::DebugInfoItemsSize,
- &dex_ir::Collections::DebugInfoItemsOffset
+ [](const dex_ir::Header* h) { return h->DebugInfoItems().Size(); },
+ [](const dex_ir::Header* h) { return h->DebugInfoItems().GetOffset(); }
}, {
"CodeItem",
DexFile::kDexTypeCodeItem,
- &dex_ir::Collections::CodeItemsSize,
- &dex_ir::Collections::CodeItemsOffset
+ [](const dex_ir::Header* h) { return h->CodeItems().Size(); },
+ [](const dex_ir::Header* h) { return h->CodeItems().GetOffset(); }
}, {
"ClassData",
DexFile::kDexTypeClassDataItem,
- &dex_ir::Collections::ClassDatasSize,
- &dex_ir::Collections::ClassDatasOffset
+ [](const dex_ir::Header* h) { return h->ClassDatas().Size(); },
+ [](const dex_ir::Header* h) { return h->ClassDatas().GetOffset(); }
}
};
std::vector<dex_ir::DexFileSection> GetSortedDexFileSections(dex_ir::Header* header,
dex_ir::SortDirection direction) {
- const dex_ir::Collections& collections = header->GetCollections();
std::vector<dex_ir::DexFileSection> sorted_sections;
// Build the table that will map from offset to color
for (const FileSectionDescriptor& s : kFileSectionDescriptors) {
sorted_sections.push_back(dex_ir::DexFileSection(s.name,
s.type,
- s.size_fn(collections),
- s.offset_fn(collections)));
+ s.size_fn(header),
+ s.offset_fn(header)));
}
// Sort by offset.
std::sort(sorted_sections.begin(),
diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h
index 54ff105..9f355ba 100644
--- a/dexlayout/dex_ir.h
+++ b/dexlayout/dex_ir.h
@@ -24,6 +24,7 @@
#include <map>
#include <vector>
+#include "base/iteration_range.h"
#include "base/leb128.h"
#include "base/stl_util.h"
#include "dex/dex_file-inl.h"
@@ -107,17 +108,114 @@
DISALLOW_COPY_AND_ASSIGN(AbstractDispatcher);
};
+template<class T> class Iterator : public std::iterator<std::random_access_iterator_tag, T> {
+ public:
+ using value_type = typename std::iterator<std::random_access_iterator_tag, T>::value_type;
+ using difference_type =
+ typename std::iterator<std::random_access_iterator_tag, value_type>::difference_type;
+ using pointer = typename std::iterator<std::random_access_iterator_tag, value_type>::pointer;
+ using reference = typename std::iterator<std::random_access_iterator_tag, value_type>::reference;
+
+ Iterator(const Iterator&) = default;
+ Iterator(Iterator&&) = default;
+ Iterator& operator=(const Iterator&) = default;
+ Iterator& operator=(Iterator&&) = default;
+
+ Iterator(const std::vector<T>& vector,
+ uint32_t position,
+ uint32_t iterator_end)
+ : vector_(&vector),
+ position_(position),
+ iterator_end_(iterator_end) { }
+ Iterator() : vector_(nullptr), position_(0U), iterator_end_(0U) { }
+
+ bool IsValid() const { return position_ < iterator_end_; }
+
+ bool operator==(const Iterator& rhs) const { return position_ == rhs.position_; }
+ bool operator!=(const Iterator& rhs) const { return !(*this == rhs); }
+ bool operator<(const Iterator& rhs) const { return position_ < rhs.position_; }
+ bool operator>(const Iterator& rhs) const { return rhs < *this; }
+ bool operator<=(const Iterator& rhs) const { return !(rhs < *this); }
+ bool operator>=(const Iterator& rhs) const { return !(*this < rhs); }
+
+ Iterator& operator++() { // Value after modification.
+ ++position_;
+ return *this;
+ }
+
+ Iterator operator++(int) {
+ Iterator temp = *this;
+ ++position_;
+ return temp;
+ }
+
+ Iterator& operator+=(difference_type delta) {
+ position_ += delta;
+ return *this;
+ }
+
+ Iterator operator+(difference_type delta) const {
+ Iterator temp = *this;
+ temp += delta;
+ return temp;
+ }
+
+ Iterator& operator--() { // Value after modification.
+ --position_;
+ return *this;
+ }
+
+ Iterator operator--(int) {
+ Iterator temp = *this;
+ --position_;
+ return temp;
+ }
+
+ Iterator& operator-=(difference_type delta) {
+ position_ -= delta;
+ return *this;
+ }
+
+ Iterator operator-(difference_type delta) const {
+ Iterator temp = *this;
+ temp -= delta;
+ return temp;
+ }
+
+ difference_type operator-(const Iterator& rhs) {
+ return position_ - rhs.position_;
+ }
+
+ reference operator*() const {
+ return const_cast<reference>((*vector_)[position_]);
+ }
+
+ pointer operator->() const {
+ return const_cast<pointer>(&((*vector_)[position_]));
+ }
+
+ reference operator[](difference_type n) const {
+ return (*vector_)[position_ + n];
+ }
+
+ private:
+ const std::vector<T>* vector_;
+ uint32_t position_;
+ uint32_t iterator_end_;
+
+ template <typename U>
+ friend bool operator<(const Iterator<U>& lhs, const Iterator<U>& rhs);
+};
+
// Collections become owners of the objects added by moving them into unique pointers.
-template<class T> class CollectionBase {
+class CollectionBase {
public:
CollectionBase() = default;
+ virtual ~CollectionBase() { }
- uint32_t GetOffset() const {
- return offset_;
- }
- void SetOffset(uint32_t new_offset) {
- offset_ = new_offset;
- }
+ uint32_t GetOffset() const { return offset_; }
+ void SetOffset(uint32_t new_offset) { offset_ = new_offset; }
+ virtual uint32_t Size() const { return 0U; }
private:
// Start out unassigned.
@@ -126,18 +224,37 @@
DISALLOW_COPY_AND_ASSIGN(CollectionBase);
};
-template<class T> class CollectionVector : public CollectionBase<T> {
+template<class T> class CollectionVector : public CollectionBase {
public:
- using Vector = std::vector<std::unique_ptr<T>>;
+ using ElementType = std::unique_ptr<T>;
+
CollectionVector() { }
explicit CollectionVector(size_t size) {
// Preallocate so that assignment does not invalidate pointers into the vector.
collection_.reserve(size);
}
+ virtual ~CollectionVector() OVERRIDE { }
- uint32_t Size() const { return collection_.size(); }
- Vector& Collection() { return collection_; }
- const Vector& Collection() const { return collection_; }
+ template<class... Args>
+ T* CreateAndAddItem(Args&&... args) {
+ T* object = new T(std::forward<Args>(args)...);
+ collection_.push_back(std::unique_ptr<T>(object));
+ return object;
+ }
+
+ virtual uint32_t Size() const OVERRIDE { return collection_.size(); }
+
+ Iterator<ElementType> begin() const { return Iterator<ElementType>(collection_, 0U, Size()); }
+ Iterator<ElementType> end() const { return Iterator<ElementType>(collection_, Size(), Size()); }
+
+ const ElementType& operator[](size_t index) const {
+ DCHECK_LT(index, Size());
+ return collection_[index];
+ }
+ ElementType& operator[](size_t index) {
+ DCHECK_LT(index, Size());
+ return collection_[index];
+ }
// Sort the vector by copying pointers over.
template <typename MapType>
@@ -147,24 +264,16 @@
for (size_t i = 0; i < Size(); ++i) {
// There are times when the array will temporarily contain the same pointer twice, doing the
// release here sure there is no double free errors.
- Collection()[i].release();
- Collection()[i].reset(it->second);
+ collection_[i].release();
+ collection_[i].reset(it->second);
++it;
}
}
protected:
- Vector collection_;
-
- template<class... Args>
- T* CreateAndAddItem(Args&&... args) {
- T* object = new T(std::forward<Args>(args)...);
- collection_.push_back(std::unique_ptr<T>(object));
- return object;
- }
+ std::vector<ElementType> collection_;
private:
- friend class Collections;
DISALLOW_COPY_AND_ASSIGN(CollectionVector);
};
@@ -174,7 +283,6 @@
IndexedCollectionVector() = default;
explicit IndexedCollectionVector(size_t size) : CollectionVector<T>(size) { }
- private:
template <class... Args>
T* CreateAndAddIndexedItem(uint32_t index, Args&&... args) {
T* object = CollectionVector<T>::CreateAndAddItem(std::forward<Args>(args)...);
@@ -182,332 +290,15 @@
return object;
}
- T* GetElement(uint32_t index) {
- DCHECK_LT(index, CollectionVector<T>::Size());
+ T* operator[](size_t index) const {
DCHECK_NE(CollectionVector<T>::collection_[index].get(), static_cast<T*>(nullptr));
return CollectionVector<T>::collection_[index].get();
}
- friend class Collections;
+ private:
DISALLOW_COPY_AND_ASSIGN(IndexedCollectionVector);
};
-template<class T> class CollectionMap : public CollectionBase<T> {
- public:
- CollectionMap() = default;
-
- // Returns the existing item if it is already inserted, null otherwise.
- T* GetExistingObject(uint32_t offset) {
- auto it = collection_.find(offset);
- return it != collection_.end() ? it->second : nullptr;
- }
-
- // Lower case for template interop with std::map.
- uint32_t size() const { return collection_.size(); }
- std::map<uint32_t, T*>& Collection() { return collection_; }
-
- private:
- std::map<uint32_t, T*> collection_;
-
- // CollectionMaps do not own the objects they contain, therefore AddItem is supported
- // rather than CreateAndAddItem.
- void AddItem(T* object, uint32_t offset) {
- auto it = collection_.emplace(offset, object);
- CHECK(it.second) << "CollectionMap already has an object with offset " << offset << " "
- << " and address " << it.first->second;
- }
-
- friend class Collections;
- DISALLOW_COPY_AND_ASSIGN(CollectionMap);
-};
-
-class Collections {
- public:
- Collections() = default;
- Collections(uint32_t num_string_ids,
- uint32_t num_type_ids,
- uint32_t num_proto_ids,
- uint32_t num_field_ids,
- uint32_t num_method_ids,
- uint32_t num_class_defs)
- : string_ids_(num_string_ids),
- type_ids_(num_type_ids),
- proto_ids_(num_proto_ids),
- field_ids_(num_field_ids),
- method_ids_(num_method_ids),
- class_defs_(num_class_defs) { }
-
- IndexedCollectionVector<StringId>::Vector& StringIds() { return string_ids_.Collection(); }
- IndexedCollectionVector<TypeId>::Vector& TypeIds() { return type_ids_.Collection(); }
- IndexedCollectionVector<ProtoId>::Vector& ProtoIds() { return proto_ids_.Collection(); }
- IndexedCollectionVector<FieldId>::Vector& FieldIds() { return field_ids_.Collection(); }
- IndexedCollectionVector<MethodId>::Vector& MethodIds() { return method_ids_.Collection(); }
- IndexedCollectionVector<ClassDef>::Vector& ClassDefs() { return class_defs_.Collection(); }
- CollectionVector<CallSiteId>::Vector& CallSiteIds() { return call_site_ids_.Collection(); }
- CollectionVector<MethodHandleItem>::Vector& MethodHandleItems()
- { return method_handle_items_.Collection(); }
- CollectionVector<StringData>::Vector& StringDatas() { return string_datas_.Collection(); }
- CollectionVector<TypeList>::Vector& TypeLists() { return type_lists_.Collection(); }
- CollectionVector<EncodedArrayItem>::Vector& EncodedArrayItems()
- { return encoded_array_items_.Collection(); }
- CollectionVector<AnnotationItem>::Vector& AnnotationItems()
- { return annotation_items_.Collection(); }
- CollectionVector<AnnotationSetItem>::Vector& AnnotationSetItems()
- { return annotation_set_items_.Collection(); }
- CollectionVector<AnnotationSetRefList>::Vector& AnnotationSetRefLists()
- { return annotation_set_ref_lists_.Collection(); }
- CollectionVector<AnnotationsDirectoryItem>::Vector& AnnotationsDirectoryItems()
- { return annotations_directory_items_.Collection(); }
- CollectionVector<DebugInfoItem>::Vector& DebugInfoItems()
- { return debug_info_items_.Collection(); }
- CollectionVector<CodeItem>::Vector& CodeItems() { return code_items_.Collection(); }
- CollectionVector<ClassData>::Vector& ClassDatas() { return class_datas_.Collection(); }
-
- const CollectionVector<ClassDef>::Vector& ClassDefs() const { return class_defs_.Collection(); }
-
- void CreateStringId(const DexFile& dex_file, uint32_t i);
- void CreateTypeId(const DexFile& dex_file, uint32_t i);
- void CreateProtoId(const DexFile& dex_file, uint32_t i);
- void CreateFieldId(const DexFile& dex_file, uint32_t i);
- void CreateMethodId(const DexFile& dex_file, uint32_t i);
- void CreateClassDef(const DexFile& dex_file, uint32_t i);
- void CreateCallSiteId(const DexFile& dex_file, uint32_t i);
- void CreateMethodHandleItem(const DexFile& dex_file, uint32_t i);
-
- void CreateCallSitesAndMethodHandles(const DexFile& dex_file);
-
- TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset);
- EncodedArrayItem* CreateEncodedArrayItem(const DexFile& dex_file,
- const uint8_t* static_data,
- uint32_t offset);
- AnnotationItem* CreateAnnotationItem(const DexFile& dex_file,
- const DexFile::AnnotationItem* annotation);
- AnnotationSetItem* CreateAnnotationSetItem(const DexFile& dex_file,
- const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset);
- AnnotationsDirectoryItem* CreateAnnotationsDirectoryItem(const DexFile& dex_file,
- const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset);
- CodeItem* DedupeOrCreateCodeItem(const DexFile& dex_file,
- 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);
- void AddAnnotationsFromMapListSection(const DexFile& dex_file,
- uint32_t start_offset,
- uint32_t count);
-
- StringId* GetStringId(uint32_t index) {
- return string_ids_.GetElement(index);
- }
- TypeId* GetTypeId(uint32_t index) {
- return type_ids_.GetElement(index);
- }
- ProtoId* GetProtoId(uint32_t index) {
- return proto_ids_.GetElement(index);
- }
- FieldId* GetFieldId(uint32_t index) {
- return field_ids_.GetElement(index);
- }
- MethodId* GetMethodId(uint32_t index) {
- return method_ids_.GetElement(index);
- }
- ClassDef* GetClassDef(uint32_t index) {
- return class_defs_.GetElement(index);
- }
- CallSiteId* GetCallSiteId(uint32_t index) {
- CHECK_LT(index, CallSiteIdsSize());
- return CallSiteIds()[index].get();
- }
- MethodHandleItem* GetMethodHandle(uint32_t index) {
- CHECK_LT(index, MethodHandleItemsSize());
- return MethodHandleItems()[index].get();
- }
-
- StringId* GetStringIdOrNullPtr(uint32_t index) {
- return index == dex::kDexNoIndex ? nullptr : GetStringId(index);
- }
- TypeId* GetTypeIdOrNullPtr(uint16_t index) {
- return index == DexFile::kDexNoIndex16 ? nullptr : GetTypeId(index);
- }
-
- uint32_t StringIdsOffset() const { return string_ids_.GetOffset(); }
- uint32_t TypeIdsOffset() const { return type_ids_.GetOffset(); }
- uint32_t ProtoIdsOffset() const { return proto_ids_.GetOffset(); }
- uint32_t FieldIdsOffset() const { return field_ids_.GetOffset(); }
- uint32_t MethodIdsOffset() const { return method_ids_.GetOffset(); }
- uint32_t ClassDefsOffset() const { return class_defs_.GetOffset(); }
- uint32_t CallSiteIdsOffset() const { return call_site_ids_.GetOffset(); }
- uint32_t MethodHandleItemsOffset() const { return method_handle_items_.GetOffset(); }
- uint32_t StringDatasOffset() const { return string_datas_.GetOffset(); }
- uint32_t TypeListsOffset() const { return type_lists_.GetOffset(); }
- uint32_t EncodedArrayItemsOffset() const { return encoded_array_items_.GetOffset(); }
- uint32_t AnnotationItemsOffset() const { return annotation_items_.GetOffset(); }
- uint32_t AnnotationSetItemsOffset() const { return annotation_set_items_.GetOffset(); }
- uint32_t AnnotationSetRefListsOffset() const { return annotation_set_ref_lists_.GetOffset(); }
- uint32_t AnnotationsDirectoryItemsOffset() const
- { return annotations_directory_items_.GetOffset(); }
- uint32_t DebugInfoItemsOffset() const { return debug_info_items_.GetOffset(); }
- uint32_t CodeItemsOffset() const { return code_items_.GetOffset(); }
- uint32_t ClassDatasOffset() const { return class_datas_.GetOffset(); }
- uint32_t MapListOffset() const { return map_list_offset_; }
-
- void SetStringIdsOffset(uint32_t new_offset) { string_ids_.SetOffset(new_offset); }
- void SetTypeIdsOffset(uint32_t new_offset) { type_ids_.SetOffset(new_offset); }
- void SetProtoIdsOffset(uint32_t new_offset) { proto_ids_.SetOffset(new_offset); }
- void SetFieldIdsOffset(uint32_t new_offset) { field_ids_.SetOffset(new_offset); }
- void SetMethodIdsOffset(uint32_t new_offset) { method_ids_.SetOffset(new_offset); }
- void SetClassDefsOffset(uint32_t new_offset) { class_defs_.SetOffset(new_offset); }
- void SetCallSiteIdsOffset(uint32_t new_offset) { call_site_ids_.SetOffset(new_offset); }
- void SetMethodHandleItemsOffset(uint32_t new_offset)
- { method_handle_items_.SetOffset(new_offset); }
- void SetStringDatasOffset(uint32_t new_offset) { string_datas_.SetOffset(new_offset); }
- void SetTypeListsOffset(uint32_t new_offset) { type_lists_.SetOffset(new_offset); }
- void SetEncodedArrayItemsOffset(uint32_t new_offset)
- { encoded_array_items_.SetOffset(new_offset); }
- void SetAnnotationItemsOffset(uint32_t new_offset) { annotation_items_.SetOffset(new_offset); }
- void SetAnnotationSetItemsOffset(uint32_t new_offset)
- { annotation_set_items_.SetOffset(new_offset); }
- void SetAnnotationSetRefListsOffset(uint32_t new_offset)
- { annotation_set_ref_lists_.SetOffset(new_offset); }
- void SetAnnotationsDirectoryItemsOffset(uint32_t new_offset)
- { annotations_directory_items_.SetOffset(new_offset); }
- void SetDebugInfoItemsOffset(uint32_t new_offset) { debug_info_items_.SetOffset(new_offset); }
- void SetCodeItemsOffset(uint32_t new_offset) { code_items_.SetOffset(new_offset); }
- void SetClassDatasOffset(uint32_t new_offset) { class_datas_.SetOffset(new_offset); }
- void SetMapListOffset(uint32_t new_offset) { map_list_offset_ = new_offset; }
-
- uint32_t StringIdsSize() const { return string_ids_.Size(); }
- uint32_t TypeIdsSize() const { return type_ids_.Size(); }
- uint32_t ProtoIdsSize() const { return proto_ids_.Size(); }
- uint32_t FieldIdsSize() const { return field_ids_.Size(); }
- uint32_t MethodIdsSize() const { return method_ids_.Size(); }
- uint32_t ClassDefsSize() const { return class_defs_.Size(); }
- uint32_t CallSiteIdsSize() const { return call_site_ids_.Size(); }
- uint32_t MethodHandleItemsSize() const { return method_handle_items_.Size(); }
- uint32_t StringDatasSize() const { return string_datas_.Size(); }
- uint32_t TypeListsSize() const { return type_lists_.Size(); }
- uint32_t EncodedArrayItemsSize() const { return encoded_array_items_.Size(); }
- uint32_t AnnotationItemsSize() const { return annotation_items_.Size(); }
- uint32_t AnnotationSetItemsSize() const { return annotation_set_items_.Size(); }
- uint32_t AnnotationSetRefListsSize() const { return annotation_set_ref_lists_.Size(); }
- uint32_t AnnotationsDirectoryItemsSize() const { return annotations_directory_items_.Size(); }
- uint32_t DebugInfoItemsSize() const { return debug_info_items_.Size(); }
- uint32_t CodeItemsSize() const { return code_items_.Size(); }
- uint32_t ClassDatasSize() const { return class_datas_.Size(); }
-
- // Sort the vectors buy map order (same order that was used in the input file).
- void SortVectorsByMapOrder();
- // Empty the maps, which are only used for IR construction.
- void ClearMaps();
-
- template <typename Type, class... Args>
- Type* CreateAndAddItem(CollectionMap<Type>& map,
- CollectionVector<Type>& vector,
- uint32_t offset,
- Args&&... args) {
- Type* item = vector.CreateAndAddItem(std::forward<Args>(args)...);
- DCHECK(!map.GetExistingObject(offset));
- DCHECK(!item->OffsetAssigned());
- if (eagerly_assign_offsets_) {
- item->SetOffset(offset);
- }
- map.AddItem(item, offset);
- return item;
- }
-
- template <typename Type, class... Args>
- Type* CreateAndAddIndexedItem(IndexedCollectionVector<Type>& vector,
- uint32_t offset,
- uint32_t index,
- Args&&... args) {
- Type* item = vector.CreateAndAddIndexedItem(index, std::forward<Args>(args)...);
- DCHECK(!item->OffsetAssigned());
- if (eagerly_assign_offsets_) {
- item->SetOffset(offset);
- }
- return item;
- }
-
- void SetEagerlyAssignOffsets(bool eagerly_assign_offsets) {
- eagerly_assign_offsets_ = eagerly_assign_offsets;
- }
-
- void SetLinkData(std::vector<uint8_t>&& link_data) {
- link_data_ = std::move(link_data);
- }
-
- const std::vector<uint8_t>& LinkData() const {
- return link_data_;
- }
-
- private:
- EncodedValue* ReadEncodedValue(const DexFile& dex_file, const uint8_t** data);
- EncodedValue* ReadEncodedValue(const DexFile& dex_file,
- const uint8_t** data,
- uint8_t type,
- uint8_t length);
- void ReadEncodedValue(const DexFile& dex_file,
- const uint8_t** data,
- uint8_t type,
- uint8_t length,
- EncodedValue* item);
-
- ParameterAnnotation* GenerateParameterAnnotation(const DexFile& dex_file, MethodId* method_id,
- const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset);
- MethodItem GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii);
-
- // Collection vectors own the IR data.
- IndexedCollectionVector<StringId> string_ids_;
- IndexedCollectionVector<TypeId> type_ids_;
- IndexedCollectionVector<ProtoId> proto_ids_;
- IndexedCollectionVector<FieldId> field_ids_;
- IndexedCollectionVector<MethodId> method_ids_;
- IndexedCollectionVector<ClassDef> class_defs_;
- IndexedCollectionVector<CallSiteId> call_site_ids_;
- IndexedCollectionVector<MethodHandleItem> method_handle_items_;
- IndexedCollectionVector<StringData> string_datas_;
- IndexedCollectionVector<TypeList> type_lists_;
- IndexedCollectionVector<EncodedArrayItem> encoded_array_items_;
- IndexedCollectionVector<AnnotationItem> annotation_items_;
- IndexedCollectionVector<AnnotationSetItem> annotation_set_items_;
- IndexedCollectionVector<AnnotationSetRefList> annotation_set_ref_lists_;
- IndexedCollectionVector<AnnotationsDirectoryItem> annotations_directory_items_;
- // The order of the vectors controls the layout of the output file by index order, to change the
- // layout just sort the vector. Note that you may only change the order of the non indexed vectors
- // below. Indexed vectors are accessed by indices in other places, changing the sorting order will
- // invalidate the existing indices and is not currently supported.
- CollectionVector<DebugInfoItem> debug_info_items_;
- CollectionVector<CodeItem> code_items_;
- CollectionVector<ClassData> class_datas_;
-
- // Note that the maps do not have ownership, the vectors do.
- // TODO: These maps should only be required for building the IR and should be put in a separate
- // IR builder class.
- CollectionMap<StringData> string_datas_map_;
- CollectionMap<TypeList> type_lists_map_;
- CollectionMap<EncodedArrayItem> encoded_array_items_map_;
- CollectionMap<AnnotationItem> annotation_items_map_;
- CollectionMap<AnnotationSetItem> annotation_set_items_map_;
- CollectionMap<AnnotationSetRefList> annotation_set_ref_lists_map_;
- CollectionMap<AnnotationsDirectoryItem> annotations_directory_items_map_;
- CollectionMap<DebugInfoItem> debug_info_items_map_;
- // Code item maps need to check both the debug info offset and debug info offset, do not use
- // CollectionMap.
- // First offset is the code item offset, second is the debug info offset.
- std::map<std::pair<uint32_t, uint32_t>, CodeItem*> code_items_map_;
- CollectionMap<ClassData> class_datas_map_;
-
- uint32_t map_list_offset_ = 0;
-
- // Link data.
- std::vector<uint8_t> link_data_;
-
- // If we eagerly assign offsets during IR building or later after layout. Must be false if
- // changing the layout is enabled.
- bool eagerly_assign_offsets_;
-
- DISALLOW_COPY_AND_ASSIGN(Collections);
-};
-
class Item {
public:
Item() { }
@@ -598,12 +389,12 @@
uint32_t num_class_defs)
: Item(0, kHeaderItemSize),
support_default_methods_(support_default_methods),
- collections_(num_string_ids,
- num_type_ids,
- num_proto_ids,
- num_field_ids,
- num_method_ids,
- num_class_defs) {
+ string_ids_(num_string_ids),
+ type_ids_(num_type_ids),
+ proto_ids_(num_proto_ids),
+ field_ids_(num_field_ids),
+ method_ids_(num_method_ids),
+ class_defs_(num_class_defs) {
ConstructorHelper(magic,
checksum,
signature,
@@ -641,7 +432,69 @@
void SetDataSize(uint32_t new_data_size) { data_size_ = new_data_size; }
void SetDataOffset(uint32_t new_data_offset) { data_offset_ = new_data_offset; }
- Collections& GetCollections() { return collections_; }
+ IndexedCollectionVector<StringId>& StringIds() { return string_ids_; }
+ const IndexedCollectionVector<StringId>& StringIds() const { return string_ids_; }
+ IndexedCollectionVector<TypeId>& TypeIds() { return type_ids_; }
+ const IndexedCollectionVector<TypeId>& TypeIds() const { return type_ids_; }
+ IndexedCollectionVector<ProtoId>& ProtoIds() { return proto_ids_; }
+ const IndexedCollectionVector<ProtoId>& ProtoIds() const { return proto_ids_; }
+ IndexedCollectionVector<FieldId>& FieldIds() { return field_ids_; }
+ const IndexedCollectionVector<FieldId>& FieldIds() const { return field_ids_; }
+ IndexedCollectionVector<MethodId>& MethodIds() { return method_ids_; }
+ const IndexedCollectionVector<MethodId>& MethodIds() const { return method_ids_; }
+ IndexedCollectionVector<ClassDef>& ClassDefs() { return class_defs_; }
+ const IndexedCollectionVector<ClassDef>& ClassDefs() const { return class_defs_; }
+ IndexedCollectionVector<CallSiteId>& CallSiteIds() { return call_site_ids_; }
+ const IndexedCollectionVector<CallSiteId>& CallSiteIds() const { return call_site_ids_; }
+ IndexedCollectionVector<MethodHandleItem>& MethodHandleItems() { return method_handle_items_; }
+ const IndexedCollectionVector<MethodHandleItem>& MethodHandleItems() const {
+ return method_handle_items_;
+ }
+ CollectionVector<StringData>& StringDatas() { return string_datas_; }
+ const CollectionVector<StringData>& StringDatas() const { return string_datas_; }
+ CollectionVector<TypeList>& TypeLists() { return type_lists_; }
+ const CollectionVector<TypeList>& TypeLists() const { return type_lists_; }
+ CollectionVector<EncodedArrayItem>& EncodedArrayItems() { return encoded_array_items_; }
+ const CollectionVector<EncodedArrayItem>& EncodedArrayItems() const {
+ return encoded_array_items_;
+ }
+ CollectionVector<AnnotationItem>& AnnotationItems() { return annotation_items_; }
+ const CollectionVector<AnnotationItem>& AnnotationItems() const { return annotation_items_; }
+ CollectionVector<AnnotationSetItem>& AnnotationSetItems() { return annotation_set_items_; }
+ const CollectionVector<AnnotationSetItem>& AnnotationSetItems() const {
+ return annotation_set_items_;
+ }
+ CollectionVector<AnnotationSetRefList>& AnnotationSetRefLists() {
+ return annotation_set_ref_lists_;
+ }
+ const CollectionVector<AnnotationSetRefList>& AnnotationSetRefLists() const {
+ return annotation_set_ref_lists_;
+ }
+ CollectionVector<AnnotationsDirectoryItem>& AnnotationsDirectoryItems() {
+ return annotations_directory_items_;
+ }
+ const CollectionVector<AnnotationsDirectoryItem>& AnnotationsDirectoryItems() const {
+ return annotations_directory_items_;
+ }
+ CollectionVector<DebugInfoItem>& DebugInfoItems() { return debug_info_items_; }
+ const CollectionVector<DebugInfoItem>& DebugInfoItems() const { return debug_info_items_; }
+ CollectionVector<CodeItem>& CodeItems() { return code_items_; }
+ const CollectionVector<CodeItem>& CodeItems() const { return code_items_; }
+ CollectionVector<ClassData>& ClassDatas() { return class_datas_; }
+ const CollectionVector<ClassData>& ClassDatas() const { return class_datas_; }
+
+ StringId* GetStringIdOrNullPtr(uint32_t index) {
+ return index == dex::kDexNoIndex ? nullptr : StringIds()[index];
+ }
+ TypeId* GetTypeIdOrNullPtr(uint16_t index) {
+ return index == DexFile::kDexNoIndex16 ? nullptr : TypeIds()[index];
+ }
+
+ uint32_t MapListOffset() const { return map_list_offset_; }
+ void SetMapListOffset(uint32_t new_offset) { map_list_offset_ = new_offset; }
+
+ const std::vector<uint8_t>& LinkData() const { return link_data_; }
+ void SetLinkData(std::vector<uint8_t>&& link_data) { link_data_ = std::move(link_data); }
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
@@ -683,7 +536,35 @@
memcpy(magic_, magic, sizeof(magic_));
memcpy(signature_, signature, sizeof(signature_));
}
- Collections collections_;
+
+ // Collection vectors own the IR data.
+ IndexedCollectionVector<StringId> string_ids_;
+ IndexedCollectionVector<TypeId> type_ids_;
+ IndexedCollectionVector<ProtoId> proto_ids_;
+ IndexedCollectionVector<FieldId> field_ids_;
+ IndexedCollectionVector<MethodId> method_ids_;
+ IndexedCollectionVector<ClassDef> class_defs_;
+ IndexedCollectionVector<CallSiteId> call_site_ids_;
+ IndexedCollectionVector<MethodHandleItem> method_handle_items_;
+ IndexedCollectionVector<StringData> string_datas_;
+ IndexedCollectionVector<TypeList> type_lists_;
+ IndexedCollectionVector<EncodedArrayItem> encoded_array_items_;
+ IndexedCollectionVector<AnnotationItem> annotation_items_;
+ IndexedCollectionVector<AnnotationSetItem> annotation_set_items_;
+ IndexedCollectionVector<AnnotationSetRefList> annotation_set_ref_lists_;
+ IndexedCollectionVector<AnnotationsDirectoryItem> annotations_directory_items_;
+ // The order of the vectors controls the layout of the output file by index order, to change the
+ // layout just sort the vector. Note that you may only change the order of the non indexed vectors
+ // below. Indexed vectors are accessed by indices in other places, changing the sorting order will
+ // invalidate the existing indices and is not currently supported.
+ CollectionVector<DebugInfoItem> debug_info_items_;
+ CollectionVector<CodeItem> code_items_;
+ CollectionVector<ClassData> class_datas_;
+
+ uint32_t map_list_offset_ = 0;
+
+ // Link data.
+ std::vector<uint8_t> link_data_;
DISALLOW_COPY_AND_ASSIGN(Header);
};
diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc
index 9468f76..a04a234 100644
--- a/dexlayout/dex_ir_builder.cc
+++ b/dexlayout/dex_ir_builder.cc
@@ -20,14 +20,226 @@
#include <vector>
#include "dex_ir_builder.h"
+
+#include "dex/code_item_accessors-inl.h"
+#include "dex/dex_file_exception_helpers.h"
#include "dexlayout.h"
namespace art {
namespace dex_ir {
-static void CheckAndSetRemainingOffsets(const DexFile& dex_file,
- Collections* collections,
- const Options& options);
+static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) {
+ uint64_t value = 0;
+ for (uint32_t i = 0; i <= length; i++) {
+ value |= static_cast<uint64_t>(*(*data)++) << (i * 8);
+ }
+ if (sign_extend) {
+ int shift = (7 - length) * 8;
+ return (static_cast<int64_t>(value) << shift) >> shift;
+ }
+ return value;
+}
+
+static uint32_t GetDebugInfoStreamSize(const uint8_t* debug_info_stream) {
+ const uint8_t* stream = debug_info_stream;
+ DecodeUnsignedLeb128(&stream); // line_start
+ uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
+ for (uint32_t i = 0; i < parameters_size; ++i) {
+ DecodeUnsignedLeb128P1(&stream); // Parameter name.
+ }
+
+ for (;;) {
+ uint8_t opcode = *stream++;
+ switch (opcode) {
+ case DexFile::DBG_END_SEQUENCE:
+ return stream - debug_info_stream; // end of stream.
+ case DexFile::DBG_ADVANCE_PC:
+ DecodeUnsignedLeb128(&stream); // addr_diff
+ break;
+ case DexFile::DBG_ADVANCE_LINE:
+ DecodeSignedLeb128(&stream); // line_diff
+ break;
+ case DexFile::DBG_START_LOCAL:
+ DecodeUnsignedLeb128(&stream); // register_num
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ DecodeUnsignedLeb128P1(&stream); // type_idx
+ break;
+ case DexFile::DBG_START_LOCAL_EXTENDED:
+ DecodeUnsignedLeb128(&stream); // register_num
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ DecodeUnsignedLeb128P1(&stream); // type_idx
+ DecodeUnsignedLeb128P1(&stream); // sig_idx
+ break;
+ case DexFile::DBG_END_LOCAL:
+ case DexFile::DBG_RESTART_LOCAL:
+ DecodeUnsignedLeb128(&stream); // register_num
+ break;
+ case DexFile::DBG_SET_PROLOGUE_END:
+ case DexFile::DBG_SET_EPILOGUE_BEGIN:
+ break;
+ case DexFile::DBG_SET_FILE: {
+ DecodeUnsignedLeb128P1(&stream); // name_idx
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+}
+
+template<class T> class CollectionMap : public CollectionBase {
+ public:
+ CollectionMap() = default;
+ virtual ~CollectionMap() OVERRIDE { }
+
+ template <class... Args>
+ T* CreateAndAddItem(CollectionVector<T>& vector,
+ bool eagerly_assign_offsets,
+ uint32_t offset,
+ Args&&... args) {
+ T* item = vector.CreateAndAddItem(std::forward<Args>(args)...);
+ DCHECK(!GetExistingObject(offset));
+ DCHECK(!item->OffsetAssigned());
+ if (eagerly_assign_offsets) {
+ item->SetOffset(offset);
+ }
+ AddItem(item, offset);
+ return item;
+ }
+
+ // Returns the existing item if it is already inserted, null otherwise.
+ T* GetExistingObject(uint32_t offset) {
+ auto it = collection_.find(offset);
+ return it != collection_.end() ? it->second : nullptr;
+ }
+
+ // Lower case for template interop with std::map.
+ uint32_t size() const { return collection_.size(); }
+ std::map<uint32_t, T*>& Collection() { return collection_; }
+
+ private:
+ std::map<uint32_t, T*> collection_;
+
+ // CollectionMaps do not own the objects they contain, therefore AddItem is supported
+ // rather than CreateAndAddItem.
+ void AddItem(T* object, uint32_t offset) {
+ auto it = collection_.emplace(offset, object);
+ CHECK(it.second) << "CollectionMap already has an object with offset " << offset << " "
+ << " and address " << it.first->second;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(CollectionMap);
+};
+
+class BuilderMaps {
+ public:
+ BuilderMaps(Header* header, bool eagerly_assign_offsets)
+ : header_(header), eagerly_assign_offsets_(eagerly_assign_offsets) { }
+
+ void CreateStringId(const DexFile& dex_file, uint32_t i);
+ void CreateTypeId(const DexFile& dex_file, uint32_t i);
+ void CreateProtoId(const DexFile& dex_file, uint32_t i);
+ void CreateFieldId(const DexFile& dex_file, uint32_t i);
+ void CreateMethodId(const DexFile& dex_file, uint32_t i);
+ void CreateClassDef(const DexFile& dex_file, uint32_t i);
+ void CreateCallSiteId(const DexFile& dex_file, uint32_t i);
+ void CreateMethodHandleItem(const DexFile& dex_file, uint32_t i);
+
+ void CreateCallSitesAndMethodHandles(const DexFile& dex_file);
+
+ TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset);
+ EncodedArrayItem* CreateEncodedArrayItem(const DexFile& dex_file,
+ const uint8_t* static_data,
+ uint32_t offset);
+ AnnotationItem* CreateAnnotationItem(const DexFile& dex_file,
+ const DexFile::AnnotationItem* annotation);
+ AnnotationSetItem* CreateAnnotationSetItem(const DexFile& dex_file,
+ const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset);
+ AnnotationsDirectoryItem* CreateAnnotationsDirectoryItem(const DexFile& dex_file,
+ const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset);
+ CodeItem* DedupeOrCreateCodeItem(const DexFile& dex_file,
+ 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);
+
+ void AddAnnotationsFromMapListSection(const DexFile& dex_file,
+ uint32_t start_offset,
+ uint32_t count);
+
+ void CheckAndSetRemainingOffsets(const DexFile& dex_file, const Options& options);
+
+ // Sort the vectors buy map order (same order that was used in the input file).
+ void SortVectorsByMapOrder();
+
+ private:
+ bool GetIdsFromByteCode(const CodeItem* code,
+ std::vector<TypeId*>* type_ids,
+ std::vector<StringId*>* string_ids,
+ std::vector<MethodId*>* method_ids,
+ std::vector<FieldId*>* field_ids);
+
+ bool GetIdFromInstruction(const Instruction* dec_insn,
+ std::vector<TypeId*>* type_ids,
+ std::vector<StringId*>* string_ids,
+ std::vector<MethodId*>* method_ids,
+ std::vector<FieldId*>* field_ids);
+
+ EncodedValue* ReadEncodedValue(const DexFile& dex_file, const uint8_t** data);
+ EncodedValue* ReadEncodedValue(const DexFile& dex_file,
+ const uint8_t** data,
+ uint8_t type,
+ uint8_t length);
+ void ReadEncodedValue(const DexFile& dex_file,
+ const uint8_t** data,
+ uint8_t type,
+ uint8_t length,
+ EncodedValue* item);
+
+ MethodItem GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii);
+
+ ParameterAnnotation* GenerateParameterAnnotation(
+ const DexFile& dex_file,
+ MethodId* method_id,
+ const DexFile::AnnotationSetRefList* annotation_set_ref_list,
+ uint32_t offset);
+
+ template <typename Type, class... Args>
+ Type* CreateAndAddIndexedItem(IndexedCollectionVector<Type>& vector,
+ uint32_t offset,
+ uint32_t index,
+ Args&&... args) {
+ Type* item = vector.CreateAndAddIndexedItem(index, std::forward<Args>(args)...);
+ DCHECK(!item->OffsetAssigned());
+ if (eagerly_assign_offsets_) {
+ item->SetOffset(offset);
+ }
+ return item;
+ }
+
+ Header* header_;
+ // If we eagerly assign offsets during IR building or later after layout. Must be false if
+ // changing the layout is enabled.
+ bool eagerly_assign_offsets_;
+
+ // Note: maps do not have ownership.
+ CollectionMap<StringData> string_datas_map_;
+ CollectionMap<TypeList> type_lists_map_;
+ CollectionMap<EncodedArrayItem> encoded_array_items_map_;
+ CollectionMap<AnnotationItem> annotation_items_map_;
+ CollectionMap<AnnotationSetItem> annotation_set_items_map_;
+ CollectionMap<AnnotationSetRefList> annotation_set_ref_lists_map_;
+ CollectionMap<AnnotationsDirectoryItem> annotations_directory_items_map_;
+ CollectionMap<DebugInfoItem> debug_info_items_map_;
+ // Code item maps need to check both the debug info offset and debug info offset, do not use
+ // CollectionMap.
+ // First offset is the code item offset, second is the debug info offset.
+ std::map<std::pair<uint32_t, uint32_t>, CodeItem*> code_items_map_;
+ CollectionMap<ClassData> class_datas_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(BuilderMaps);
+};
Header* DexIrBuilder(const DexFile& dex_file,
bool eagerly_assign_offsets,
@@ -50,36 +262,35 @@
dex_file.NumFieldIds(),
dex_file.NumMethodIds(),
dex_file.NumClassDefs());
- Collections& collections = header->GetCollections();
- collections.SetEagerlyAssignOffsets(eagerly_assign_offsets);
+ BuilderMaps builder_maps(header, eagerly_assign_offsets);
// Walk the rest of the header fields.
// StringId table.
- collections.SetStringIdsOffset(disk_header.string_ids_off_);
+ header->StringIds().SetOffset(disk_header.string_ids_off_);
for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) {
- collections.CreateStringId(dex_file, i);
+ builder_maps.CreateStringId(dex_file, i);
}
// TypeId table.
- collections.SetTypeIdsOffset(disk_header.type_ids_off_);
+ header->TypeIds().SetOffset(disk_header.type_ids_off_);
for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
- collections.CreateTypeId(dex_file, i);
+ builder_maps.CreateTypeId(dex_file, i);
}
// ProtoId table.
- collections.SetProtoIdsOffset(disk_header.proto_ids_off_);
+ header->ProtoIds().SetOffset(disk_header.proto_ids_off_);
for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) {
- collections.CreateProtoId(dex_file, i);
+ builder_maps.CreateProtoId(dex_file, i);
}
// FieldId table.
- collections.SetFieldIdsOffset(disk_header.field_ids_off_);
+ header->FieldIds().SetOffset(disk_header.field_ids_off_);
for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) {
- collections.CreateFieldId(dex_file, i);
+ builder_maps.CreateFieldId(dex_file, i);
}
// MethodId table.
- collections.SetMethodIdsOffset(disk_header.method_ids_off_);
+ header->MethodIds().SetOffset(disk_header.method_ids_off_);
for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) {
- collections.CreateMethodId(dex_file, i);
+ builder_maps.CreateMethodId(dex_file, i);
}
// ClassDef table.
- collections.SetClassDefsOffset(disk_header.class_defs_off_);
+ header->ClassDefs().SetOffset(disk_header.class_defs_off_);
for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
if (!options.class_filter_.empty()) {
// If the filter is enabled (not empty), filter out classes that don't have a matching
@@ -90,29 +301,29 @@
continue;
}
}
- collections.CreateClassDef(dex_file, i);
+ builder_maps.CreateClassDef(dex_file, i);
}
// MapItem.
- collections.SetMapListOffset(disk_header.map_off_);
+ header->SetMapListOffset(disk_header.map_off_);
// CallSiteIds and MethodHandleItems.
- collections.CreateCallSitesAndMethodHandles(dex_file);
- CheckAndSetRemainingOffsets(dex_file, &collections, options);
+ builder_maps.CreateCallSitesAndMethodHandles(dex_file);
+ builder_maps.CheckAndSetRemainingOffsets(dex_file, options);
// Sort the vectors by the map order (same order as the file).
- collections.SortVectorsByMapOrder();
- collections.ClearMaps();
+ builder_maps.SortVectorsByMapOrder();
// Load the link data if it exists.
- collections.SetLinkData(std::vector<uint8_t>(
+ header->SetLinkData(std::vector<uint8_t>(
dex_file.DataBegin() + dex_file.GetHeader().link_off_,
dex_file.DataBegin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_));
return header;
}
-static void CheckAndSetRemainingOffsets(const DexFile& dex_file,
- Collections* collections,
- const Options& options) {
+/*
+ * Get all the types, strings, methods, and fields referred to from bytecode.
+ */
+void BuilderMaps::CheckAndSetRemainingOffsets(const DexFile& dex_file, const Options& options) {
const DexFile::Header& disk_header = dex_file.GetHeader();
// Read MapItems and validate/set remaining offsets.
const DexFile::MapList* map = dex_file.GetMapList();
@@ -125,74 +336,74 @@
CHECK_EQ(item->offset_, 0u);
break;
case DexFile::kDexTypeStringIdItem:
- CHECK_EQ(item->size_, collections->StringIdsSize());
- CHECK_EQ(item->offset_, collections->StringIdsOffset());
+ CHECK_EQ(item->size_, header_->StringIds().Size());
+ CHECK_EQ(item->offset_, header_->StringIds().GetOffset());
break;
case DexFile::kDexTypeTypeIdItem:
- CHECK_EQ(item->size_, collections->TypeIdsSize());
- CHECK_EQ(item->offset_, collections->TypeIdsOffset());
+ CHECK_EQ(item->size_, header_->TypeIds().Size());
+ CHECK_EQ(item->offset_, header_->TypeIds().GetOffset());
break;
case DexFile::kDexTypeProtoIdItem:
- CHECK_EQ(item->size_, collections->ProtoIdsSize());
- CHECK_EQ(item->offset_, collections->ProtoIdsOffset());
+ CHECK_EQ(item->size_, header_->ProtoIds().Size());
+ CHECK_EQ(item->offset_, header_->ProtoIds().GetOffset());
break;
case DexFile::kDexTypeFieldIdItem:
- CHECK_EQ(item->size_, collections->FieldIdsSize());
- CHECK_EQ(item->offset_, collections->FieldIdsOffset());
+ CHECK_EQ(item->size_, header_->FieldIds().Size());
+ CHECK_EQ(item->offset_, header_->FieldIds().GetOffset());
break;
case DexFile::kDexTypeMethodIdItem:
- CHECK_EQ(item->size_, collections->MethodIdsSize());
- CHECK_EQ(item->offset_, collections->MethodIdsOffset());
+ CHECK_EQ(item->size_, header_->MethodIds().Size());
+ CHECK_EQ(item->offset_, header_->MethodIds().GetOffset());
break;
case DexFile::kDexTypeClassDefItem:
if (options.class_filter_.empty()) {
// The filter may have removed some classes, this will get fixed up during writing.
- CHECK_EQ(item->size_, collections->ClassDefsSize());
+ CHECK_EQ(item->size_, header_->ClassDefs().Size());
}
- CHECK_EQ(item->offset_, collections->ClassDefsOffset());
+ CHECK_EQ(item->offset_, header_->ClassDefs().GetOffset());
break;
case DexFile::kDexTypeCallSiteIdItem:
- CHECK_EQ(item->size_, collections->CallSiteIdsSize());
- CHECK_EQ(item->offset_, collections->CallSiteIdsOffset());
+ CHECK_EQ(item->size_, header_->CallSiteIds().Size());
+ CHECK_EQ(item->offset_, header_->CallSiteIds().GetOffset());
break;
case DexFile::kDexTypeMethodHandleItem:
- CHECK_EQ(item->size_, collections->MethodHandleItemsSize());
- CHECK_EQ(item->offset_, collections->MethodHandleItemsOffset());
+ CHECK_EQ(item->size_, header_->MethodHandleItems().Size());
+ CHECK_EQ(item->offset_, header_->MethodHandleItems().GetOffset());
break;
case DexFile::kDexTypeMapList:
CHECK_EQ(item->size_, 1u);
CHECK_EQ(item->offset_, disk_header.map_off_);
break;
case DexFile::kDexTypeTypeList:
- collections->SetTypeListsOffset(item->offset_);
+ header_->TypeLists().SetOffset(item->offset_);
break;
case DexFile::kDexTypeAnnotationSetRefList:
- collections->SetAnnotationSetRefListsOffset(item->offset_);
+ header_->AnnotationSetRefLists().SetOffset(item->offset_);
break;
case DexFile::kDexTypeAnnotationSetItem:
- collections->SetAnnotationSetItemsOffset(item->offset_);
+ header_->AnnotationSetItems().SetOffset(item->offset_);
break;
case DexFile::kDexTypeClassDataItem:
- collections->SetClassDatasOffset(item->offset_);
+ header_->ClassDatas().SetOffset(item->offset_);
break;
case DexFile::kDexTypeCodeItem:
- collections->SetCodeItemsOffset(item->offset_);
+ header_->CodeItems().SetOffset(item->offset_);
break;
case DexFile::kDexTypeStringDataItem:
- collections->SetStringDatasOffset(item->offset_);
+ header_->StringDatas().SetOffset(item->offset_);
break;
case DexFile::kDexTypeDebugInfoItem:
- collections->SetDebugInfoItemsOffset(item->offset_);
+ header_->DebugInfoItems().SetOffset(item->offset_);
break;
case DexFile::kDexTypeAnnotationItem:
- collections->SetAnnotationItemsOffset(item->offset_);
- collections->AddAnnotationsFromMapListSection(dex_file, item->offset_, item->size_);
+ header_->AnnotationItems().SetOffset(item->offset_);
+ AddAnnotationsFromMapListSection(dex_file, item->offset_, item->size_);
break;
case DexFile::kDexTypeEncodedArrayItem:
- collections->SetEncodedArrayItemsOffset(item->offset_);
+ header_->EncodedArrayItems().SetOffset(item->offset_);
break;
case DexFile::kDexTypeAnnotationsDirectoryItem:
- collections->SetAnnotationsDirectoryItemsOffset(item->offset_);
+ header_->AnnotationsDirectoryItems().SetOffset(item->offset_);
break;
default:
LOG(ERROR) << "Unknown map list item type.";
@@ -200,5 +411,798 @@
}
}
+void BuilderMaps::CreateStringId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i));
+ StringData* string_data =
+ string_datas_map_.CreateAndAddItem(header_->StringDatas(),
+ eagerly_assign_offsets_,
+ disk_string_id.string_data_off_,
+ dex_file.GetStringData(disk_string_id));
+ CreateAndAddIndexedItem(header_->StringIds(),
+ header_->StringIds().GetOffset() + i * StringId::ItemSize(),
+ i,
+ string_data);
+}
+
+void BuilderMaps::CreateTypeId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i));
+ CreateAndAddIndexedItem(header_->TypeIds(),
+ header_->TypeIds().GetOffset() + i * TypeId::ItemSize(),
+ i,
+ header_->StringIds()[disk_type_id.descriptor_idx_.index_]);
+}
+
+void BuilderMaps::CreateProtoId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(dex::ProtoIndex(i));
+ const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
+ TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_);
+
+ CreateAndAddIndexedItem(header_->ProtoIds(),
+ header_->ProtoIds().GetOffset() + i * ProtoId::ItemSize(),
+ i,
+ header_->StringIds()[disk_proto_id.shorty_idx_.index_],
+ header_->TypeIds()[disk_proto_id.return_type_idx_.index_],
+ parameter_type_list);
+}
+
+void BuilderMaps::CreateFieldId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
+ CreateAndAddIndexedItem(header_->FieldIds(),
+ header_->FieldIds().GetOffset() + i * FieldId::ItemSize(),
+ i,
+ header_->TypeIds()[disk_field_id.class_idx_.index_],
+ header_->TypeIds()[disk_field_id.type_idx_.index_],
+ header_->StringIds()[disk_field_id.name_idx_.index_]);
+}
+
+void BuilderMaps::CreateMethodId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
+ CreateAndAddIndexedItem(header_->MethodIds(),
+ header_->MethodIds().GetOffset() + i * MethodId::ItemSize(),
+ i,
+ header_->TypeIds()[disk_method_id.class_idx_.index_],
+ header_->ProtoIds()[disk_method_id.proto_idx_.index_],
+ header_->StringIds()[disk_method_id.name_idx_.index_]);
+}
+
+void BuilderMaps::CreateClassDef(const DexFile& dex_file, uint32_t i) {
+ const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
+ const TypeId* class_type = header_->TypeIds()[disk_class_def.class_idx_.index_];
+ uint32_t access_flags = disk_class_def.access_flags_;
+ const TypeId* superclass = header_->GetTypeIdOrNullPtr(disk_class_def.superclass_idx_.index_);
+
+ const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
+ TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_);
+
+ const StringId* source_file =
+ header_->GetStringIdOrNullPtr(disk_class_def.source_file_idx_.index_);
+ // Annotations.
+ AnnotationsDirectoryItem* annotations = nullptr;
+ const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
+ dex_file.GetAnnotationsDirectory(disk_class_def);
+ if (disk_annotations_directory_item != nullptr) {
+ annotations = CreateAnnotationsDirectoryItem(
+ dex_file, disk_annotations_directory_item, disk_class_def.annotations_off_);
+ }
+ // Static field initializers.
+ 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_);
+ CreateAndAddIndexedItem(header_->ClassDefs(),
+ header_->ClassDefs().GetOffset() + i * ClassDef::ItemSize(),
+ i,
+ class_type,
+ access_flags,
+ superclass,
+ interfaces_type_list,
+ source_file,
+ annotations,
+ static_values,
+ class_data);
+}
+
+void BuilderMaps::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i);
+ const uint8_t* disk_call_item_ptr = dex_file.DataBegin() + disk_call_site_id.data_off_;
+ EncodedArrayItem* call_site_item =
+ CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_);
+
+ CreateAndAddIndexedItem(header_->CallSiteIds(),
+ header_->CallSiteIds().GetOffset() + i * CallSiteId::ItemSize(),
+ i,
+ call_site_item);
+}
+
+void BuilderMaps::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
+ const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i);
+ uint16_t index = disk_method_handle.field_or_method_idx_;
+ DexFile::MethodHandleType type =
+ static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_);
+ bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic ||
+ type == DexFile::MethodHandleType::kInvokeInstance ||
+ type == DexFile::MethodHandleType::kInvokeConstructor ||
+ type == DexFile::MethodHandleType::kInvokeDirect ||
+ type == DexFile::MethodHandleType::kInvokeInterface;
+ static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeInterface,
+ "Unexpected method handle types.");
+ IndexedItem* field_or_method_id;
+ if (is_invoke) {
+ field_or_method_id = header_->MethodIds()[index];
+ } else {
+ field_or_method_id = header_->FieldIds()[index];
+ }
+ CreateAndAddIndexedItem(header_->MethodHandleItems(),
+ header_->MethodHandleItems().GetOffset() +
+ i * MethodHandleItem::ItemSize(),
+ i,
+ type,
+ field_or_method_id);
+}
+
+void BuilderMaps::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
+ // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems.
+ const DexFile::MapList* map = dex_file.GetMapList();
+ for (uint32_t i = 0; i < map->size_; ++i) {
+ const DexFile::MapItem* item = map->list_ + i;
+ switch (item->type_) {
+ case DexFile::kDexTypeCallSiteIdItem:
+ header_->CallSiteIds().SetOffset(item->offset_);
+ break;
+ case DexFile::kDexTypeMethodHandleItem:
+ header_->MethodHandleItems().SetOffset(item->offset_);
+ break;
+ default:
+ break;
+ }
+ }
+ // Populate MethodHandleItems first (CallSiteIds may depend on them).
+ for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) {
+ CreateMethodHandleItem(dex_file, i);
+ }
+ // Populate CallSiteIds.
+ for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) {
+ CreateCallSiteId(dex_file, i);
+ }
+}
+
+TypeList* BuilderMaps::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) {
+ if (dex_type_list == nullptr) {
+ return nullptr;
+ }
+ TypeList* type_list = type_lists_map_.GetExistingObject(offset);
+ if (type_list == nullptr) {
+ TypeIdVector* type_vector = new TypeIdVector();
+ uint32_t size = dex_type_list->Size();
+ for (uint32_t index = 0; index < size; ++index) {
+ type_vector->push_back(header_->TypeIds()[
+ dex_type_list->GetTypeItem(index).type_idx_.index_]);
+ }
+ type_list = type_lists_map_.CreateAndAddItem(header_->TypeLists(),
+ eagerly_assign_offsets_,
+ offset,
+ type_vector);
+ }
+ return type_list;
+}
+
+EncodedArrayItem* BuilderMaps::CreateEncodedArrayItem(const DexFile& dex_file,
+ const uint8_t* static_data,
+ uint32_t offset) {
+ if (static_data == nullptr) {
+ return nullptr;
+ }
+ EncodedArrayItem* encoded_array_item = encoded_array_items_map_.GetExistingObject(offset);
+ if (encoded_array_item == nullptr) {
+ uint32_t size = DecodeUnsignedLeb128(&static_data);
+ EncodedValueVector* values = new EncodedValueVector();
+ for (uint32_t i = 0; i < size; ++i) {
+ values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, &static_data)));
+ }
+ // TODO: Calculate the size of the encoded array.
+ encoded_array_item = encoded_array_items_map_.CreateAndAddItem(header_->EncodedArrayItems(),
+ eagerly_assign_offsets_,
+ offset,
+ values);
+ }
+ return encoded_array_item;
+}
+
+void BuilderMaps::AddAnnotationsFromMapListSection(const DexFile& dex_file,
+ uint32_t start_offset,
+ uint32_t count) {
+ uint32_t current_offset = start_offset;
+ for (size_t i = 0; i < count; ++i) {
+ // Annotation that we didn't process already, add it to the set.
+ const DexFile::AnnotationItem* annotation = dex_file.GetAnnotationItemAtOffset(current_offset);
+ AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation);
+ DCHECK(annotation_item != nullptr);
+ current_offset += annotation_item->GetSize();
+ }
+}
+
+AnnotationItem* BuilderMaps::CreateAnnotationItem(const DexFile& dex_file,
+ const DexFile::AnnotationItem* annotation) {
+ const uint8_t* const start_data = reinterpret_cast<const uint8_t*>(annotation);
+ const uint32_t offset = start_data - dex_file.DataBegin();
+ AnnotationItem* annotation_item = annotation_items_map_.GetExistingObject(offset);
+ if (annotation_item == nullptr) {
+ uint8_t visibility = annotation->visibility_;
+ const uint8_t* annotation_data = annotation->annotation_;
+ std::unique_ptr<EncodedValue> encoded_value(
+ ReadEncodedValue(dex_file, &annotation_data, DexFile::kDexAnnotationAnnotation, 0));
+ annotation_item =
+ annotation_items_map_.CreateAndAddItem(header_->AnnotationItems(),
+ eagerly_assign_offsets_,
+ offset,
+ visibility,
+ encoded_value->ReleaseEncodedAnnotation());
+ annotation_item->SetSize(annotation_data - start_data);
+ }
+ return annotation_item;
+}
+
+
+AnnotationSetItem* BuilderMaps::CreateAnnotationSetItem(const DexFile& dex_file,
+ const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset) {
+ if (disk_annotations_item == nullptr || (disk_annotations_item->size_ == 0 && offset == 0)) {
+ return nullptr;
+ }
+ AnnotationSetItem* annotation_set_item = annotation_set_items_map_.GetExistingObject(offset);
+ if (annotation_set_item == nullptr) {
+ std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
+ for (uint32_t i = 0; i < disk_annotations_item->size_; ++i) {
+ const DexFile::AnnotationItem* annotation =
+ dex_file.GetAnnotationItem(disk_annotations_item, i);
+ if (annotation == nullptr) {
+ continue;
+ }
+ AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation);
+ items->push_back(annotation_item);
+ }
+ annotation_set_item =
+ annotation_set_items_map_.CreateAndAddItem(header_->AnnotationSetItems(),
+ eagerly_assign_offsets_,
+ offset,
+ items);
+ }
+ return annotation_set_item;
+}
+
+AnnotationsDirectoryItem* BuilderMaps::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
+ const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
+ AnnotationsDirectoryItem* annotations_directory_item =
+ annotations_directory_items_map_.GetExistingObject(offset);
+ if (annotations_directory_item != nullptr) {
+ return annotations_directory_item;
+ }
+ const DexFile::AnnotationSetItem* class_set_item =
+ dex_file.GetClassAnnotationSet(disk_annotations_item);
+ AnnotationSetItem* class_annotation = nullptr;
+ if (class_set_item != nullptr) {
+ uint32_t item_offset = disk_annotations_item->class_annotations_off_;
+ class_annotation = CreateAnnotationSetItem(dex_file, class_set_item, item_offset);
+ }
+ const DexFile::FieldAnnotationsItem* fields =
+ dex_file.GetFieldAnnotations(disk_annotations_item);
+ FieldAnnotationVector* field_annotations = nullptr;
+ if (fields != nullptr) {
+ field_annotations = new FieldAnnotationVector();
+ for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
+ FieldId* field_id = header_->FieldIds()[fields[i].field_idx_];
+ const DexFile::AnnotationSetItem* field_set_item =
+ dex_file.GetFieldAnnotationSetItem(fields[i]);
+ uint32_t annotation_set_offset = fields[i].annotations_off_;
+ AnnotationSetItem* annotation_set_item =
+ CreateAnnotationSetItem(dex_file, field_set_item, annotation_set_offset);
+ field_annotations->push_back(std::unique_ptr<FieldAnnotation>(
+ new FieldAnnotation(field_id, annotation_set_item)));
+ }
+ }
+ const DexFile::MethodAnnotationsItem* methods =
+ dex_file.GetMethodAnnotations(disk_annotations_item);
+ MethodAnnotationVector* method_annotations = nullptr;
+ if (methods != nullptr) {
+ method_annotations = new MethodAnnotationVector();
+ for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
+ MethodId* method_id = header_->MethodIds()[methods[i].method_idx_];
+ const DexFile::AnnotationSetItem* method_set_item =
+ dex_file.GetMethodAnnotationSetItem(methods[i]);
+ uint32_t annotation_set_offset = methods[i].annotations_off_;
+ AnnotationSetItem* annotation_set_item =
+ CreateAnnotationSetItem(dex_file, method_set_item, annotation_set_offset);
+ method_annotations->push_back(std::unique_ptr<MethodAnnotation>(
+ new MethodAnnotation(method_id, annotation_set_item)));
+ }
+ }
+ const DexFile::ParameterAnnotationsItem* parameters =
+ dex_file.GetParameterAnnotations(disk_annotations_item);
+ ParameterAnnotationVector* parameter_annotations = nullptr;
+ if (parameters != nullptr) {
+ parameter_annotations = new ParameterAnnotationVector();
+ for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
+ MethodId* method_id = header_->MethodIds()[parameters[i].method_idx_];
+ const DexFile::AnnotationSetRefList* list =
+ dex_file.GetParameterAnnotationSetRefList(¶meters[i]);
+ parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
+ GenerateParameterAnnotation(dex_file, method_id, list, parameters[i].annotations_off_)));
+ }
+ }
+ // TODO: Calculate the size of the annotations directory.
+ return annotations_directory_items_map_.CreateAndAddItem(header_->AnnotationsDirectoryItems(),
+ eagerly_assign_offsets_,
+ offset,
+ class_annotation,
+ field_annotations,
+ method_annotations,
+ parameter_annotations);
+}
+
+CodeItem* BuilderMaps::DedupeOrCreateCodeItem(const DexFile& dex_file,
+ const DexFile::CodeItem* disk_code_item,
+ uint32_t offset,
+ uint32_t dex_method_index) {
+ if (disk_code_item == nullptr) {
+ return nullptr;
+ }
+ CodeItemDebugInfoAccessor accessor(dex_file, disk_code_item, dex_method_index);
+ const uint32_t debug_info_offset = accessor.DebugInfoOffset();
+
+ // Create the offsets pair and dedupe based on it.
+ std::pair<uint32_t, uint32_t> offsets_pair(offset, debug_info_offset);
+ auto existing = code_items_map_.find(offsets_pair);
+ if (existing != code_items_map_.end()) {
+ return existing->second;
+ }
+
+ const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(debug_info_offset);
+ DebugInfoItem* debug_info = nullptr;
+ if (debug_info_stream != nullptr) {
+ debug_info = debug_info_items_map_.GetExistingObject(debug_info_offset);
+ if (debug_info == nullptr) {
+ uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream);
+ uint8_t* debug_info_buffer = new uint8_t[debug_info_size];
+ memcpy(debug_info_buffer, debug_info_stream, debug_info_size);
+ debug_info = debug_info_items_map_.CreateAndAddItem(header_->DebugInfoItems(),
+ eagerly_assign_offsets_,
+ debug_info_offset,
+ debug_info_size,
+ debug_info_buffer);
+ }
+ }
+
+ uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
+ uint16_t* insns = new uint16_t[insns_size];
+ memcpy(insns, accessor.Insns(), insns_size * sizeof(uint16_t));
+
+ TryItemVector* tries = nullptr;
+ CatchHandlerVector* handler_list = nullptr;
+ if (accessor.TriesSize() > 0) {
+ tries = new TryItemVector();
+ handler_list = new CatchHandlerVector();
+ for (const DexFile::TryItem& disk_try_item : accessor.TryItems()) {
+ uint32_t start_addr = disk_try_item.start_addr_;
+ uint16_t insn_count = disk_try_item.insn_count_;
+ uint16_t handler_off = disk_try_item.handler_off_;
+ const CatchHandler* handlers = nullptr;
+ for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
+ if (handler_off == existing_handlers->GetListOffset()) {
+ handlers = existing_handlers.get();
+ break;
+ }
+ }
+ if (handlers == nullptr) {
+ bool catch_all = false;
+ TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
+ for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) {
+ const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
+ const TypeId* type_id = header_->GetTypeIdOrNullPtr(type_index.index_);
+ catch_all |= type_id == nullptr;
+ addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>(
+ new TypeAddrPair(type_id, it.GetHandlerAddress())));
+ }
+ handlers = new CatchHandler(catch_all, handler_off, addr_pairs);
+ handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers));
+ }
+ TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
+ tries->push_back(std::unique_ptr<const TryItem>(try_item));
+ }
+ // Manually walk catch handlers list and add any missing handlers unreferenced by try items.
+ const uint8_t* handlers_base = accessor.GetCatchHandlerData();
+ const uint8_t* handlers_data = handlers_base;
+ uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data);
+ while (handlers_size > handler_list->size()) {
+ bool already_added = false;
+ uint16_t handler_off = handlers_data - handlers_base;
+ for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
+ if (handler_off == existing_handlers->GetListOffset()) {
+ already_added = true;
+ break;
+ }
+ }
+ int32_t size = DecodeSignedLeb128(&handlers_data);
+ bool has_catch_all = size <= 0;
+ if (has_catch_all) {
+ size = -size;
+ }
+ if (already_added) {
+ for (int32_t i = 0; i < size; i++) {
+ DecodeUnsignedLeb128(&handlers_data);
+ DecodeUnsignedLeb128(&handlers_data);
+ }
+ if (has_catch_all) {
+ DecodeUnsignedLeb128(&handlers_data);
+ }
+ continue;
+ }
+ TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
+ for (int32_t i = 0; i < size; i++) {
+ const TypeId* type_id =
+ header_->GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data));
+ uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
+ addr_pairs->push_back(
+ std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr)));
+ }
+ if (has_catch_all) {
+ uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
+ addr_pairs->push_back(
+ std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr)));
+ }
+ const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs);
+ handler_list->push_back(std::unique_ptr<const CatchHandler>(handler));
+ }
+ }
+
+ uint32_t size = dex_file.GetCodeItemSize(*disk_code_item);
+ CodeItem* code_item = header_->CodeItems().CreateAndAddItem(accessor.RegistersSize(),
+ accessor.InsSize(),
+ accessor.OutsSize(),
+ debug_info,
+ insns_size,
+ insns,
+ tries,
+ handler_list);
+ code_item->SetSize(size);
+
+ // Add the code item to the map.
+ DCHECK(!code_item->OffsetAssigned());
+ if (eagerly_assign_offsets_) {
+ code_item->SetOffset(offset);
+ }
+ code_items_map_.emplace(offsets_pair, code_item);
+
+ // Add "fixup" references to types, strings, methods, and fields.
+ // This is temporary, as we will probably want more detailed parsing of the
+ // instructions here.
+ std::vector<TypeId*> type_ids;
+ std::vector<StringId*> string_ids;
+ std::vector<MethodId*> method_ids;
+ std::vector<FieldId*> field_ids;
+ if (GetIdsFromByteCode(code_item,
+ /*out*/ &type_ids,
+ /*out*/ &string_ids,
+ /*out*/ &method_ids,
+ /*out*/ &field_ids)) {
+ CodeFixups* fixups = new CodeFixups(std::move(type_ids),
+ std::move(string_ids),
+ std::move(method_ids),
+ std::move(field_ids));
+ code_item->SetCodeFixups(fixups);
+ }
+
+ return code_item;
+}
+
+ClassData* BuilderMaps::CreateClassData(
+ const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
+ // Read the fields and methods defined by the class, resolving the circular reference from those
+ // to classes by setting class at the same time.
+ ClassData* class_data = class_datas_map_.GetExistingObject(offset);
+ if (class_data == nullptr && encoded_data != nullptr) {
+ ClassDataItemIterator cdii(dex_file, encoded_data);
+ // 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();
+ 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();
+ 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));
+ }
+ // Virtual methods.
+ MethodItemVector* virtual_methods = new MethodItemVector();
+ for (; cdii.HasNextVirtualMethod(); cdii.Next()) {
+ virtual_methods->push_back(GenerateMethodItem(dex_file, cdii));
+ }
+ class_data = class_datas_map_.CreateAndAddItem(header_->ClassDatas(),
+ eagerly_assign_offsets_,
+ offset,
+ static_fields,
+ instance_fields,
+ direct_methods,
+ virtual_methods);
+ class_data->SetSize(cdii.EndDataPointer() - encoded_data);
+ }
+ return class_data;
+}
+
+void BuilderMaps::SortVectorsByMapOrder() {
+ header_->StringDatas().SortByMapOrder(string_datas_map_.Collection());
+ header_->TypeLists().SortByMapOrder(type_lists_map_.Collection());
+ header_->EncodedArrayItems().SortByMapOrder(encoded_array_items_map_.Collection());
+ header_->AnnotationItems().SortByMapOrder(annotation_items_map_.Collection());
+ header_->AnnotationSetItems().SortByMapOrder(annotation_set_items_map_.Collection());
+ header_->AnnotationSetRefLists().SortByMapOrder(annotation_set_ref_lists_map_.Collection());
+ header_->AnnotationsDirectoryItems().SortByMapOrder(
+ annotations_directory_items_map_.Collection());
+ header_->DebugInfoItems().SortByMapOrder(debug_info_items_map_.Collection());
+ header_->CodeItems().SortByMapOrder(code_items_map_);
+ header_->ClassDatas().SortByMapOrder(class_datas_map_.Collection());
+}
+
+bool BuilderMaps::GetIdsFromByteCode(const CodeItem* code,
+ std::vector<TypeId*>* type_ids,
+ std::vector<StringId*>* string_ids,
+ std::vector<MethodId*>* method_ids,
+ std::vector<FieldId*>* field_ids) {
+ bool has_id = false;
+ IterationRange<DexInstructionIterator> instructions = code->Instructions();
+ SafeDexInstructionIterator it(instructions.begin(), instructions.end());
+ for (; !it.IsErrorState() && it < instructions.end(); ++it) {
+ // In case the instruction goes past the end of the code item, make sure to not process it.
+ SafeDexInstructionIterator next = it;
+ ++next;
+ if (next.IsErrorState()) {
+ break;
+ }
+ has_id |= GetIdFromInstruction(&it.Inst(), type_ids, string_ids, method_ids, field_ids);
+ } // for
+ return has_id;
+}
+
+bool BuilderMaps::GetIdFromInstruction(const Instruction* dec_insn,
+ std::vector<TypeId*>* type_ids,
+ std::vector<StringId*>* string_ids,
+ std::vector<MethodId*>* method_ids,
+ std::vector<FieldId*>* field_ids) {
+ // Determine index and width of the string.
+ uint32_t index = 0;
+ switch (Instruction::FormatOf(dec_insn->Opcode())) {
+ // SOME NOT SUPPORTED:
+ // case Instruction::k20bc:
+ case Instruction::k21c:
+ case Instruction::k35c:
+ // case Instruction::k35ms:
+ case Instruction::k3rc:
+ // case Instruction::k3rms:
+ // case Instruction::k35mi:
+ // case Instruction::k3rmi:
+ case Instruction::k45cc:
+ case Instruction::k4rcc:
+ index = dec_insn->VRegB();
+ break;
+ case Instruction::k31c:
+ index = dec_insn->VRegB();
+ break;
+ case Instruction::k22c:
+ // case Instruction::k22cs:
+ index = dec_insn->VRegC();
+ break;
+ default:
+ break;
+ } // switch
+
+ // Determine index type, and add reference to the appropriate collection.
+ switch (Instruction::IndexTypeOf(dec_insn->Opcode())) {
+ case Instruction::kIndexTypeRef:
+ if (index < header_->TypeIds().Size()) {
+ type_ids->push_back(header_->TypeIds()[index]);
+ return true;
+ }
+ break;
+ case Instruction::kIndexStringRef:
+ if (index < header_->StringIds().Size()) {
+ string_ids->push_back(header_->StringIds()[index]);
+ return true;
+ }
+ break;
+ case Instruction::kIndexMethodRef:
+ case Instruction::kIndexMethodAndProtoRef:
+ if (index < header_->MethodIds().Size()) {
+ method_ids->push_back(header_->MethodIds()[index]);
+ return true;
+ }
+ break;
+ case Instruction::kIndexFieldRef:
+ if (index < header_->FieldIds().Size()) {
+ field_ids->push_back(header_->FieldIds()[index]);
+ return true;
+ }
+ break;
+ case Instruction::kIndexUnknown:
+ case Instruction::kIndexNone:
+ case Instruction::kIndexVtableOffset:
+ case Instruction::kIndexFieldOffset:
+ default:
+ break;
+ } // switch
+ return false;
+}
+
+EncodedValue* BuilderMaps::ReadEncodedValue(const DexFile& dex_file, const uint8_t** data) {
+ const uint8_t encoded_value = *(*data)++;
+ const uint8_t type = encoded_value & 0x1f;
+ EncodedValue* item = new EncodedValue(type);
+ ReadEncodedValue(dex_file, data, type, encoded_value >> 5, item);
+ return item;
+}
+
+EncodedValue* BuilderMaps::ReadEncodedValue(const DexFile& dex_file,
+ const uint8_t** data,
+ uint8_t type,
+ uint8_t length) {
+ EncodedValue* item = new EncodedValue(type);
+ ReadEncodedValue(dex_file, data, type, length, item);
+ return item;
+}
+
+void BuilderMaps::ReadEncodedValue(const DexFile& dex_file,
+ const uint8_t** data,
+ uint8_t type,
+ uint8_t length,
+ EncodedValue* item) {
+ switch (type) {
+ case DexFile::kDexAnnotationByte:
+ item->SetByte(static_cast<int8_t>(ReadVarWidth(data, length, false)));
+ break;
+ case DexFile::kDexAnnotationShort:
+ item->SetShort(static_cast<int16_t>(ReadVarWidth(data, length, true)));
+ break;
+ case DexFile::kDexAnnotationChar:
+ item->SetChar(static_cast<uint16_t>(ReadVarWidth(data, length, false)));
+ break;
+ case DexFile::kDexAnnotationInt:
+ item->SetInt(static_cast<int32_t>(ReadVarWidth(data, length, true)));
+ break;
+ case DexFile::kDexAnnotationLong:
+ item->SetLong(static_cast<int64_t>(ReadVarWidth(data, length, true)));
+ break;
+ case DexFile::kDexAnnotationFloat: {
+ // Fill on right.
+ union {
+ float f;
+ uint32_t data;
+ } conv;
+ conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
+ item->SetFloat(conv.f);
+ break;
+ }
+ case DexFile::kDexAnnotationDouble: {
+ // Fill on right.
+ union {
+ double d;
+ uint64_t data;
+ } conv;
+ conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
+ item->SetDouble(conv.d);
+ break;
+ }
+ case DexFile::kDexAnnotationMethodType: {
+ const uint32_t proto_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetProtoId(header_->ProtoIds()[proto_index]);
+ break;
+ }
+ case DexFile::kDexAnnotationMethodHandle: {
+ const uint32_t method_handle_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetMethodHandle(header_->MethodHandleItems()[method_handle_index]);
+ break;
+ }
+ case DexFile::kDexAnnotationString: {
+ const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetStringId(header_->StringIds()[string_index]);
+ break;
+ }
+ case DexFile::kDexAnnotationType: {
+ const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetTypeId(header_->TypeIds()[string_index]);
+ break;
+ }
+ case DexFile::kDexAnnotationField:
+ case DexFile::kDexAnnotationEnum: {
+ const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetFieldId(header_->FieldIds()[field_index]);
+ break;
+ }
+ case DexFile::kDexAnnotationMethod: {
+ const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetMethodId(header_->MethodIds()[method_index]);
+ break;
+ }
+ case DexFile::kDexAnnotationArray: {
+ EncodedValueVector* values = new EncodedValueVector();
+ const uint32_t offset = *data - dex_file.DataBegin();
+ const uint32_t size = DecodeUnsignedLeb128(data);
+ // Decode all elements.
+ for (uint32_t i = 0; i < size; i++) {
+ values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, data)));
+ }
+ EncodedArrayItem* array_item = new EncodedArrayItem(values);
+ if (eagerly_assign_offsets_) {
+ array_item->SetOffset(offset);
+ }
+ item->SetEncodedArray(array_item);
+ break;
+ }
+ case DexFile::kDexAnnotationAnnotation: {
+ AnnotationElementVector* elements = new AnnotationElementVector();
+ const uint32_t type_idx = DecodeUnsignedLeb128(data);
+ const uint32_t size = DecodeUnsignedLeb128(data);
+ // Decode all name=value pairs.
+ for (uint32_t i = 0; i < size; i++) {
+ const uint32_t name_index = DecodeUnsignedLeb128(data);
+ elements->push_back(std::unique_ptr<AnnotationElement>(
+ new AnnotationElement(header_->StringIds()[name_index],
+ ReadEncodedValue(dex_file, data))));
+ }
+ item->SetEncodedAnnotation(new EncodedAnnotation(header_->TypeIds()[type_idx], elements));
+ break;
+ }
+ case DexFile::kDexAnnotationNull:
+ break;
+ case DexFile::kDexAnnotationBoolean:
+ item->SetBoolean(length != 0);
+ break;
+ default:
+ break;
+ }
+}
+
+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();
+ // 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());
+ return MethodItem(access_flags, method_id, code_item);
+}
+
+ParameterAnnotation* BuilderMaps::GenerateParameterAnnotation(
+ const DexFile& dex_file,
+ MethodId* method_id,
+ const DexFile::AnnotationSetRefList* annotation_set_ref_list,
+ uint32_t offset) {
+ AnnotationSetRefList* set_ref_list = annotation_set_ref_lists_map_.GetExistingObject(offset);
+ if (set_ref_list == nullptr) {
+ std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
+ for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
+ const DexFile::AnnotationSetItem* annotation_set_item =
+ dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
+ uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
+ annotations->push_back(CreateAnnotationSetItem(dex_file, annotation_set_item, set_offset));
+ }
+ set_ref_list =
+ annotation_set_ref_lists_map_.CreateAndAddItem(header_->AnnotationSetRefLists(),
+ eagerly_assign_offsets_,
+ offset,
+ annotations);
+ }
+ return new ParameterAnnotation(method_id, set_ref_list);
+}
+
} // namespace dex_ir
} // namespace art
diff --git a/dexlayout/dex_verify.cc b/dexlayout/dex_verify.cc
index 2e4756b..962798d 100644
--- a/dexlayout/dex_verify.cc
+++ b/dexlayout/dex_verify.cc
@@ -31,38 +31,42 @@
bool VerifyOutputDexFile(dex_ir::Header* orig_header,
dex_ir::Header* output_header,
std::string* error_msg) {
- dex_ir::Collections& orig = orig_header->GetCollections();
- dex_ir::Collections& output = output_header->GetCollections();
-
// 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) ||
- !VerifyIds(orig.FieldIds(), output.FieldIds(), "field ids", error_msg) ||
- !VerifyIds(orig.MethodIds(), output.MethodIds(), "method ids", error_msg)) {
+ if (!VerifyIds(orig_header->StringIds(), output_header->StringIds(), "string ids", error_msg) ||
+ !VerifyIds(orig_header->TypeIds(), output_header->TypeIds(), "type ids", error_msg) ||
+ !VerifyIds(orig_header->ProtoIds(), output_header->ProtoIds(), "proto ids", error_msg) ||
+ !VerifyIds(orig_header->FieldIds(), output_header->FieldIds(), "field ids", error_msg) ||
+ !VerifyIds(orig_header->MethodIds(), output_header->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)) {
+ if (!VerifyClassDefs(orig_header->ClassDefs(), output_header->ClassDefs(), error_msg)) {
return false;
}
return true;
}
-template<class T> bool VerifyIds(std::vector<std::unique_ptr<T>>& orig,
- std::vector<std::unique_ptr<T>>& output,
+template<class T> bool VerifyIds(dex_ir::CollectionVector<T>& orig,
+ dex_ir::CollectionVector<T>& output,
const char* section_name,
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());
- return false;
- }
- for (size_t i = 0; i < orig.size(); ++i) {
- if (!VerifyId(orig[i].get(), output[i].get(), error_msg)) {
+ auto orig_iter = orig.begin();
+ auto output_iter = output.begin();
+ for (; orig_iter != orig.end() && output_iter != output.end(); ++orig_iter, ++output_iter) {
+ if (!VerifyId(orig_iter->get(), output_iter->get(), error_msg)) {
return false;
}
}
+ if (orig_iter != orig.end() || output_iter != output.end()) {
+ const char* longer;
+ if (orig_iter == orig.end()) {
+ longer = "output";
+ } else {
+ longer = "original";
+ }
+ *error_msg = StringPrintf("Mismatch for %s section: %s is longer.", section_name, longer);
+ return false;
+ }
return true;
}
@@ -181,29 +185,36 @@
// 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,
+bool VerifyClassDefs(dex_ir::CollectionVector<dex_ir::ClassDef>& orig,
+ dex_ir::CollectionVector<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.begin();
+ auto output_iter = output.begin();
+ for (; orig_iter != orig.end() && output_iter != output.end(); ++orig_iter, ++output_iter) {
+ orig_set.insert(orig_iter->get());
+ output_set.insert(output_iter->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)) {
+ if (orig_iter != orig.end() || output_iter != output.end()) {
+ const char* longer;
+ if (orig_iter == orig.end()) {
+ longer = "output";
+ } else {
+ longer = "original";
+ }
+ *error_msg = StringPrintf("Mismatch for class defs section: %s is longer.", longer);
+ return false;
+ }
+ auto orig_set_iter = orig_set.begin();
+ auto output_set_iter = output_set.begin();
+ while (orig_set_iter != orig_set.end() && output_set_iter != output_set.end()) {
+ if (!VerifyClassDef(*orig_set_iter, *output_set_iter, error_msg)) {
return false;
}
- orig_iter++;
- output_iter++;
+ orig_set_iter++;
+ output_set_iter++;
}
return true;
}
diff --git a/dexlayout/dex_verify.h b/dexlayout/dex_verify.h
index 998939b..4943def 100644
--- a/dexlayout/dex_verify.h
+++ b/dexlayout/dex_verify.h
@@ -30,8 +30,8 @@
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,
+template<class T> bool VerifyIds(dex_ir::CollectionVector<T>& orig,
+ dex_ir::CollectionVector<T>& output,
const char* section_name,
std::string* error_msg);
bool VerifyId(dex_ir::StringId* orig, dex_ir::StringId* output, std::string* error_msg);
@@ -40,8 +40,8 @@
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,
+bool VerifyClassDefs(dex_ir::CollectionVector<dex_ir::ClassDef>& orig,
+ dex_ir::CollectionVector<dex_ir::ClassDef>& output,
std::string* error_msg);
bool VerifyClassDef(dex_ir::ClassDef* orig, dex_ir::ClassDef* output, std::string* error_msg);
diff --git a/dexlayout/dex_visualize.cc b/dexlayout/dex_visualize.cc
index 0e04c58..abcaffc 100644
--- a/dexlayout/dex_visualize.cc
+++ b/dexlayout/dex_visualize.cc
@@ -252,9 +252,9 @@
return;
}
- const uint32_t class_defs_size = header->GetCollections().ClassDefsSize();
+ const uint32_t class_defs_size = header->ClassDefs().Size();
for (uint32_t class_index = 0; class_index < class_defs_size; class_index++) {
- dex_ir::ClassDef* class_def = header->GetCollections().GetClassDef(class_index);
+ dex_ir::ClassDef* class_def = header->ClassDefs()[class_index];
dex::TypeIndex type_idx(class_def->ClassType()->GetIndex());
if (profile_info != nullptr && !profile_info->ContainsClass(*dex_file, type_idx)) {
continue;
diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc
index 9ed1312..a4c5cda 100644
--- a/dexlayout/dex_writer.cc
+++ b/dexlayout/dex_writer.cc
@@ -231,7 +231,7 @@
// function that takes a CollectionVector<T> and uses overloading.
void DexWriter::WriteStringIds(Stream* stream, bool reserve_only) {
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::StringId>& string_id : header_->GetCollections().StringIds()) {
+ for (auto& string_id : header_->StringIds()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeStringIdItem));
if (reserve_only) {
stream->Skip(string_id->GetSize());
@@ -241,7 +241,7 @@
}
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetStringIdsOffset(start);
+ header_->StringIds().SetOffset(start);
}
}
@@ -256,25 +256,25 @@
void DexWriter::WriteStringDatas(Stream* stream) {
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::StringData>& string_data : header_->GetCollections().StringDatas()) {
+ for (auto& string_data : header_->StringDatas()) {
WriteStringData(stream, string_data.get());
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetStringDatasOffset(start);
+ header_->StringDatas().SetOffset(start);
}
}
void DexWriter::WriteTypeIds(Stream* stream) {
uint32_t descriptor_idx[1];
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::TypeId>& type_id : header_->GetCollections().TypeIds()) {
+ for (auto& type_id : header_->TypeIds()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeTypeIdItem));
ProcessOffset(stream, type_id.get());
descriptor_idx[0] = type_id->GetStringId()->GetIndex();
stream->Write(descriptor_idx, type_id->GetSize());
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetTypeIdsOffset(start);
+ header_->TypeIds().SetOffset(start);
}
}
@@ -282,7 +282,7 @@
uint32_t size[1];
uint16_t list[1];
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::TypeList>& type_list : header_->GetCollections().TypeLists()) {
+ for (auto& type_list : header_->TypeLists()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeTypeList));
size[0] = type_list->GetTypeList()->size();
ProcessOffset(stream, type_list.get());
@@ -293,14 +293,14 @@
}
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetTypeListsOffset(start);
+ header_->TypeLists().SetOffset(start);
}
}
void DexWriter::WriteProtoIds(Stream* stream, bool reserve_only) {
uint32_t buffer[3];
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::ProtoId>& proto_id : header_->GetCollections().ProtoIds()) {
+ for (auto& proto_id : header_->ProtoIds()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeProtoIdItem));
ProcessOffset(stream, proto_id.get());
if (reserve_only) {
@@ -313,14 +313,14 @@
}
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetProtoIdsOffset(start);
+ header_->ProtoIds().SetOffset(start);
}
}
void DexWriter::WriteFieldIds(Stream* stream) {
uint16_t buffer[4];
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::FieldId>& field_id : header_->GetCollections().FieldIds()) {
+ for (auto& field_id : header_->FieldIds()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeFieldIdItem));
ProcessOffset(stream, field_id.get());
buffer[0] = field_id->Class()->GetIndex();
@@ -330,14 +330,14 @@
stream->Write(buffer, field_id->GetSize());
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetFieldIdsOffset(start);
+ header_->FieldIds().SetOffset(start);
}
}
void DexWriter::WriteMethodIds(Stream* stream) {
uint16_t buffer[4];
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::MethodId>& method_id : header_->GetCollections().MethodIds()) {
+ for (auto& method_id : header_->MethodIds()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeMethodIdItem));
ProcessOffset(stream, method_id.get());
buffer[0] = method_id->Class()->GetIndex();
@@ -347,28 +347,26 @@
stream->Write(buffer, method_id->GetSize());
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetMethodIdsOffset(start);
+ header_->MethodIds().SetOffset(start);
}
}
void DexWriter::WriteEncodedArrays(Stream* stream) {
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::EncodedArrayItem>& encoded_array :
- header_->GetCollections().EncodedArrayItems()) {
+ for (auto& encoded_array : header_->EncodedArrayItems()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeEncodedArrayItem));
ProcessOffset(stream, encoded_array.get());
WriteEncodedArray(stream, encoded_array->GetEncodedValues());
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetEncodedArrayItemsOffset(start);
+ header_->EncodedArrayItems().SetOffset(start);
}
}
void DexWriter::WriteAnnotations(Stream* stream) {
uint8_t visibility[1];
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::AnnotationItem>& annotation :
- header_->GetCollections().AnnotationItems()) {
+ for (auto& annotation : header_->AnnotationItems()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationItem));
visibility[0] = annotation->GetVisibility();
ProcessOffset(stream, annotation.get());
@@ -376,7 +374,7 @@
WriteEncodedAnnotation(stream, annotation->GetAnnotation());
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetAnnotationItemsOffset(start);
+ header_->AnnotationItems().SetOffset(start);
}
}
@@ -384,8 +382,7 @@
uint32_t size[1];
uint32_t annotation_off[1];
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::AnnotationSetItem>& annotation_set :
- header_->GetCollections().AnnotationSetItems()) {
+ for (auto& annotation_set : header_->AnnotationSetItems()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationSetItem));
size[0] = annotation_set->GetItems()->size();
ProcessOffset(stream, annotation_set.get());
@@ -396,7 +393,7 @@
}
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetAnnotationSetItemsOffset(start);
+ header_->AnnotationSetItems().SetOffset(start);
}
}
@@ -404,8 +401,7 @@
uint32_t size[1];
uint32_t annotations_off[1];
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::AnnotationSetRefList>& annotation_set_ref :
- header_->GetCollections().AnnotationSetRefLists()) {
+ for (auto& annotation_set_ref : header_->AnnotationSetRefLists()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationSetRefList));
size[0] = annotation_set_ref->GetItems()->size();
ProcessOffset(stream, annotation_set_ref.get());
@@ -416,7 +412,7 @@
}
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetAnnotationSetRefListsOffset(start);
+ header_->AnnotationSetRefLists().SetOffset(start);
}
}
@@ -424,8 +420,7 @@
uint32_t directory_buffer[4];
uint32_t annotation_buffer[2];
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::AnnotationsDirectoryItem>& annotations_directory :
- header_->GetCollections().AnnotationsDirectoryItems()) {
+ for (auto& annotations_directory : header_->AnnotationsDirectoryItems()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationsDirectoryItem));
ProcessOffset(stream, annotations_directory.get());
directory_buffer[0] = annotations_directory->GetClassAnnotation() == nullptr ? 0 :
@@ -463,7 +458,7 @@
}
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetAnnotationsDirectoryItemsOffset(start);
+ header_->AnnotationsDirectoryItems().SetOffset(start);
}
}
@@ -475,12 +470,11 @@
void DexWriter::WriteDebugInfoItems(Stream* stream) {
const uint32_t start = stream->Tell();
- for (std::unique_ptr<dex_ir::DebugInfoItem>& debug_info :
- header_->GetCollections().DebugInfoItems()) {
+ for (auto& debug_info : header_->DebugInfoItems()) {
WriteDebugInfoItem(stream, debug_info.get());
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetDebugInfoItemsOffset(start);
+ header_->DebugInfoItems().SetOffset(start);
}
}
@@ -558,7 +552,7 @@
DexLayoutSections::SectionType::kSectionTypeCode)];
}
const uint32_t start = stream->Tell();
- for (auto& code_item : header_->GetCollections().CodeItems()) {
+ for (auto& code_item : header_->CodeItems()) {
uint32_t start_offset = stream->Tell();
WriteCodeItem(stream, code_item.get(), reserve_only);
// Only add the section hotness info once.
@@ -573,14 +567,14 @@
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetCodeItemsOffset(start);
+ header_->CodeItems().SetOffset(start);
}
}
void DexWriter::WriteClassDefs(Stream* stream, bool reserve_only) {
const uint32_t start = stream->Tell();
uint32_t class_def_buffer[8];
- for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) {
+ for (auto& class_def : header_->ClassDefs()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeClassDefItem));
if (reserve_only) {
stream->Skip(class_def->GetSize());
@@ -602,14 +596,14 @@
}
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetClassDefsOffset(start);
+ header_->ClassDefs().SetOffset(start);
}
}
void DexWriter::WriteClassDatas(Stream* stream) {
const uint32_t start = stream->Tell();
for (const std::unique_ptr<dex_ir::ClassData>& class_data :
- header_->GetCollections().ClassDatas()) {
+ header_->ClassDatas()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeClassDataItem));
ProcessOffset(stream, class_data.get());
stream->WriteUleb128(class_data->StaticFields()->size());
@@ -622,15 +616,14 @@
WriteEncodedMethods(stream, class_data->VirtualMethods());
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetClassDatasOffset(start);
+ header_->ClassDatas().SetOffset(start);
}
}
void DexWriter::WriteCallSiteIds(Stream* stream, bool reserve_only) {
const uint32_t start = stream->Tell();
uint32_t call_site_off[1];
- for (std::unique_ptr<dex_ir::CallSiteId>& call_site_id :
- header_->GetCollections().CallSiteIds()) {
+ for (auto& call_site_id : header_->CallSiteIds()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeCallSiteIdItem));
if (reserve_only) {
stream->Skip(call_site_id->GetSize());
@@ -640,15 +633,14 @@
}
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetCallSiteIdsOffset(start);
+ header_->CallSiteIds().SetOffset(start);
}
}
void DexWriter::WriteMethodHandles(Stream* stream) {
const uint32_t start = stream->Tell();
uint16_t method_handle_buff[4];
- for (std::unique_ptr<dex_ir::MethodHandleItem>& method_handle :
- header_->GetCollections().MethodHandleItems()) {
+ for (auto& method_handle : header_->MethodHandleItems()) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeMethodHandleItem));
method_handle_buff[0] = static_cast<uint16_t>(method_handle->GetMethodHandleType());
method_handle_buff[1] = 0; // unused.
@@ -657,7 +649,7 @@
stream->Write(method_handle_buff, method_handle->GetSize());
}
if (compute_offsets_ && start != stream->Tell()) {
- header_->GetCollections().SetMethodHandleItemsOffset(start);
+ header_->MethodHandleItems().SetOffset(start);
}
}
@@ -678,67 +670,66 @@
}
void DexWriter::GenerateAndWriteMapItems(Stream* stream) {
- dex_ir::Collections& collection = header_->GetCollections();
MapItemQueue queue;
// Header and index section.
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeHeaderItem, 1, 0));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringIdItem,
- collection.StringIdsSize(),
- collection.StringIdsOffset()));
+ header_->StringIds().Size(),
+ header_->StringIds().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeIdItem,
- collection.TypeIdsSize(),
- collection.TypeIdsOffset()));
+ header_->TypeIds().Size(),
+ header_->TypeIds().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeProtoIdItem,
- collection.ProtoIdsSize(),
- collection.ProtoIdsOffset()));
+ header_->ProtoIds().Size(),
+ header_->ProtoIds().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeFieldIdItem,
- collection.FieldIdsSize(),
- collection.FieldIdsOffset()));
+ header_->FieldIds().Size(),
+ header_->FieldIds().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodIdItem,
- collection.MethodIdsSize(),
- collection.MethodIdsOffset()));
+ header_->MethodIds().Size(),
+ header_->MethodIds().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDefItem,
- collection.ClassDefsSize(),
- collection.ClassDefsOffset()));
+ header_->ClassDefs().Size(),
+ header_->ClassDefs().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCallSiteIdItem,
- collection.CallSiteIdsSize(),
- collection.CallSiteIdsOffset()));
+ header_->CallSiteIds().Size(),
+ header_->CallSiteIds().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodHandleItem,
- collection.MethodHandleItemsSize(),
- collection.MethodHandleItemsOffset()));
+ header_->MethodHandleItems().Size(),
+ header_->MethodHandleItems().GetOffset()));
// Data section.
- queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMapList, 1, collection.MapListOffset()));
+ queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMapList, 1, header_->MapListOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeList,
- collection.TypeListsSize(),
- collection.TypeListsOffset()));
+ header_->TypeLists().Size(),
+ header_->TypeLists().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetRefList,
- collection.AnnotationSetRefListsSize(),
- collection.AnnotationSetRefListsOffset()));
+ header_->AnnotationSetRefLists().Size(),
+ header_->AnnotationSetRefLists().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetItem,
- collection.AnnotationSetItemsSize(),
- collection.AnnotationSetItemsOffset()));
+ header_->AnnotationSetItems().Size(),
+ header_->AnnotationSetItems().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDataItem,
- collection.ClassDatasSize(),
- collection.ClassDatasOffset()));
+ header_->ClassDatas().Size(),
+ header_->ClassDatas().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCodeItem,
- collection.CodeItemsSize(),
- collection.CodeItemsOffset()));
+ header_->CodeItems().Size(),
+ header_->CodeItems().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringDataItem,
- collection.StringDatasSize(),
- collection.StringDatasOffset()));
+ header_->StringDatas().Size(),
+ header_->StringDatas().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeDebugInfoItem,
- collection.DebugInfoItemsSize(),
- collection.DebugInfoItemsOffset()));
+ header_->DebugInfoItems().Size(),
+ header_->DebugInfoItems().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationItem,
- collection.AnnotationItemsSize(),
- collection.AnnotationItemsOffset()));
+ header_->AnnotationItems().Size(),
+ header_->AnnotationItems().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeEncodedArrayItem,
- collection.EncodedArrayItemsSize(),
- collection.EncodedArrayItemsOffset()));
+ header_->EncodedArrayItems().Size(),
+ header_->EncodedArrayItems().GetOffset()));
queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationsDirectoryItem,
- collection.AnnotationsDirectoryItemsSize(),
- collection.AnnotationsDirectoryItemsOffset()));
+ header_->AnnotationsDirectoryItems().Size(),
+ header_->AnnotationsDirectoryItems().GetOffset()));
WriteMapItems(stream, &queue);
}
@@ -761,20 +752,19 @@
header.endian_tag_ = header_->EndianTag();
header.link_size_ = header_->LinkSize();
header.link_off_ = header_->LinkOffset();
- const dex_ir::Collections& collections = header_->GetCollections();
- header.map_off_ = collections.MapListOffset();
- header.string_ids_size_ = collections.StringIdsSize();
- header.string_ids_off_ = collections.StringIdsOffset();
- header.type_ids_size_ = collections.TypeIdsSize();
- header.type_ids_off_ = collections.TypeIdsOffset();
- header.proto_ids_size_ = collections.ProtoIdsSize();
- header.proto_ids_off_ = collections.ProtoIdsOffset();
- header.field_ids_size_ = collections.FieldIdsSize();
- header.field_ids_off_ = collections.FieldIdsOffset();
- header.method_ids_size_ = collections.MethodIdsSize();
- header.method_ids_off_ = collections.MethodIdsOffset();
- header.class_defs_size_ = collections.ClassDefsSize();
- header.class_defs_off_ = collections.ClassDefsOffset();
+ header.map_off_ = header_->MapListOffset();
+ header.string_ids_size_ = header_->StringIds().Size();
+ header.string_ids_off_ = header_->StringIds().GetOffset();
+ header.type_ids_size_ = header_->TypeIds().Size();
+ header.type_ids_off_ = header_->TypeIds().GetOffset();
+ header.proto_ids_size_ = header_->ProtoIds().Size();
+ header.proto_ids_off_ = header_->ProtoIds().GetOffset();
+ header.field_ids_size_ = header_->FieldIds().Size();
+ header.field_ids_off_ = header_->FieldIds().GetOffset();
+ header.method_ids_size_ = header_->MethodIds().Size();
+ header.method_ids_off_ = header_->MethodIds().GetOffset();
+ header.class_defs_size_ = header_->ClassDefs().Size();
+ header.class_defs_off_ = header_->ClassDefs().GetOffset();
header.data_size_ = header_->DataSize();
header.data_off_ = header_->DataOffset();
@@ -797,8 +787,6 @@
// Starting offset is right after the header.
stream->Seek(GetHeaderSize());
- dex_ir::Collections& collection = header_->GetCollections();
-
// Based on: https://source.android.com/devices/tech/dalvik/dex-format
// Since the offsets may not be calculated already, the writing must be done in the correct order.
const uint32_t string_ids_offset = stream->Tell();
@@ -863,9 +851,9 @@
// Write the map list.
if (compute_offsets_) {
stream->AlignTo(SectionAlignment(DexFile::kDexTypeMapList));
- collection.SetMapListOffset(stream->Tell());
+ header_->SetMapListOffset(stream->Tell());
} else {
- stream->Seek(collection.MapListOffset());
+ stream->Seek(header_->MapListOffset());
}
GenerateAndWriteMapItems(stream);
stream->AlignTo(kDataSectionAlignment);
@@ -882,7 +870,7 @@
}
// Write link data if it exists.
- const std::vector<uint8_t>& link_data = collection.LinkData();
+ const std::vector<uint8_t>& link_data = header_->LinkData();
if (link_data.size() > 0) {
CHECK_EQ(header_->LinkSize(), static_cast<uint32_t>(link_data.size()));
if (compute_offsets_) {
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 39d93bf..d6dd9d1 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -417,24 +417,24 @@
outSize = snprintf(buf.get(), buf_size, "<no-index>");
break;
case Instruction::kIndexTypeRef:
- if (index < header->GetCollections().TypeIdsSize()) {
- const char* tp = header->GetCollections().GetTypeId(index)->GetStringId()->Data();
+ if (index < header->TypeIds().Size()) {
+ const char* tp = header->TypeIds()[index]->GetStringId()->Data();
outSize = snprintf(buf.get(), buf_size, "%s // type@%0*x", tp, width, index);
} else {
outSize = snprintf(buf.get(), buf_size, "<type?> // type@%0*x", width, index);
}
break;
case Instruction::kIndexStringRef:
- if (index < header->GetCollections().StringIdsSize()) {
- const char* st = header->GetCollections().GetStringId(index)->Data();
+ if (index < header->StringIds().Size()) {
+ const char* st = header->StringIds()[index]->Data();
outSize = snprintf(buf.get(), buf_size, "\"%s\" // string@%0*x", st, width, index);
} else {
outSize = snprintf(buf.get(), buf_size, "<string?> // string@%0*x", width, index);
}
break;
case Instruction::kIndexMethodRef:
- if (index < header->GetCollections().MethodIdsSize()) {
- dex_ir::MethodId* method_id = header->GetCollections().GetMethodId(index);
+ if (index < header->MethodIds().Size()) {
+ dex_ir::MethodId* method_id = header->MethodIds()[index];
const char* name = method_id->Name()->Data();
std::string type_descriptor = GetSignatureForProtoId(method_id->Proto());
const char* back_descriptor = method_id->Class()->GetStringId()->Data();
@@ -445,8 +445,8 @@
}
break;
case Instruction::kIndexFieldRef:
- if (index < header->GetCollections().FieldIdsSize()) {
- dex_ir::FieldId* field_id = header->GetCollections().GetFieldId(index);
+ if (index < header->FieldIds().Size()) {
+ dex_ir::FieldId* field_id = header->FieldIds()[index];
const char* name = field_id->Name()->Data();
const char* type_descriptor = field_id->Type()->GetStringId()->Data();
const char* back_descriptor = field_id->Class()->GetStringId()->Data();
@@ -466,15 +466,15 @@
case Instruction::kIndexMethodAndProtoRef: {
std::string method("<method?>");
std::string proto("<proto?>");
- if (index < header->GetCollections().MethodIdsSize()) {
- dex_ir::MethodId* method_id = header->GetCollections().GetMethodId(index);
+ if (index < header->MethodIds().Size()) {
+ dex_ir::MethodId* method_id = header->MethodIds()[index];
const char* name = method_id->Name()->Data();
std::string type_descriptor = GetSignatureForProtoId(method_id->Proto());
const char* back_descriptor = method_id->Class()->GetStringId()->Data();
method = StringPrintf("%s.%s:%s", back_descriptor, name, type_descriptor.c_str());
}
- if (secondary_index < header->GetCollections().ProtoIdsSize()) {
- dex_ir::ProtoId* proto_id = header->GetCollections().GetProtoId(secondary_index);
+ if (secondary_index < header->ProtoIds().Size()) {
+ dex_ir::ProtoId* proto_id = header->ProtoIds()[secondary_index];
proto = GetSignatureForProtoId(proto_id);
}
outSize = snprintf(buf.get(), buf_size, "%s, %s // method@%0*x, proto@%0*x",
@@ -596,7 +596,6 @@
*/
void DexLayout::DumpFileHeader() {
char sanitized[8 * 2 + 1];
- dex_ir::Collections& collections = header_->GetCollections();
fprintf(out_file_, "DEX file header:\n");
Asciify(sanitized, header_->Magic(), 8);
fprintf(out_file_, "magic : '%s'\n", sanitized);
@@ -610,24 +609,24 @@
fprintf(out_file_, "link_size : %d\n", header_->LinkSize());
fprintf(out_file_, "link_off : %d (0x%06x)\n",
header_->LinkOffset(), header_->LinkOffset());
- fprintf(out_file_, "string_ids_size : %d\n", collections.StringIdsSize());
+ fprintf(out_file_, "string_ids_size : %d\n", header_->StringIds().Size());
fprintf(out_file_, "string_ids_off : %d (0x%06x)\n",
- collections.StringIdsOffset(), collections.StringIdsOffset());
- fprintf(out_file_, "type_ids_size : %d\n", collections.TypeIdsSize());
+ header_->StringIds().GetOffset(), header_->StringIds().GetOffset());
+ fprintf(out_file_, "type_ids_size : %d\n", header_->TypeIds().Size());
fprintf(out_file_, "type_ids_off : %d (0x%06x)\n",
- collections.TypeIdsOffset(), collections.TypeIdsOffset());
- fprintf(out_file_, "proto_ids_size : %d\n", collections.ProtoIdsSize());
+ header_->TypeIds().GetOffset(), header_->TypeIds().GetOffset());
+ fprintf(out_file_, "proto_ids_size : %d\n", header_->ProtoIds().Size());
fprintf(out_file_, "proto_ids_off : %d (0x%06x)\n",
- collections.ProtoIdsOffset(), collections.ProtoIdsOffset());
- fprintf(out_file_, "field_ids_size : %d\n", collections.FieldIdsSize());
+ header_->ProtoIds().GetOffset(), header_->ProtoIds().GetOffset());
+ fprintf(out_file_, "field_ids_size : %d\n", header_->FieldIds().Size());
fprintf(out_file_, "field_ids_off : %d (0x%06x)\n",
- collections.FieldIdsOffset(), collections.FieldIdsOffset());
- fprintf(out_file_, "method_ids_size : %d\n", collections.MethodIdsSize());
+ header_->FieldIds().GetOffset(), header_->FieldIds().GetOffset());
+ fprintf(out_file_, "method_ids_size : %d\n", header_->MethodIds().Size());
fprintf(out_file_, "method_ids_off : %d (0x%06x)\n",
- collections.MethodIdsOffset(), collections.MethodIdsOffset());
- fprintf(out_file_, "class_defs_size : %d\n", collections.ClassDefsSize());
+ header_->MethodIds().GetOffset(), header_->MethodIds().GetOffset());
+ fprintf(out_file_, "class_defs_size : %d\n", header_->ClassDefs().Size());
fprintf(out_file_, "class_defs_off : %d (0x%06x)\n",
- collections.ClassDefsOffset(), collections.ClassDefsOffset());
+ header_->ClassDefs().GetOffset(), header_->ClassDefs().GetOffset());
fprintf(out_file_, "data_size : %d\n", header_->DataSize());
fprintf(out_file_, "data_off : %d (0x%06x)\n\n",
header_->DataOffset(), header_->DataOffset());
@@ -638,7 +637,7 @@
*/
void DexLayout::DumpClassDef(int idx) {
// General class information.
- dex_ir::ClassDef* class_def = header_->GetCollections().GetClassDef(idx);
+ dex_ir::ClassDef* class_def = header_->ClassDefs()[idx];
fprintf(out_file_, "Class #%d header:\n", idx);
fprintf(out_file_, "class_idx : %d\n", class_def->ClassType()->GetIndex());
fprintf(out_file_, "access_flags : %d (0x%04x)\n",
@@ -719,7 +718,7 @@
* Dumps class annotations.
*/
void DexLayout::DumpClassAnnotations(int idx) {
- dex_ir::ClassDef* class_def = header_->GetCollections().GetClassDef(idx);
+ dex_ir::ClassDef* class_def = header_->ClassDefs()[idx];
dex_ir::AnnotationsDirectoryItem* annotations_directory = class_def->Annotations();
if (annotations_directory == nullptr) {
return; // none
@@ -1039,7 +1038,7 @@
* Dumps a bytecode disassembly.
*/
void DexLayout::DumpBytecodes(uint32_t idx, const dex_ir::CodeItem* code, uint32_t code_offset) {
- dex_ir::MethodId* method_id = header_->GetCollections().GetMethodId(idx);
+ dex_ir::MethodId* method_id = header_->MethodIds()[idx];
const char* name = method_id->Name()->Data();
std::string type_descriptor = GetSignatureForProtoId(method_id->Proto());
const char* back_descriptor = method_id->Class()->GetStringId()->Data();
@@ -1083,16 +1082,16 @@
/*
* Lookup functions.
*/
-static const char* StringDataByIdx(uint32_t idx, dex_ir::Collections& collections) {
- dex_ir::StringId* string_id = collections.GetStringIdOrNullPtr(idx);
+static const char* StringDataByIdx(uint32_t idx, dex_ir::Header* header) {
+ dex_ir::StringId* string_id = header->GetStringIdOrNullPtr(idx);
if (string_id == nullptr) {
return nullptr;
}
return string_id->Data();
}
-static const char* StringDataByTypeIdx(uint16_t idx, dex_ir::Collections& collections) {
- dex_ir::TypeId* type_id = collections.GetTypeIdOrNullPtr(idx);
+static const char* StringDataByTypeIdx(uint16_t idx, dex_ir::Header* header) {
+ dex_ir::TypeId* type_id = header->GetTypeIdOrNullPtr(idx);
if (type_id == nullptr) {
return nullptr;
}
@@ -1134,7 +1133,7 @@
if (debug_info != nullptr) {
DexFile::DecodeDebugPositionInfo(debug_info->GetDebugInfo(),
[this](uint32_t idx) {
- return StringDataByIdx(idx, this->header_->GetCollections());
+ return StringDataByIdx(idx, this->header_);
},
DumpPositionsCb,
out_file_);
@@ -1161,12 +1160,12 @@
code->InsSize(),
code->InsnsSize(),
[this](uint32_t idx) {
- return StringDataByIdx(idx, this->header_->GetCollections());
+ return StringDataByIdx(idx, this->header_);
},
[this](uint32_t idx) {
return
StringDataByTypeIdx(dchecked_integral_cast<uint16_t>(idx),
- this->header_->GetCollections());
+ this->header_);
},
DumpLocalsCb,
out_file_);
@@ -1182,7 +1181,7 @@
return;
}
- dex_ir::MethodId* method_id = header_->GetCollections().GetMethodId(idx);
+ dex_ir::MethodId* method_id = header_->MethodIds()[idx];
const char* name = method_id->Name()->Data();
char* type_descriptor = strdup(GetSignatureForProtoId(method_id->Proto()).c_str());
const char* back_descriptor = method_id->Class()->GetStringId()->Data();
@@ -1292,7 +1291,7 @@
return;
}
- dex_ir::FieldId* field_id = header_->GetCollections().GetFieldId(idx);
+ dex_ir::FieldId* field_id = header_->FieldIds()[idx];
const char* name = field_id->Name()->Data();
const char* type_descriptor = field_id->Type()->GetStringId()->Data();
const char* back_descriptor = field_id->Class()->GetStringId()->Data();
@@ -1346,7 +1345,7 @@
* the value will be replaced with a newly-allocated string.
*/
void DexLayout::DumpClass(int idx, char** last_package) {
- dex_ir::ClassDef* class_def = header_->GetCollections().GetClassDef(idx);
+ dex_ir::ClassDef* class_def = header_->ClassDefs()[idx];
// Omitting non-public class.
if (options_.exports_only_ && (class_def->GetAccessFlags() & kAccPublic) == 0) {
return;
@@ -1364,8 +1363,7 @@
// up the classes, sort them, and dump them alphabetically so the
// package name wouldn't jump around, but that's not a great plan
// for something that needs to run on the device.
- const char* class_descriptor =
- header_->GetCollections().GetClassDef(idx)->ClassType()->GetStringId()->Data();
+ const char* class_descriptor = header_->ClassDefs()[idx]->ClassType()->GetStringId()->Data();
if (!(class_descriptor[0] == 'L' &&
class_descriptor[strlen(class_descriptor)-1] == ';')) {
// Arrays and primitives should not be defined explicitly. Keep going?
@@ -1543,7 +1541,7 @@
// Iterate over all classes.
char* package = nullptr;
- const uint32_t class_defs_size = header_->GetCollections().ClassDefsSize();
+ const uint32_t class_defs_size = header_->ClassDefs().Size();
for (uint32_t i = 0; i < class_defs_size; i++) {
DumpClass(i, &package);
} // for
@@ -1562,13 +1560,13 @@
void DexLayout::LayoutClassDefsAndClassData(const DexFile* dex_file) {
std::vector<dex_ir::ClassDef*> new_class_def_order;
- for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) {
+ for (auto& class_def : header_->ClassDefs()) {
dex::TypeIndex type_idx(class_def->ClassType()->GetIndex());
if (info_->ContainsClass(*dex_file, type_idx)) {
new_class_def_order.push_back(class_def.get());
}
}
- for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) {
+ for (auto& class_def : header_->ClassDefs()) {
dex::TypeIndex type_idx(class_def->ClassType()->GetIndex());
if (!info_->ContainsClass(*dex_file, type_idx)) {
new_class_def_order.push_back(class_def.get());
@@ -1576,8 +1574,7 @@
}
std::unordered_set<dex_ir::ClassData*> visited_class_data;
size_t class_data_index = 0;
- dex_ir::CollectionVector<dex_ir::ClassData>::Vector& class_datas =
- header_->GetCollections().ClassDatas();
+ auto& class_datas = header_->ClassDatas();
for (dex_ir::ClassDef* class_def : new_class_def_order) {
dex_ir::ClassData* class_data = class_def->GetClassData();
if (class_data != nullptr && visited_class_data.find(class_data) == visited_class_data.end()) {
@@ -1590,15 +1587,14 @@
++class_data_index;
}
}
- CHECK_EQ(class_data_index, class_datas.size());
+ CHECK_EQ(class_data_index, class_datas.Size());
if (DexLayout::kChangeClassDefOrder) {
// This currently produces dex files that violate the spec since the super class class_def is
// supposed to occur before any subclasses.
- dex_ir::CollectionVector<dex_ir::ClassDef>::Vector& class_defs =
- header_->GetCollections().ClassDefs();
- CHECK_EQ(new_class_def_order.size(), class_defs.size());
- for (size_t i = 0; i < class_defs.size(); ++i) {
+ dex_ir::CollectionVector<dex_ir::ClassDef>& class_defs = header_->ClassDefs();
+ CHECK_EQ(new_class_def_order.size(), class_defs.Size());
+ for (size_t i = 0; i < class_defs.Size(); ++i) {
// Overwrite the existing vector with the new ordering, note that the sets of objects are
// equivalent, but the order changes. This is why this is not a memory leak.
// TODO: Consider cleaning this up with a shared_ptr.
@@ -1609,10 +1605,10 @@
}
void DexLayout::LayoutStringData(const DexFile* dex_file) {
- const size_t num_strings = header_->GetCollections().StringIds().size();
+ const size_t num_strings = header_->StringIds().Size();
std::vector<bool> is_shorty(num_strings, false);
std::vector<bool> from_hot_method(num_strings, false);
- for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) {
+ for (auto& class_def : header_->ClassDefs()) {
// A name of a profile class is probably going to get looked up by ClassTable::Lookup, mark it
// as hot. Add its super class and interfaces as well, which can be used during initialization.
const bool is_profile_class =
@@ -1678,7 +1674,7 @@
}
// Sort string data by specified order.
std::vector<dex_ir::StringId*> string_ids;
- for (auto& string_id : header_->GetCollections().StringIds()) {
+ for (auto& string_id : header_->StringIds()) {
string_ids.push_back(string_id.get());
}
std::sort(string_ids.begin(),
@@ -1699,8 +1695,7 @@
// Order by index by default.
return a->GetIndex() < b->GetIndex();
});
- dex_ir::CollectionVector<dex_ir::StringData>::Vector& string_datas =
- header_->GetCollections().StringDatas();
+ auto& string_datas = header_->StringDatas();
// Now we know what order we want the string data, reorder them.
size_t data_index = 0;
for (dex_ir::StringId* string_id : string_ids) {
@@ -1713,11 +1708,11 @@
for (const std::unique_ptr<dex_ir::StringData>& data : string_datas) {
visited.insert(data.get());
}
- for (auto& string_id : header_->GetCollections().StringIds()) {
+ for (auto& string_id : header_->StringIds()) {
CHECK(visited.find(string_id->DataItem()) != visited.end());
}
}
- CHECK_EQ(data_index, string_datas.size());
+ CHECK_EQ(data_index, string_datas.Size());
}
// Orders code items according to specified class data ordering.
@@ -1732,7 +1727,7 @@
// Assign hotness flags to all code items.
for (InvokeType invoke_type : invoke_types) {
- for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) {
+ for (auto& class_def : header_->ClassDefs()) {
const bool is_profile_class =
info_->ContainsClass(*dex_file, dex::TypeIndex(class_def->ClassType()->GetIndex()));
@@ -1778,8 +1773,7 @@
}
}
- dex_ir::CollectionVector<dex_ir::CodeItem>::Vector& code_items =
- header_->GetCollections().CodeItems();
+ const auto& code_items = header_->CodeItems();
if (VLOG_IS_ON(dex)) {
size_t layout_count[static_cast<size_t>(LayoutType::kLayoutTypeCount)] = {};
for (const std::unique_ptr<dex_ir::CodeItem>& code_item : code_items) {
@@ -1871,7 +1865,7 @@
const bool has_output_container = dex_container != nullptr;
const bool output = options_.output_dex_directory_ != nullptr || has_output_container;
- // Try to avoid eagerly assigning offsets to find bugs since GetOffset will abort if the offset
+ // Try to avoid eagerly assigning offsets to find bugs since Offset will abort if the offset
// is unassigned.
bool eagerly_assign_offsets = false;
if (options_.visualize_pattern_ || options_.show_section_statistics_ || options_.dump_) {