diff options
Diffstat (limited to 'dexlayout/dex_ir.cc')
| -rw-r--r-- | dexlayout/dex_ir.cc | 171 |
1 files changed, 150 insertions, 21 deletions
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc index 131f4b9f63..4905b5c2f6 100644 --- a/dexlayout/dex_ir.cc +++ b/dexlayout/dex_ir.cc @@ -50,13 +50,14 @@ static void GetLocalsCb(void* context, const DexFile::LocalInfo& entry) { DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context); LocalInfoVector& locals = debug_info->GetLocalInfo(); const char* name = entry.name_ != nullptr ? entry.name_ : "(null)"; + const char* descriptor = entry.descriptor_ != nullptr ? entry.descriptor_ : ""; const char* signature = entry.signature_ != nullptr ? entry.signature_ : ""; locals.push_back(std::unique_ptr<LocalInfo>( - new LocalInfo(name, entry.descriptor_, signature, entry.start_address_, - entry.end_address_, entry.reg_))); + new LocalInfo(name, descriptor, signature, entry.start_address_, entry.end_address_, + entry.reg_))); } -static uint32_t GetCodeItemSize(const DexFile& dex_file, const DexFile::CodeItem& disk_code_item) { +static uint32_t GetCodeItemSize(const DexFile::CodeItem& disk_code_item) { uintptr_t code_item_start = reinterpret_cast<uintptr_t>(&disk_code_item); uint32_t insns_size = disk_code_item.insns_size_in_code_units_; uint32_t tries_size = disk_code_item.tries_size_; @@ -64,23 +65,18 @@ static uint32_t GetCodeItemSize(const DexFile& dex_file, const DexFile::CodeItem uintptr_t insns_end = reinterpret_cast<uintptr_t>(&disk_code_item.insns_[insns_size]); return insns_end - code_item_start; } else { - uint32_t last_handler_off = 0; - for (uint32_t i = 0; i < tries_size; ++i) { - // Iterate over the try items to find the last catch handler. - const DexFile::TryItem* disk_try_item = dex_file.GetTryItems(disk_code_item, i); - uint16_t handler_off = disk_try_item->handler_off_; - if (handler_off > last_handler_off) { - last_handler_off = handler_off; + // Get the start of the handler data. + const uint8_t* handler_data = DexFile::GetCatchHandlerData(disk_code_item, 0); + uint32_t handlers_size = DecodeUnsignedLeb128(&handler_data); + // Manually read each handler. + for (uint32_t i = 0; i < handlers_size; ++i) { + int32_t uleb128_count = DecodeSignedLeb128(&handler_data) * 2; + if (uleb128_count <= 0) { + uleb128_count = -uleb128_count + 1; + } + for (int32_t j = 0; j < uleb128_count; ++j) { + DecodeUnsignedLeb128(&handler_data); } - } - // Decode the final handler to see where it ends. - const uint8_t* handler_data = DexFile::GetCatchHandlerData(disk_code_item, last_handler_off); - int32_t uleb128_count = DecodeSignedLeb128(&handler_data) * 2; - if (uleb128_count <= 0) { - uleb128_count = -uleb128_count + 1; - } - for (int32_t i = 0; i < uleb128_count; ++i) { - DecodeUnsignedLeb128(&handler_data); } return reinterpret_cast<uintptr_t>(handler_data) - code_item_start; } @@ -649,7 +645,7 @@ CodeItem* Collections::CreateCodeItem(const DexFile& dex_file, } } int32_t size = DecodeSignedLeb128(&handlers_data); - bool has_catch_all = size < 0; + bool has_catch_all = size <= 0; if (has_catch_all) { size = -size; } @@ -680,7 +676,7 @@ CodeItem* Collections::CreateCodeItem(const DexFile& dex_file, } } - uint32_t size = GetCodeItemSize(dex_file, disk_code_item); + uint32_t size = GetCodeItemSize(disk_code_item); CodeItem* code_item = new CodeItem( registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries, handler_list); code_item->SetSize(size); @@ -768,5 +764,138 @@ ClassData* Collections::CreateClassData( return class_data; } +static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) { + return 0; +} + +static uint32_t HeaderSize(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) { + // Size is in elements, so there is only one header. + return 1; +} + +// The description of each dex file section type. +struct FileSectionDescriptor { + public: + 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; + // 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; +}; + +static const std::vector<FileSectionDescriptor> kFileSectionDescriptors = { + { + "Header", + DexFile::kDexTypeHeaderItem, + &HeaderSize, + &HeaderOffset, + }, { + "StringId", + DexFile::kDexTypeStringIdItem, + &dex_ir::Collections::StringIdsSize, + &dex_ir::Collections::StringIdsOffset + }, { + "TypeId", + DexFile::kDexTypeTypeIdItem, + &dex_ir::Collections::TypeIdsSize, + &dex_ir::Collections::TypeIdsOffset + }, { + "ProtoId", + DexFile::kDexTypeProtoIdItem, + &dex_ir::Collections::ProtoIdsSize, + &dex_ir::Collections::ProtoIdsOffset + }, { + "FieldId", + DexFile::kDexTypeFieldIdItem, + &dex_ir::Collections::FieldIdsSize, + &dex_ir::Collections::FieldIdsOffset + }, { + "MethodId", + DexFile::kDexTypeMethodIdItem, + &dex_ir::Collections::MethodIdsSize, + &dex_ir::Collections::MethodIdsOffset + }, { + "ClassDef", + DexFile::kDexTypeClassDefItem, + &dex_ir::Collections::ClassDefsSize, + &dex_ir::Collections::ClassDefsOffset + }, { + "StringData", + DexFile::kDexTypeStringDataItem, + &dex_ir::Collections::StringDatasSize, + &dex_ir::Collections::StringDatasOffset + }, { + "TypeList", + DexFile::kDexTypeTypeList, + &dex_ir::Collections::TypeListsSize, + &dex_ir::Collections::TypeListsOffset + }, { + "EncArr", + DexFile::kDexTypeEncodedArrayItem, + &dex_ir::Collections::EncodedArrayItemsSize, + &dex_ir::Collections::EncodedArrayItemsOffset + }, { + "Annotation", + DexFile::kDexTypeAnnotationItem, + &dex_ir::Collections::AnnotationItemsSize, + &dex_ir::Collections::AnnotationItemsOffset + }, { + "AnnoSet", + DexFile::kDexTypeAnnotationSetItem, + &dex_ir::Collections::AnnotationSetItemsSize, + &dex_ir::Collections::AnnotationSetItemsOffset + }, { + "AnnoSetRL", + DexFile::kDexTypeAnnotationSetRefList, + &dex_ir::Collections::AnnotationSetRefListsSize, + &dex_ir::Collections::AnnotationSetRefListsOffset + }, { + "AnnoDir", + DexFile::kDexTypeAnnotationsDirectoryItem, + &dex_ir::Collections::AnnotationsDirectoryItemsSize, + &dex_ir::Collections::AnnotationsDirectoryItemsOffset + }, { + "DebugInfo", + DexFile::kDexTypeDebugInfoItem, + &dex_ir::Collections::DebugInfoItemsSize, + &dex_ir::Collections::DebugInfoItemsOffset + }, { + "CodeItem", + DexFile::kDexTypeCodeItem, + &dex_ir::Collections::CodeItemsSize, + &dex_ir::Collections::CodeItemsOffset + }, { + "ClassData", + DexFile::kDexTypeClassDataItem, + &dex_ir::Collections::ClassDatasSize, + &dex_ir::Collections::ClassDatasOffset + } +}; + +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))); + } + // Sort by offset. + std::sort(sorted_sections.begin(), + sorted_sections.end(), + [=](dex_ir::DexFileSection& a, dex_ir::DexFileSection& b) { + if (direction == SortDirection::kSortDescending) { + return a.offset > b.offset; + } else { + return a.offset < b.offset; + } + }); + return sorted_sections; +} + } // namespace dex_ir } // namespace art |