Home | History | Annotate | Download | only in dexlayout
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  * Implementation file of the dexlayout utility.
     17  *
     18  * This is a tool to read dex files into an internal representation,
     19  * reorganize the representation, and emit dex files with a better
     20  * file layout.
     21  */
     22 
     23 #include "dex_ir.h"
     24 #include "dex_instruction-inl.h"
     25 #include "dex_ir_builder.h"
     26 
     27 namespace art {
     28 namespace dex_ir {
     29 
     30 static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) {
     31   uint64_t value = 0;
     32   for (uint32_t i = 0; i <= length; i++) {
     33     value |= static_cast<uint64_t>(*(*data)++) << (i * 8);
     34   }
     35   if (sign_extend) {
     36     int shift = (7 - length) * 8;
     37     return (static_cast<int64_t>(value) << shift) >> shift;
     38   }
     39   return value;
     40 }
     41 
     42 static bool GetPositionsCb(void* context, const DexFile::PositionInfo& entry) {
     43   DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
     44   PositionInfoVector& positions = debug_info->GetPositionInfo();
     45   positions.push_back(std::unique_ptr<PositionInfo>(new PositionInfo(entry.address_, entry.line_)));
     46   return false;
     47 }
     48 
     49 static void GetLocalsCb(void* context, const DexFile::LocalInfo& entry) {
     50   DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
     51   LocalInfoVector& locals = debug_info->GetLocalInfo();
     52   const char* name = entry.name_ != nullptr ? entry.name_ : "(null)";
     53   const char* descriptor = entry.descriptor_ != nullptr ? entry.descriptor_ : "";
     54   const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
     55   locals.push_back(std::unique_ptr<LocalInfo>(
     56       new LocalInfo(name, descriptor, signature, entry.start_address_, entry.end_address_,
     57                     entry.reg_)));
     58 }
     59 
     60 static uint32_t GetDebugInfoStreamSize(const uint8_t* debug_info_stream) {
     61   const uint8_t* stream = debug_info_stream;
     62   DecodeUnsignedLeb128(&stream);  // line_start
     63   uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
     64   for (uint32_t i = 0; i < parameters_size; ++i) {
     65     DecodeUnsignedLeb128P1(&stream);  // Parameter name.
     66   }
     67 
     68   for (;;)  {
     69     uint8_t opcode = *stream++;
     70     switch (opcode) {
     71       case DexFile::DBG_END_SEQUENCE:
     72         return stream - debug_info_stream;  // end of stream.
     73       case DexFile::DBG_ADVANCE_PC:
     74         DecodeUnsignedLeb128(&stream);  // addr_diff
     75         break;
     76       case DexFile::DBG_ADVANCE_LINE:
     77         DecodeSignedLeb128(&stream);  // line_diff
     78         break;
     79       case DexFile::DBG_START_LOCAL:
     80         DecodeUnsignedLeb128(&stream);  // register_num
     81         DecodeUnsignedLeb128P1(&stream);  // name_idx
     82         DecodeUnsignedLeb128P1(&stream);  // type_idx
     83         break;
     84       case DexFile::DBG_START_LOCAL_EXTENDED:
     85         DecodeUnsignedLeb128(&stream);  // register_num
     86         DecodeUnsignedLeb128P1(&stream);  // name_idx
     87         DecodeUnsignedLeb128P1(&stream);  // type_idx
     88         DecodeUnsignedLeb128P1(&stream);  // sig_idx
     89         break;
     90       case DexFile::DBG_END_LOCAL:
     91       case DexFile::DBG_RESTART_LOCAL:
     92         DecodeUnsignedLeb128(&stream);  // register_num
     93         break;
     94       case DexFile::DBG_SET_PROLOGUE_END:
     95       case DexFile::DBG_SET_EPILOGUE_BEGIN:
     96         break;
     97       case DexFile::DBG_SET_FILE: {
     98         DecodeUnsignedLeb128P1(&stream);  // name_idx
     99         break;
    100       }
    101       default: {
    102         break;
    103       }
    104     }
    105   }
    106 }
    107 
    108 static bool GetIdFromInstruction(Collections& collections,
    109                                  const Instruction* dec_insn,
    110                                  std::vector<TypeId*>* type_ids,
    111                                  std::vector<StringId*>* string_ids,
    112                                  std::vector<MethodId*>* method_ids,
    113                                  std::vector<FieldId*>* field_ids) {
    114   // Determine index and width of the string.
    115   uint32_t index = 0;
    116   switch (Instruction::FormatOf(dec_insn->Opcode())) {
    117     // SOME NOT SUPPORTED:
    118     // case Instruction::k20bc:
    119     case Instruction::k21c:
    120     case Instruction::k35c:
    121     // case Instruction::k35ms:
    122     case Instruction::k3rc:
    123     // case Instruction::k3rms:
    124     // case Instruction::k35mi:
    125     // case Instruction::k3rmi:
    126     case Instruction::k45cc:
    127     case Instruction::k4rcc:
    128       index = dec_insn->VRegB();
    129       break;
    130     case Instruction::k31c:
    131       index = dec_insn->VRegB();
    132       break;
    133     case Instruction::k22c:
    134     // case Instruction::k22cs:
    135       index = dec_insn->VRegC();
    136       break;
    137     default:
    138       break;
    139   }  // switch
    140 
    141   // Determine index type, and add reference to the appropriate collection.
    142   switch (Instruction::IndexTypeOf(dec_insn->Opcode())) {
    143     case Instruction::kIndexTypeRef:
    144       if (index < collections.TypeIdsSize()) {
    145         type_ids->push_back(collections.GetTypeId(index));
    146         return true;
    147       }
    148       break;
    149     case Instruction::kIndexStringRef:
    150       if (index < collections.StringIdsSize()) {
    151         string_ids->push_back(collections.GetStringId(index));
    152         return true;
    153       }
    154       break;
    155     case Instruction::kIndexMethodRef:
    156     case Instruction::kIndexMethodAndProtoRef:
    157       if (index < collections.MethodIdsSize()) {
    158         method_ids->push_back(collections.GetMethodId(index));
    159         return true;
    160       }
    161       break;
    162     case Instruction::kIndexFieldRef:
    163       if (index < collections.FieldIdsSize()) {
    164         field_ids->push_back(collections.GetFieldId(index));
    165         return true;
    166       }
    167       break;
    168     case Instruction::kIndexUnknown:
    169     case Instruction::kIndexNone:
    170     case Instruction::kIndexVtableOffset:
    171     case Instruction::kIndexFieldOffset:
    172     default:
    173       break;
    174   }  // switch
    175   return false;
    176 }
    177 
    178 /*
    179  * Get all the types, strings, methods, and fields referred to from bytecode.
    180  */
    181 static bool GetIdsFromByteCode(Collections& collections,
    182                                const CodeItem* code,
    183                                std::vector<TypeId*>* type_ids,
    184                                std::vector<StringId*>* string_ids,
    185                                std::vector<MethodId*>* method_ids,
    186                                std::vector<FieldId*>* field_ids) {
    187   bool has_id = false;
    188   // Iterate over all instructions.
    189   const uint16_t* insns = code->Insns();
    190   for (uint32_t insn_idx = 0; insn_idx < code->InsnsSize();) {
    191     const Instruction* instruction = Instruction::At(&insns[insn_idx]);
    192     const uint32_t insn_width = instruction->SizeInCodeUnits();
    193     if (insn_width == 0) {
    194       break;
    195     }
    196     has_id |= GetIdFromInstruction(collections,
    197                                    instruction,
    198                                    type_ids,
    199                                    string_ids,
    200                                    method_ids,
    201                                    field_ids);
    202     insn_idx += insn_width;
    203   }  // for
    204   return has_id;
    205 }
    206 
    207 EncodedValue* Collections::ReadEncodedValue(const uint8_t** data) {
    208   const uint8_t encoded_value = *(*data)++;
    209   const uint8_t type = encoded_value & 0x1f;
    210   EncodedValue* item = new EncodedValue(type);
    211   ReadEncodedValue(data, type, encoded_value >> 5, item);
    212   return item;
    213 }
    214 
    215 EncodedValue* Collections::ReadEncodedValue(const uint8_t** data, uint8_t type, uint8_t length) {
    216   EncodedValue* item = new EncodedValue(type);
    217   ReadEncodedValue(data, type, length, item);
    218   return item;
    219 }
    220 
    221 void Collections::ReadEncodedValue(
    222     const uint8_t** data, uint8_t type, uint8_t length, EncodedValue* item) {
    223   switch (type) {
    224     case DexFile::kDexAnnotationByte:
    225       item->SetByte(static_cast<int8_t>(ReadVarWidth(data, length, false)));
    226       break;
    227     case DexFile::kDexAnnotationShort:
    228       item->SetShort(static_cast<int16_t>(ReadVarWidth(data, length, true)));
    229       break;
    230     case DexFile::kDexAnnotationChar:
    231       item->SetChar(static_cast<uint16_t>(ReadVarWidth(data, length, false)));
    232       break;
    233     case DexFile::kDexAnnotationInt:
    234       item->SetInt(static_cast<int32_t>(ReadVarWidth(data, length, true)));
    235       break;
    236     case DexFile::kDexAnnotationLong:
    237       item->SetLong(static_cast<int64_t>(ReadVarWidth(data, length, true)));
    238       break;
    239     case DexFile::kDexAnnotationFloat: {
    240       // Fill on right.
    241       union {
    242         float f;
    243         uint32_t data;
    244       } conv;
    245       conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
    246       item->SetFloat(conv.f);
    247       break;
    248     }
    249     case DexFile::kDexAnnotationDouble: {
    250       // Fill on right.
    251       union {
    252         double d;
    253         uint64_t data;
    254       } conv;
    255       conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
    256       item->SetDouble(conv.d);
    257       break;
    258     }
    259     case DexFile::kDexAnnotationMethodType: {
    260       const uint32_t proto_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
    261       item->SetProtoId(GetProtoId(proto_index));
    262       break;
    263     }
    264     case DexFile::kDexAnnotationMethodHandle: {
    265       const uint32_t method_handle_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
    266       item->SetMethodHandle(GetMethodHandle(method_handle_index));
    267       break;
    268     }
    269     case DexFile::kDexAnnotationString: {
    270       const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
    271       item->SetStringId(GetStringId(string_index));
    272       break;
    273     }
    274     case DexFile::kDexAnnotationType: {
    275       const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
    276       item->SetTypeId(GetTypeId(string_index));
    277       break;
    278     }
    279     case DexFile::kDexAnnotationField:
    280     case DexFile::kDexAnnotationEnum: {
    281       const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
    282       item->SetFieldId(GetFieldId(field_index));
    283       break;
    284     }
    285     case DexFile::kDexAnnotationMethod: {
    286       const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
    287       item->SetMethodId(GetMethodId(method_index));
    288       break;
    289     }
    290     case DexFile::kDexAnnotationArray: {
    291       EncodedValueVector* values = new EncodedValueVector();
    292       const uint32_t size = DecodeUnsignedLeb128(data);
    293       // Decode all elements.
    294       for (uint32_t i = 0; i < size; i++) {
    295         values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(data)));
    296       }
    297       item->SetEncodedArray(new EncodedArrayItem(values));
    298       break;
    299     }
    300     case DexFile::kDexAnnotationAnnotation: {
    301       AnnotationElementVector* elements = new AnnotationElementVector();
    302       const uint32_t type_idx = DecodeUnsignedLeb128(data);
    303       const uint32_t size = DecodeUnsignedLeb128(data);
    304       // Decode all name=value pairs.
    305       for (uint32_t i = 0; i < size; i++) {
    306         const uint32_t name_index = DecodeUnsignedLeb128(data);
    307         elements->push_back(std::unique_ptr<AnnotationElement>(
    308             new AnnotationElement(GetStringId(name_index), ReadEncodedValue(data))));
    309       }
    310       item->SetEncodedAnnotation(new EncodedAnnotation(GetTypeId(type_idx), elements));
    311       break;
    312     }
    313     case DexFile::kDexAnnotationNull:
    314       break;
    315     case DexFile::kDexAnnotationBoolean:
    316       item->SetBoolean(length != 0);
    317       break;
    318     default:
    319       break;
    320   }
    321 }
    322 
    323 void Collections::CreateStringId(const DexFile& dex_file, uint32_t i) {
    324   const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i));
    325   StringData* string_data = new StringData(dex_file.GetStringData(disk_string_id));
    326   string_datas_.AddItem(string_data, disk_string_id.string_data_off_);
    327 
    328   StringId* string_id = new StringId(string_data);
    329   string_ids_.AddIndexedItem(string_id, StringIdsOffset() + i * StringId::ItemSize(), i);
    330 }
    331 
    332 void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) {
    333   const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i));
    334   TypeId* type_id = new TypeId(GetStringId(disk_type_id.descriptor_idx_.index_));
    335   type_ids_.AddIndexedItem(type_id, TypeIdsOffset() + i * TypeId::ItemSize(), i);
    336 }
    337 
    338 void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) {
    339   const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i);
    340   const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
    341   TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_);
    342 
    343   ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_.index_),
    344                                   GetTypeId(disk_proto_id.return_type_idx_.index_),
    345                                   parameter_type_list);
    346   proto_ids_.AddIndexedItem(proto_id, ProtoIdsOffset() + i * ProtoId::ItemSize(), i);
    347 }
    348 
    349 void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) {
    350   const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
    351   FieldId* field_id = new FieldId(GetTypeId(disk_field_id.class_idx_.index_),
    352                                   GetTypeId(disk_field_id.type_idx_.index_),
    353                                   GetStringId(disk_field_id.name_idx_.index_));
    354   field_ids_.AddIndexedItem(field_id, FieldIdsOffset() + i * FieldId::ItemSize(), i);
    355 }
    356 
    357 void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) {
    358   const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
    359   MethodId* method_id = new MethodId(GetTypeId(disk_method_id.class_idx_.index_),
    360                                      GetProtoId(disk_method_id.proto_idx_),
    361                                      GetStringId(disk_method_id.name_idx_.index_));
    362   method_ids_.AddIndexedItem(method_id, MethodIdsOffset() + i * MethodId::ItemSize(), i);
    363 }
    364 
    365 void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) {
    366   const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
    367   const TypeId* class_type = GetTypeId(disk_class_def.class_idx_.index_);
    368   uint32_t access_flags = disk_class_def.access_flags_;
    369   const TypeId* superclass = GetTypeIdOrNullPtr(disk_class_def.superclass_idx_.index_);
    370 
    371   const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
    372   TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_);
    373 
    374   const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_.index_);
    375   // Annotations.
    376   AnnotationsDirectoryItem* annotations = nullptr;
    377   const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
    378       dex_file.GetAnnotationsDirectory(disk_class_def);
    379   if (disk_annotations_directory_item != nullptr) {
    380     annotations = CreateAnnotationsDirectoryItem(
    381         dex_file, disk_annotations_directory_item, disk_class_def.annotations_off_);
    382   }
    383   // Static field initializers.
    384   const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def);
    385   EncodedArrayItem* static_values =
    386       CreateEncodedArrayItem(static_data, disk_class_def.static_values_off_);
    387   ClassData* class_data = CreateClassData(
    388       dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_);
    389   ClassDef* class_def = new ClassDef(class_type, access_flags, superclass, interfaces_type_list,
    390                                      source_file, annotations, static_values, class_data);
    391   class_defs_.AddIndexedItem(class_def, ClassDefsOffset() + i * ClassDef::ItemSize(), i);
    392 }
    393 
    394 TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) {
    395   if (dex_type_list == nullptr) {
    396     return nullptr;
    397   }
    398   auto found_type_list = TypeLists().find(offset);
    399   if (found_type_list != TypeLists().end()) {
    400     return found_type_list->second.get();
    401   }
    402   TypeIdVector* type_vector = new TypeIdVector();
    403   uint32_t size = dex_type_list->Size();
    404   for (uint32_t index = 0; index < size; ++index) {
    405     type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_.index_));
    406   }
    407   TypeList* new_type_list = new TypeList(type_vector);
    408   type_lists_.AddItem(new_type_list, offset);
    409   return new_type_list;
    410 }
    411 
    412 EncodedArrayItem* Collections::CreateEncodedArrayItem(const uint8_t* static_data, uint32_t offset) {
    413   if (static_data == nullptr) {
    414     return nullptr;
    415   }
    416   auto found_encoded_array_item = EncodedArrayItems().find(offset);
    417   if (found_encoded_array_item != EncodedArrayItems().end()) {
    418     return found_encoded_array_item->second.get();
    419   }
    420   uint32_t size = DecodeUnsignedLeb128(&static_data);
    421   EncodedValueVector* values = new EncodedValueVector();
    422   for (uint32_t i = 0; i < size; ++i) {
    423     values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(&static_data)));
    424   }
    425   // TODO: Calculate the size of the encoded array.
    426   EncodedArrayItem* encoded_array_item = new EncodedArrayItem(values);
    427   encoded_array_items_.AddItem(encoded_array_item, offset);
    428   return encoded_array_item;
    429 }
    430 
    431 AnnotationItem* Collections::CreateAnnotationItem(const DexFile::AnnotationItem* annotation,
    432                                                   uint32_t offset) {
    433   auto found_annotation_item = AnnotationItems().find(offset);
    434   if (found_annotation_item != AnnotationItems().end()) {
    435     return found_annotation_item->second.get();
    436   }
    437   uint8_t visibility = annotation->visibility_;
    438   const uint8_t* annotation_data = annotation->annotation_;
    439   std::unique_ptr<EncodedValue> encoded_value(
    440       ReadEncodedValue(&annotation_data, DexFile::kDexAnnotationAnnotation, 0));
    441   // TODO: Calculate the size of the annotation.
    442   AnnotationItem* annotation_item =
    443       new AnnotationItem(visibility, encoded_value->ReleaseEncodedAnnotation());
    444   annotation_items_.AddItem(annotation_item, offset);
    445   return annotation_item;
    446 }
    447 
    448 
    449 AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file,
    450     const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset) {
    451   if (disk_annotations_item == nullptr || (disk_annotations_item->size_ == 0 && offset == 0)) {
    452     return nullptr;
    453   }
    454   auto found_anno_set_item = AnnotationSetItems().find(offset);
    455   if (found_anno_set_item != AnnotationSetItems().end()) {
    456     return found_anno_set_item->second.get();
    457   }
    458   std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
    459   for (uint32_t i = 0; i < disk_annotations_item->size_; ++i) {
    460     const DexFile::AnnotationItem* annotation =
    461         dex_file.GetAnnotationItem(disk_annotations_item, i);
    462     if (annotation == nullptr) {
    463       continue;
    464     }
    465     AnnotationItem* annotation_item =
    466         CreateAnnotationItem(annotation, disk_annotations_item->entries_[i]);
    467     items->push_back(annotation_item);
    468   }
    469   AnnotationSetItem* annotation_set_item = new AnnotationSetItem(items);
    470   annotation_set_items_.AddItem(annotation_set_item, offset);
    471   return annotation_set_item;
    472 }
    473 
    474 AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
    475     const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
    476   auto found_anno_dir_item = AnnotationsDirectoryItems().find(offset);
    477   if (found_anno_dir_item != AnnotationsDirectoryItems().end()) {
    478     return found_anno_dir_item->second.get();
    479   }
    480   const DexFile::AnnotationSetItem* class_set_item =
    481       dex_file.GetClassAnnotationSet(disk_annotations_item);
    482   AnnotationSetItem* class_annotation = nullptr;
    483   if (class_set_item != nullptr) {
    484     uint32_t item_offset = disk_annotations_item->class_annotations_off_;
    485     class_annotation = CreateAnnotationSetItem(dex_file, class_set_item, item_offset);
    486   }
    487   const DexFile::FieldAnnotationsItem* fields =
    488       dex_file.GetFieldAnnotations(disk_annotations_item);
    489   FieldAnnotationVector* field_annotations = nullptr;
    490   if (fields != nullptr) {
    491     field_annotations = new FieldAnnotationVector();
    492     for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
    493       FieldId* field_id = GetFieldId(fields[i].field_idx_);
    494       const DexFile::AnnotationSetItem* field_set_item =
    495           dex_file.GetFieldAnnotationSetItem(fields[i]);
    496       uint32_t annotation_set_offset = fields[i].annotations_off_;
    497       AnnotationSetItem* annotation_set_item =
    498           CreateAnnotationSetItem(dex_file, field_set_item, annotation_set_offset);
    499       field_annotations->push_back(std::unique_ptr<FieldAnnotation>(
    500           new FieldAnnotation(field_id, annotation_set_item)));
    501     }
    502   }
    503   const DexFile::MethodAnnotationsItem* methods =
    504       dex_file.GetMethodAnnotations(disk_annotations_item);
    505   MethodAnnotationVector* method_annotations = nullptr;
    506   if (methods != nullptr) {
    507     method_annotations = new MethodAnnotationVector();
    508     for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
    509       MethodId* method_id = GetMethodId(methods[i].method_idx_);
    510       const DexFile::AnnotationSetItem* method_set_item =
    511           dex_file.GetMethodAnnotationSetItem(methods[i]);
    512       uint32_t annotation_set_offset = methods[i].annotations_off_;
    513       AnnotationSetItem* annotation_set_item =
    514           CreateAnnotationSetItem(dex_file, method_set_item, annotation_set_offset);
    515       method_annotations->push_back(std::unique_ptr<MethodAnnotation>(
    516           new MethodAnnotation(method_id, annotation_set_item)));
    517     }
    518   }
    519   const DexFile::ParameterAnnotationsItem* parameters =
    520       dex_file.GetParameterAnnotations(disk_annotations_item);
    521   ParameterAnnotationVector* parameter_annotations = nullptr;
    522   if (parameters != nullptr) {
    523     parameter_annotations = new ParameterAnnotationVector();
    524     for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
    525       MethodId* method_id = GetMethodId(parameters[i].method_idx_);
    526       const DexFile::AnnotationSetRefList* list =
    527           dex_file.GetParameterAnnotationSetRefList(&parameters[i]);
    528       parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
    529           GenerateParameterAnnotation(dex_file, method_id, list, parameters[i].annotations_off_)));
    530     }
    531   }
    532   // TODO: Calculate the size of the annotations directory.
    533   AnnotationsDirectoryItem* annotations_directory_item = new AnnotationsDirectoryItem(
    534       class_annotation, field_annotations, method_annotations, parameter_annotations);
    535   annotations_directory_items_.AddItem(annotations_directory_item, offset);
    536   return annotations_directory_item;
    537 }
    538 
    539 ParameterAnnotation* Collections::GenerateParameterAnnotation(
    540     const DexFile& dex_file, MethodId* method_id,
    541     const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) {
    542   AnnotationSetRefList* set_ref_list = nullptr;
    543   auto found_set_ref_list = AnnotationSetRefLists().find(offset);
    544   if (found_set_ref_list != AnnotationSetRefLists().end()) {
    545     set_ref_list = found_set_ref_list->second.get();
    546   }
    547   if (set_ref_list == nullptr) {
    548     std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
    549     for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
    550       const DexFile::AnnotationSetItem* annotation_set_item =
    551           dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
    552       uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
    553       annotations->push_back(CreateAnnotationSetItem(dex_file, annotation_set_item, set_offset));
    554     }
    555     set_ref_list = new AnnotationSetRefList(annotations);
    556     annotation_set_ref_lists_.AddItem(set_ref_list, offset);
    557   }
    558   return new ParameterAnnotation(method_id, set_ref_list);
    559 }
    560 
    561 CodeItem* Collections::CreateCodeItem(const DexFile& dex_file,
    562                                       const DexFile::CodeItem& disk_code_item, uint32_t offset) {
    563   uint16_t registers_size = disk_code_item.registers_size_;
    564   uint16_t ins_size = disk_code_item.ins_size_;
    565   uint16_t outs_size = disk_code_item.outs_size_;
    566   uint32_t tries_size = disk_code_item.tries_size_;
    567 
    568   // TODO: Calculate the size of the debug info.
    569   const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(&disk_code_item);
    570   DebugInfoItem* debug_info = nullptr;
    571   if (debug_info_stream != nullptr) {
    572     debug_info = debug_info_items_.GetExistingObject(disk_code_item.debug_info_off_);
    573     if (debug_info == nullptr) {
    574       uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream);
    575       uint8_t* debug_info_buffer = new uint8_t[debug_info_size];
    576       memcpy(debug_info_buffer, debug_info_stream, debug_info_size);
    577       debug_info = new DebugInfoItem(debug_info_size, debug_info_buffer);
    578       debug_info_items_.AddItem(debug_info, disk_code_item.debug_info_off_);
    579     }
    580   }
    581 
    582   uint32_t insns_size = disk_code_item.insns_size_in_code_units_;
    583   uint16_t* insns = new uint16_t[insns_size];
    584   memcpy(insns, disk_code_item.insns_, insns_size * sizeof(uint16_t));
    585 
    586   TryItemVector* tries = nullptr;
    587   CatchHandlerVector* handler_list = nullptr;
    588   if (tries_size > 0) {
    589     tries = new TryItemVector();
    590     handler_list = new CatchHandlerVector();
    591     for (uint32_t i = 0; i < tries_size; ++i) {
    592       const DexFile::TryItem* disk_try_item = dex_file.GetTryItems(disk_code_item, i);
    593       uint32_t start_addr = disk_try_item->start_addr_;
    594       uint16_t insn_count = disk_try_item->insn_count_;
    595       uint16_t handler_off = disk_try_item->handler_off_;
    596       const CatchHandler* handlers = nullptr;
    597       for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
    598         if (handler_off == existing_handlers->GetListOffset()) {
    599           handlers = existing_handlers.get();
    600           break;
    601         }
    602       }
    603       if (handlers == nullptr) {
    604         bool catch_all = false;
    605         TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
    606         for (CatchHandlerIterator it(disk_code_item, *disk_try_item); it.HasNext(); it.Next()) {
    607           const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
    608           const TypeId* type_id = GetTypeIdOrNullPtr(type_index.index_);
    609           catch_all |= type_id == nullptr;
    610           addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>(
    611               new TypeAddrPair(type_id, it.GetHandlerAddress())));
    612         }
    613         handlers = new CatchHandler(catch_all, handler_off, addr_pairs);
    614         handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers));
    615       }
    616       TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
    617       tries->push_back(std::unique_ptr<const TryItem>(try_item));
    618     }
    619     // Manually walk catch handlers list and add any missing handlers unreferenced by try items.
    620     const uint8_t* handlers_base = DexFile::GetCatchHandlerData(disk_code_item, 0);
    621     const uint8_t* handlers_data = handlers_base;
    622     uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data);
    623     while (handlers_size > handler_list->size()) {
    624       bool already_added = false;
    625       uint16_t handler_off = handlers_data - handlers_base;
    626       for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
    627         if (handler_off == existing_handlers->GetListOffset()) {
    628           already_added = true;
    629           break;
    630         }
    631       }
    632       int32_t size = DecodeSignedLeb128(&handlers_data);
    633       bool has_catch_all = size <= 0;
    634       if (has_catch_all) {
    635         size = -size;
    636       }
    637       if (already_added) {
    638         for (int32_t i = 0; i < size; i++) {
    639           DecodeUnsignedLeb128(&handlers_data);
    640           DecodeUnsignedLeb128(&handlers_data);
    641         }
    642         if (has_catch_all) {
    643           DecodeUnsignedLeb128(&handlers_data);
    644         }
    645         continue;
    646       }
    647       TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
    648       for (int32_t i = 0; i < size; i++) {
    649         const TypeId* type_id = GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data));
    650         uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
    651         addr_pairs->push_back(
    652             std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr)));
    653       }
    654       if (has_catch_all) {
    655         uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
    656         addr_pairs->push_back(
    657             std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr)));
    658       }
    659       const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs);
    660       handler_list->push_back(std::unique_ptr<const CatchHandler>(handler));
    661     }
    662   }
    663 
    664   uint32_t size = DexFile::GetCodeItemSize(disk_code_item);
    665   CodeItem* code_item = new CodeItem(
    666       registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries, handler_list);
    667   code_item->SetSize(size);
    668   code_items_.AddItem(code_item, offset);
    669   // Add "fixup" references to types, strings, methods, and fields.
    670   // This is temporary, as we will probably want more detailed parsing of the
    671   // instructions here.
    672   std::unique_ptr<std::vector<TypeId*>> type_ids(new std::vector<TypeId*>());
    673   std::unique_ptr<std::vector<StringId*>> string_ids(new std::vector<StringId*>());
    674   std::unique_ptr<std::vector<MethodId*>> method_ids(new std::vector<MethodId*>());
    675   std::unique_ptr<std::vector<FieldId*>> field_ids(new std::vector<FieldId*>());
    676   if (GetIdsFromByteCode(*this,
    677                          code_item,
    678                          type_ids.get(),
    679                          string_ids.get(),
    680                          method_ids.get(),
    681                          field_ids.get())) {
    682     CodeFixups* fixups = new CodeFixups(type_ids.release(),
    683                                         string_ids.release(),
    684                                         method_ids.release(),
    685                                         field_ids.release());
    686     code_item->SetCodeFixups(fixups);
    687   }
    688 
    689   return code_item;
    690 }
    691 
    692 MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
    693   MethodId* method_id = GetMethodId(cdii.GetMemberIndex());
    694   uint32_t access_flags = cdii.GetRawMemberAccessFlags();
    695   const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
    696   CodeItem* code_item = code_items_.GetExistingObject(cdii.GetMethodCodeItemOffset());
    697   DebugInfoItem* debug_info = nullptr;
    698   if (disk_code_item != nullptr) {
    699     if (code_item == nullptr) {
    700       code_item = CreateCodeItem(dex_file, *disk_code_item, cdii.GetMethodCodeItemOffset());
    701     }
    702     debug_info = code_item->DebugInfo();
    703   }
    704   if (debug_info != nullptr) {
    705     bool is_static = (access_flags & kAccStatic) != 0;
    706     dex_file.DecodeDebugLocalInfo(
    707         disk_code_item, is_static, cdii.GetMemberIndex(), GetLocalsCb, debug_info);
    708     dex_file.DecodeDebugPositionInfo(disk_code_item, GetPositionsCb, debug_info);
    709   }
    710   return new MethodItem(access_flags, method_id, code_item);
    711 }
    712 
    713 ClassData* Collections::CreateClassData(
    714     const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
    715   // Read the fields and methods defined by the class, resolving the circular reference from those
    716   // to classes by setting class at the same time.
    717   ClassData* class_data = class_datas_.GetExistingObject(offset);
    718   if (class_data == nullptr && encoded_data != nullptr) {
    719     ClassDataItemIterator cdii(dex_file, encoded_data);
    720     // Static fields.
    721     FieldItemVector* static_fields = new FieldItemVector();
    722     for (; cdii.HasNextStaticField(); cdii.Next()) {
    723       FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
    724       uint32_t access_flags = cdii.GetRawMemberAccessFlags();
    725       static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
    726     }
    727     // Instance fields.
    728     FieldItemVector* instance_fields = new FieldItemVector();
    729     for (; cdii.HasNextInstanceField(); cdii.Next()) {
    730       FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
    731       uint32_t access_flags = cdii.GetRawMemberAccessFlags();
    732       instance_fields->push_back(
    733           std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
    734     }
    735     // Direct methods.
    736     MethodItemVector* direct_methods = new MethodItemVector();
    737     for (; cdii.HasNextDirectMethod(); cdii.Next()) {
    738       direct_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
    739     }
    740     // Virtual methods.
    741     MethodItemVector* virtual_methods = new MethodItemVector();
    742     for (; cdii.HasNextVirtualMethod(); cdii.Next()) {
    743       virtual_methods->push_back(std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
    744     }
    745     class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
    746     class_data->SetSize(cdii.EndDataPointer() - encoded_data);
    747     class_datas_.AddItem(class_data, offset);
    748   }
    749   return class_data;
    750 }
    751 
    752 void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
    753   // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems.
    754   const DexFile::MapList* map =
    755       reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + MapListOffset());
    756   for (uint32_t i = 0; i < map->size_; ++i) {
    757     const DexFile::MapItem* item = map->list_ + i;
    758     switch (item->type_) {
    759       case DexFile::kDexTypeCallSiteIdItem:
    760         SetCallSiteIdsOffset(item->offset_);
    761         break;
    762       case DexFile::kDexTypeMethodHandleItem:
    763         SetMethodHandleItemsOffset(item->offset_);
    764         break;
    765       default:
    766         break;
    767     }
    768   }
    769   // Populate MethodHandleItems first (CallSiteIds may depend on them).
    770   for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) {
    771     CreateMethodHandleItem(dex_file, i);
    772   }
    773   // Populate CallSiteIds.
    774   for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) {
    775     CreateCallSiteId(dex_file, i);
    776   }
    777 }
    778 
    779 void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
    780   const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i);
    781   const uint8_t* disk_call_item_ptr = dex_file.Begin() + disk_call_site_id.data_off_;
    782   EncodedArrayItem* call_site_item =
    783       CreateEncodedArrayItem(disk_call_item_ptr, disk_call_site_id.data_off_);
    784 
    785   CallSiteId* call_site_id = new CallSiteId(call_site_item);
    786   call_site_ids_.AddIndexedItem(call_site_id, CallSiteIdsOffset() + i * CallSiteId::ItemSize(), i);
    787 }
    788 
    789 void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
    790   const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i);
    791   uint16_t index = disk_method_handle.field_or_method_idx_;
    792   DexFile::MethodHandleType type =
    793       static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_);
    794   bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic ||
    795                    type == DexFile::MethodHandleType::kInvokeInstance ||
    796                    type == DexFile::MethodHandleType::kInvokeConstructor ||
    797                    type == DexFile::MethodHandleType::kInvokeDirect ||
    798                    type == DexFile::MethodHandleType::kInvokeInterface;
    799   static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeInterface,
    800                 "Unexpected method handle types.");
    801   IndexedItem* field_or_method_id;
    802   if (is_invoke) {
    803     field_or_method_id = GetMethodId(index);
    804   } else {
    805     field_or_method_id = GetFieldId(index);
    806   }
    807   MethodHandleItem* method_handle = new MethodHandleItem(type, field_or_method_id);
    808   method_handle_items_.AddIndexedItem(
    809       method_handle, MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(), i);
    810 }
    811 
    812 static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
    813   return 0;
    814 }
    815 
    816 static uint32_t HeaderSize(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) {
    817   // Size is in elements, so there is only one header.
    818   return 1;
    819 }
    820 
    821 // The description of each dex file section type.
    822 struct FileSectionDescriptor {
    823  public:
    824   std::string name;
    825   uint16_t type;
    826   // A function that when applied to a collection object, gives the size of the section.
    827   std::function<uint32_t(const dex_ir::Collections&)> size_fn;
    828   // A function that when applied to a collection object, gives the offset of the section.
    829   std::function<uint32_t(const dex_ir::Collections&)> offset_fn;
    830 };
    831 
    832 static const FileSectionDescriptor kFileSectionDescriptors[] = {
    833   {
    834     "Header",
    835     DexFile::kDexTypeHeaderItem,
    836     &HeaderSize,
    837     &HeaderOffset,
    838   }, {
    839     "StringId",
    840     DexFile::kDexTypeStringIdItem,
    841     &dex_ir::Collections::StringIdsSize,
    842     &dex_ir::Collections::StringIdsOffset
    843   }, {
    844     "TypeId",
    845     DexFile::kDexTypeTypeIdItem,
    846     &dex_ir::Collections::TypeIdsSize,
    847     &dex_ir::Collections::TypeIdsOffset
    848   }, {
    849     "ProtoId",
    850     DexFile::kDexTypeProtoIdItem,
    851     &dex_ir::Collections::ProtoIdsSize,
    852     &dex_ir::Collections::ProtoIdsOffset
    853   }, {
    854     "FieldId",
    855     DexFile::kDexTypeFieldIdItem,
    856     &dex_ir::Collections::FieldIdsSize,
    857     &dex_ir::Collections::FieldIdsOffset
    858   }, {
    859     "MethodId",
    860     DexFile::kDexTypeMethodIdItem,
    861     &dex_ir::Collections::MethodIdsSize,
    862     &dex_ir::Collections::MethodIdsOffset
    863   }, {
    864     "ClassDef",
    865     DexFile::kDexTypeClassDefItem,
    866     &dex_ir::Collections::ClassDefsSize,
    867     &dex_ir::Collections::ClassDefsOffset
    868   }, {
    869     "CallSiteId",
    870     DexFile::kDexTypeCallSiteIdItem,
    871     &dex_ir::Collections::CallSiteIdsSize,
    872     &dex_ir::Collections::CallSiteIdsOffset
    873   }, {
    874     "MethodHandle",
    875     DexFile::kDexTypeMethodHandleItem,
    876     &dex_ir::Collections::MethodHandleItemsSize,
    877     &dex_ir::Collections::MethodHandleItemsOffset
    878   }, {
    879     "StringData",
    880     DexFile::kDexTypeStringDataItem,
    881     &dex_ir::Collections::StringDatasSize,
    882     &dex_ir::Collections::StringDatasOffset
    883   }, {
    884     "TypeList",
    885     DexFile::kDexTypeTypeList,
    886     &dex_ir::Collections::TypeListsSize,
    887     &dex_ir::Collections::TypeListsOffset
    888   }, {
    889     "EncArr",
    890     DexFile::kDexTypeEncodedArrayItem,
    891     &dex_ir::Collections::EncodedArrayItemsSize,
    892     &dex_ir::Collections::EncodedArrayItemsOffset
    893   }, {
    894     "Annotation",
    895     DexFile::kDexTypeAnnotationItem,
    896     &dex_ir::Collections::AnnotationItemsSize,
    897     &dex_ir::Collections::AnnotationItemsOffset
    898   }, {
    899     "AnnoSet",
    900     DexFile::kDexTypeAnnotationSetItem,
    901     &dex_ir::Collections::AnnotationSetItemsSize,
    902     &dex_ir::Collections::AnnotationSetItemsOffset
    903   }, {
    904     "AnnoSetRL",
    905     DexFile::kDexTypeAnnotationSetRefList,
    906     &dex_ir::Collections::AnnotationSetRefListsSize,
    907     &dex_ir::Collections::AnnotationSetRefListsOffset
    908   }, {
    909     "AnnoDir",
    910     DexFile::kDexTypeAnnotationsDirectoryItem,
    911     &dex_ir::Collections::AnnotationsDirectoryItemsSize,
    912     &dex_ir::Collections::AnnotationsDirectoryItemsOffset
    913   }, {
    914     "DebugInfo",
    915     DexFile::kDexTypeDebugInfoItem,
    916     &dex_ir::Collections::DebugInfoItemsSize,
    917     &dex_ir::Collections::DebugInfoItemsOffset
    918   }, {
    919     "CodeItem",
    920     DexFile::kDexTypeCodeItem,
    921     &dex_ir::Collections::CodeItemsSize,
    922     &dex_ir::Collections::CodeItemsOffset
    923   }, {
    924     "ClassData",
    925     DexFile::kDexTypeClassDataItem,
    926     &dex_ir::Collections::ClassDatasSize,
    927     &dex_ir::Collections::ClassDatasOffset
    928   }
    929 };
    930 
    931 std::vector<dex_ir::DexFileSection> GetSortedDexFileSections(dex_ir::Header* header,
    932                                                              dex_ir::SortDirection direction) {
    933   const dex_ir::Collections& collections = header->GetCollections();
    934   std::vector<dex_ir::DexFileSection> sorted_sections;
    935   // Build the table that will map from offset to color
    936   for (const FileSectionDescriptor& s : kFileSectionDescriptors) {
    937     sorted_sections.push_back(dex_ir::DexFileSection(s.name,
    938                                                      s.type,
    939                                                      s.size_fn(collections),
    940                                                      s.offset_fn(collections)));
    941   }
    942   // Sort by offset.
    943   std::sort(sorted_sections.begin(),
    944             sorted_sections.end(),
    945             [=](dex_ir::DexFileSection& a, dex_ir::DexFileSection& b) {
    946               if (direction == SortDirection::kSortDescending) {
    947                 return a.offset > b.offset;
    948               } else {
    949                 return a.offset < b.offset;
    950               }
    951             });
    952   return sorted_sections;
    953 }
    954 
    955 }  // namespace dex_ir
    956 }  // namespace art
    957