diff options
Diffstat (limited to 'dexlayout/dex_ir.cc')
-rw-r--r-- | dexlayout/dex_ir.cc | 947 |
1 files changed, 42 insertions, 905 deletions
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc index 15e3baf18a..3917847ea7 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 @@ struct FileSectionDescriptor { 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 @@ static const FileSectionDescriptor kFileSectionDescriptors[] = { }, { "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(), |