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