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