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  * Header file of an in-memory representation of DEX files.
     17  */
     18 
     19 #include <stdint.h>
     20 
     21 #include <queue>
     22 #include <vector>
     23 
     24 #include "dex_writer.h"
     25 #include "utf.h"
     26 
     27 namespace art {
     28 
     29 size_t EncodeIntValue(int32_t value, uint8_t* buffer) {
     30   size_t length = 0;
     31   if (value >= 0) {
     32     while (value > 0x7f) {
     33       buffer[length++] = static_cast<uint8_t>(value);
     34       value >>= 8;
     35     }
     36   } else {
     37     while (value < -0x80) {
     38       buffer[length++] = static_cast<uint8_t>(value);
     39       value >>= 8;
     40     }
     41   }
     42   buffer[length++] = static_cast<uint8_t>(value);
     43   return length;
     44 }
     45 
     46 size_t EncodeUIntValue(uint32_t value, uint8_t* buffer) {
     47   size_t length = 0;
     48   do {
     49     buffer[length++] = static_cast<uint8_t>(value);
     50     value >>= 8;
     51   } while (value != 0);
     52   return length;
     53 }
     54 
     55 size_t EncodeLongValue(int64_t value, uint8_t* buffer) {
     56   size_t length = 0;
     57   if (value >= 0) {
     58     while (value > 0x7f) {
     59       buffer[length++] = static_cast<uint8_t>(value);
     60       value >>= 8;
     61     }
     62   } else {
     63     while (value < -0x80) {
     64       buffer[length++] = static_cast<uint8_t>(value);
     65       value >>= 8;
     66     }
     67   }
     68   buffer[length++] = static_cast<uint8_t>(value);
     69   return length;
     70 }
     71 
     72 union FloatUnion {
     73   float f_;
     74   uint32_t i_;
     75 };
     76 
     77 size_t EncodeFloatValue(float value, uint8_t* buffer) {
     78   FloatUnion float_union;
     79   float_union.f_ = value;
     80   uint32_t int_value = float_union.i_;
     81   size_t index = 3;
     82   do {
     83     buffer[index--] = int_value >> 24;
     84     int_value <<= 8;
     85   } while (int_value != 0);
     86   return 3 - index;
     87 }
     88 
     89 union DoubleUnion {
     90   double d_;
     91   uint64_t l_;
     92 };
     93 
     94 size_t EncodeDoubleValue(double value, uint8_t* buffer) {
     95   DoubleUnion double_union;
     96   double_union.d_ = value;
     97   uint64_t long_value = double_union.l_;
     98   size_t index = 7;
     99   do {
    100     buffer[index--] = long_value >> 56;
    101     long_value <<= 8;
    102   } while (long_value != 0);
    103   return 7 - index;
    104 }
    105 
    106 size_t DexWriter::Write(const void* buffer, size_t length, size_t offset) {
    107   DCHECK_LE(offset + length, mem_map_->Size());
    108   memcpy(mem_map_->Begin() + offset, buffer, length);
    109   return length;
    110 }
    111 
    112 size_t DexWriter::WriteSleb128(uint32_t value, size_t offset) {
    113   uint8_t buffer[8];
    114   EncodeSignedLeb128(buffer, value);
    115   return Write(buffer, SignedLeb128Size(value), offset);
    116 }
    117 
    118 size_t DexWriter::WriteUleb128(uint32_t value, size_t offset) {
    119   uint8_t buffer[8];
    120   EncodeUnsignedLeb128(buffer, value);
    121   return Write(buffer, UnsignedLeb128Size(value), offset);
    122 }
    123 
    124 size_t DexWriter::WriteEncodedValue(dex_ir::EncodedValue* encoded_value, size_t offset) {
    125   size_t original_offset = offset;
    126   size_t start = 0;
    127   size_t length;
    128   uint8_t buffer[8];
    129   int8_t type = encoded_value->Type();
    130   switch (type) {
    131     case DexFile::kDexAnnotationByte:
    132       length = EncodeIntValue(encoded_value->GetByte(), buffer);
    133       break;
    134     case DexFile::kDexAnnotationShort:
    135       length = EncodeIntValue(encoded_value->GetShort(), buffer);
    136       break;
    137     case DexFile::kDexAnnotationChar:
    138       length = EncodeUIntValue(encoded_value->GetChar(), buffer);
    139       break;
    140     case DexFile::kDexAnnotationInt:
    141       length = EncodeIntValue(encoded_value->GetInt(), buffer);
    142       break;
    143     case DexFile::kDexAnnotationLong:
    144       length = EncodeLongValue(encoded_value->GetLong(), buffer);
    145       break;
    146     case DexFile::kDexAnnotationFloat:
    147       length = EncodeFloatValue(encoded_value->GetFloat(), buffer);
    148       start = 4 - length;
    149       break;
    150     case DexFile::kDexAnnotationDouble:
    151       length = EncodeDoubleValue(encoded_value->GetDouble(), buffer);
    152       start = 8 - length;
    153       break;
    154     case DexFile::kDexAnnotationMethodType:
    155       length = EncodeUIntValue(encoded_value->GetProtoId()->GetIndex(), buffer);
    156       break;
    157     case DexFile::kDexAnnotationMethodHandle:
    158       length = EncodeUIntValue(encoded_value->GetMethodHandle()->GetIndex(), buffer);
    159       break;
    160     case DexFile::kDexAnnotationString:
    161       length = EncodeUIntValue(encoded_value->GetStringId()->GetIndex(), buffer);
    162       break;
    163     case DexFile::kDexAnnotationType:
    164       length = EncodeUIntValue(encoded_value->GetTypeId()->GetIndex(), buffer);
    165       break;
    166     case DexFile::kDexAnnotationField:
    167     case DexFile::kDexAnnotationEnum:
    168       length = EncodeUIntValue(encoded_value->GetFieldId()->GetIndex(), buffer);
    169       break;
    170     case DexFile::kDexAnnotationMethod:
    171       length = EncodeUIntValue(encoded_value->GetMethodId()->GetIndex(), buffer);
    172       break;
    173     case DexFile::kDexAnnotationArray:
    174       offset += WriteEncodedValueHeader(type, 0, offset);
    175       offset += WriteEncodedArray(encoded_value->GetEncodedArray()->GetEncodedValues(), offset);
    176       return offset - original_offset;
    177     case DexFile::kDexAnnotationAnnotation:
    178       offset += WriteEncodedValueHeader(type, 0, offset);
    179       offset += WriteEncodedAnnotation(encoded_value->GetEncodedAnnotation(), offset);
    180       return offset - original_offset;
    181     case DexFile::kDexAnnotationNull:
    182       return WriteEncodedValueHeader(type, 0, offset);
    183     case DexFile::kDexAnnotationBoolean:
    184       return WriteEncodedValueHeader(type, encoded_value->GetBoolean() ? 1 : 0, offset);
    185     default:
    186       return 0;
    187   }
    188   offset += WriteEncodedValueHeader(type, length - 1, offset);
    189   offset += Write(buffer + start, length, offset);
    190   return offset - original_offset;
    191 }
    192 
    193 size_t DexWriter::WriteEncodedValueHeader(int8_t value_type, size_t value_arg, size_t offset) {
    194   uint8_t buffer[1] = { static_cast<uint8_t>((value_arg << 5) | value_type) };
    195   return Write(buffer, sizeof(uint8_t), offset);
    196 }
    197 
    198 size_t DexWriter::WriteEncodedArray(dex_ir::EncodedValueVector* values, size_t offset) {
    199   size_t original_offset = offset;
    200   offset += WriteUleb128(values->size(), offset);
    201   for (std::unique_ptr<dex_ir::EncodedValue>& value : *values) {
    202     offset += WriteEncodedValue(value.get(), offset);
    203   }
    204   return offset - original_offset;
    205 }
    206 
    207 size_t DexWriter::WriteEncodedAnnotation(dex_ir::EncodedAnnotation* annotation, size_t offset) {
    208   size_t original_offset = offset;
    209   offset += WriteUleb128(annotation->GetType()->GetIndex(), offset);
    210   offset += WriteUleb128(annotation->GetAnnotationElements()->size(), offset);
    211   for (std::unique_ptr<dex_ir::AnnotationElement>& annotation_element :
    212       *annotation->GetAnnotationElements()) {
    213     offset += WriteUleb128(annotation_element->GetName()->GetIndex(), offset);
    214     offset += WriteEncodedValue(annotation_element->GetValue(), offset);
    215   }
    216   return offset - original_offset;
    217 }
    218 
    219 size_t DexWriter::WriteEncodedFields(dex_ir::FieldItemVector* fields, size_t offset) {
    220   size_t original_offset = offset;
    221   uint32_t prev_index = 0;
    222   for (std::unique_ptr<dex_ir::FieldItem>& field : *fields) {
    223     uint32_t index = field->GetFieldId()->GetIndex();
    224     offset += WriteUleb128(index - prev_index, offset);
    225     offset += WriteUleb128(field->GetAccessFlags(), offset);
    226     prev_index = index;
    227   }
    228   return offset - original_offset;
    229 }
    230 
    231 size_t DexWriter::WriteEncodedMethods(dex_ir::MethodItemVector* methods, size_t offset) {
    232   size_t original_offset = offset;
    233   uint32_t prev_index = 0;
    234   for (std::unique_ptr<dex_ir::MethodItem>& method : *methods) {
    235     uint32_t index = method->GetMethodId()->GetIndex();
    236     uint32_t code_off = method->GetCodeItem() == nullptr ? 0 : method->GetCodeItem()->GetOffset();
    237     offset += WriteUleb128(index - prev_index, offset);
    238     offset += WriteUleb128(method->GetAccessFlags(), offset);
    239     offset += WriteUleb128(code_off, offset);
    240     prev_index = index;
    241   }
    242   return offset - original_offset;
    243 }
    244 
    245 void DexWriter::WriteStrings() {
    246   uint32_t string_data_off[1];
    247   for (std::unique_ptr<dex_ir::StringId>& string_id : header_->GetCollections().StringIds()) {
    248     string_data_off[0] = string_id->DataItem()->GetOffset();
    249     Write(string_data_off, string_id->GetSize(), string_id->GetOffset());
    250   }
    251 
    252   for (auto& string_data_pair : header_->GetCollections().StringDatas()) {
    253     std::unique_ptr<dex_ir::StringData>& string_data = string_data_pair.second;
    254     uint32_t offset = string_data->GetOffset();
    255     offset += WriteUleb128(CountModifiedUtf8Chars(string_data->Data()), offset);
    256     Write(string_data->Data(), strlen(string_data->Data()), offset);
    257   }
    258 }
    259 
    260 void DexWriter::WriteTypes() {
    261   uint32_t descriptor_idx[1];
    262   for (std::unique_ptr<dex_ir::TypeId>& type_id : header_->GetCollections().TypeIds()) {
    263     descriptor_idx[0] = type_id->GetStringId()->GetIndex();
    264     Write(descriptor_idx, type_id->GetSize(), type_id->GetOffset());
    265   }
    266 }
    267 
    268 void DexWriter::WriteTypeLists() {
    269   uint32_t size[1];
    270   uint16_t list[1];
    271   for (auto& type_list_pair : header_->GetCollections().TypeLists()) {
    272     std::unique_ptr<dex_ir::TypeList>& type_list = type_list_pair.second;
    273     size[0] = type_list->GetTypeList()->size();
    274     uint32_t offset = type_list->GetOffset();
    275     offset += Write(size, sizeof(uint32_t), offset);
    276     for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) {
    277       list[0] = type_id->GetIndex();
    278       offset += Write(list, sizeof(uint16_t), offset);
    279     }
    280   }
    281 }
    282 
    283 void DexWriter::WriteProtos() {
    284   uint32_t buffer[3];
    285   for (std::unique_ptr<dex_ir::ProtoId>& proto_id : header_->GetCollections().ProtoIds()) {
    286     buffer[0] = proto_id->Shorty()->GetIndex();
    287     buffer[1] = proto_id->ReturnType()->GetIndex();
    288     buffer[2] = proto_id->Parameters() == nullptr ? 0 : proto_id->Parameters()->GetOffset();
    289     Write(buffer, proto_id->GetSize(), proto_id->GetOffset());
    290   }
    291 }
    292 
    293 void DexWriter::WriteFields() {
    294   uint16_t buffer[4];
    295   for (std::unique_ptr<dex_ir::FieldId>& field_id : header_->GetCollections().FieldIds()) {
    296     buffer[0] = field_id->Class()->GetIndex();
    297     buffer[1] = field_id->Type()->GetIndex();
    298     buffer[2] = field_id->Name()->GetIndex();
    299     buffer[3] = field_id->Name()->GetIndex() >> 16;
    300     Write(buffer, field_id->GetSize(), field_id->GetOffset());
    301   }
    302 }
    303 
    304 void DexWriter::WriteMethods() {
    305   uint16_t buffer[4];
    306   for (std::unique_ptr<dex_ir::MethodId>& method_id : header_->GetCollections().MethodIds()) {
    307     buffer[0] = method_id->Class()->GetIndex();
    308     buffer[1] = method_id->Proto()->GetIndex();
    309     buffer[2] = method_id->Name()->GetIndex();
    310     buffer[3] = method_id->Name()->GetIndex() >> 16;
    311     Write(buffer, method_id->GetSize(), method_id->GetOffset());
    312   }
    313 }
    314 
    315 void DexWriter::WriteEncodedArrays() {
    316   for (auto& encoded_array_pair : header_->GetCollections().EncodedArrayItems()) {
    317     std::unique_ptr<dex_ir::EncodedArrayItem>& encoded_array = encoded_array_pair.second;
    318     WriteEncodedArray(encoded_array->GetEncodedValues(), encoded_array->GetOffset());
    319   }
    320 }
    321 
    322 void DexWriter::WriteAnnotations() {
    323   uint8_t visibility[1];
    324   for (auto& annotation_pair : header_->GetCollections().AnnotationItems()) {
    325     std::unique_ptr<dex_ir::AnnotationItem>& annotation = annotation_pair.second;
    326     visibility[0] = annotation->GetVisibility();
    327     size_t offset = annotation->GetOffset();
    328     offset += Write(visibility, sizeof(uint8_t), offset);
    329     WriteEncodedAnnotation(annotation->GetAnnotation(), offset);
    330   }
    331 }
    332 
    333 void DexWriter::WriteAnnotationSets() {
    334   uint32_t size[1];
    335   uint32_t annotation_off[1];
    336   for (auto& annotation_set_pair : header_->GetCollections().AnnotationSetItems()) {
    337     std::unique_ptr<dex_ir::AnnotationSetItem>& annotation_set = annotation_set_pair.second;
    338     size[0] = annotation_set->GetItems()->size();
    339     size_t offset = annotation_set->GetOffset();
    340     offset += Write(size, sizeof(uint32_t), offset);
    341     for (dex_ir::AnnotationItem* annotation : *annotation_set->GetItems()) {
    342       annotation_off[0] = annotation->GetOffset();
    343       offset += Write(annotation_off, sizeof(uint32_t), offset);
    344     }
    345   }
    346 }
    347 
    348 void DexWriter::WriteAnnotationSetRefs() {
    349   uint32_t size[1];
    350   uint32_t annotations_off[1];
    351   for (auto& anno_set_ref_pair : header_->GetCollections().AnnotationSetRefLists()) {
    352     std::unique_ptr<dex_ir::AnnotationSetRefList>& annotation_set_ref = anno_set_ref_pair.second;
    353     size[0] = annotation_set_ref->GetItems()->size();
    354     size_t offset = annotation_set_ref->GetOffset();
    355     offset += Write(size, sizeof(uint32_t), offset);
    356     for (dex_ir::AnnotationSetItem* annotation_set : *annotation_set_ref->GetItems()) {
    357       annotations_off[0] = annotation_set == nullptr ? 0 : annotation_set->GetOffset();
    358       offset += Write(annotations_off, sizeof(uint32_t), offset);
    359     }
    360   }
    361 }
    362 
    363 void DexWriter::WriteAnnotationsDirectories() {
    364   uint32_t directory_buffer[4];
    365   uint32_t annotation_buffer[2];
    366   for (auto& annotations_directory_pair : header_->GetCollections().AnnotationsDirectoryItems()) {
    367     std::unique_ptr<dex_ir::AnnotationsDirectoryItem>& annotations_directory =
    368         annotations_directory_pair.second;
    369     directory_buffer[0] = annotations_directory->GetClassAnnotation() == nullptr ? 0 :
    370         annotations_directory->GetClassAnnotation()->GetOffset();
    371     directory_buffer[1] = annotations_directory->GetFieldAnnotations() == nullptr ? 0 :
    372         annotations_directory->GetFieldAnnotations()->size();
    373     directory_buffer[2] = annotations_directory->GetMethodAnnotations() == nullptr ? 0 :
    374         annotations_directory->GetMethodAnnotations()->size();
    375     directory_buffer[3] = annotations_directory->GetParameterAnnotations() == nullptr ? 0 :
    376         annotations_directory->GetParameterAnnotations()->size();
    377     uint32_t offset = annotations_directory->GetOffset();
    378     offset += Write(directory_buffer, 4 * sizeof(uint32_t), offset);
    379     if (annotations_directory->GetFieldAnnotations() != nullptr) {
    380       for (std::unique_ptr<dex_ir::FieldAnnotation>& field :
    381           *annotations_directory->GetFieldAnnotations()) {
    382         annotation_buffer[0] = field->GetFieldId()->GetIndex();
    383         annotation_buffer[1] = field->GetAnnotationSetItem()->GetOffset();
    384         offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
    385       }
    386     }
    387     if (annotations_directory->GetMethodAnnotations() != nullptr) {
    388       for (std::unique_ptr<dex_ir::MethodAnnotation>& method :
    389           *annotations_directory->GetMethodAnnotations()) {
    390         annotation_buffer[0] = method->GetMethodId()->GetIndex();
    391         annotation_buffer[1] = method->GetAnnotationSetItem()->GetOffset();
    392         offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
    393       }
    394     }
    395     if (annotations_directory->GetParameterAnnotations() != nullptr) {
    396       for (std::unique_ptr<dex_ir::ParameterAnnotation>& parameter :
    397           *annotations_directory->GetParameterAnnotations()) {
    398         annotation_buffer[0] = parameter->GetMethodId()->GetIndex();
    399         annotation_buffer[1] = parameter->GetAnnotations()->GetOffset();
    400         offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
    401       }
    402     }
    403   }
    404 }
    405 
    406 void DexWriter::WriteDebugInfoItems() {
    407   for (auto& debug_info_pair : header_->GetCollections().DebugInfoItems()) {
    408     std::unique_ptr<dex_ir::DebugInfoItem>& debug_info = debug_info_pair.second;
    409     Write(debug_info->GetDebugInfo(), debug_info->GetDebugInfoSize(), debug_info->GetOffset());
    410   }
    411 }
    412 
    413 void DexWriter::WriteCodeItems() {
    414   uint16_t uint16_buffer[4];
    415   uint32_t uint32_buffer[2];
    416   for (auto& code_item_pair : header_->GetCollections().CodeItems()) {
    417     std::unique_ptr<dex_ir::CodeItem>& code_item = code_item_pair.second;
    418     uint16_buffer[0] = code_item->RegistersSize();
    419     uint16_buffer[1] = code_item->InsSize();
    420     uint16_buffer[2] = code_item->OutsSize();
    421     uint16_buffer[3] = code_item->TriesSize();
    422     uint32_buffer[0] = code_item->DebugInfo() == nullptr ? 0 : code_item->DebugInfo()->GetOffset();
    423     uint32_buffer[1] = code_item->InsnsSize();
    424     size_t offset = code_item->GetOffset();
    425     offset += Write(uint16_buffer, 4 * sizeof(uint16_t), offset);
    426     offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset);
    427     offset += Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t), offset);
    428     if (code_item->TriesSize() != 0) {
    429       if (code_item->InsnsSize() % 2 != 0) {
    430         uint16_t padding[1] = { 0 };
    431         offset += Write(padding, sizeof(uint16_t), offset);
    432       }
    433       uint32_t start_addr[1];
    434       uint16_t insn_count_and_handler_off[2];
    435       for (std::unique_ptr<const dex_ir::TryItem>& try_item : *code_item->Tries()) {
    436         start_addr[0] = try_item->StartAddr();
    437         insn_count_and_handler_off[0] = try_item->InsnCount();
    438         insn_count_and_handler_off[1] = try_item->GetHandlers()->GetListOffset();
    439         offset += Write(start_addr, sizeof(uint32_t), offset);
    440         offset += Write(insn_count_and_handler_off, 2 * sizeof(uint16_t), offset);
    441       }
    442       // Leave offset pointing to the end of the try items.
    443       WriteUleb128(code_item->Handlers()->size(), offset);
    444       for (std::unique_ptr<const dex_ir::CatchHandler>& handlers : *code_item->Handlers()) {
    445         size_t list_offset = offset + handlers->GetListOffset();
    446         uint32_t size = handlers->HasCatchAll() ? (handlers->GetHandlers()->size() - 1) * -1 :
    447             handlers->GetHandlers()->size();
    448         list_offset += WriteSleb128(size, list_offset);
    449         for (std::unique_ptr<const dex_ir::TypeAddrPair>& handler : *handlers->GetHandlers()) {
    450           if (handler->GetTypeId() != nullptr) {
    451             list_offset += WriteUleb128(handler->GetTypeId()->GetIndex(), list_offset);
    452           }
    453           list_offset += WriteUleb128(handler->GetAddress(), list_offset);
    454         }
    455       }
    456     }
    457   }
    458 }
    459 
    460 void DexWriter::WriteClasses() {
    461   uint32_t class_def_buffer[8];
    462   for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) {
    463     class_def_buffer[0] = class_def->ClassType()->GetIndex();
    464     class_def_buffer[1] = class_def->GetAccessFlags();
    465     class_def_buffer[2] = class_def->Superclass() == nullptr ? DexFile::kDexNoIndex :
    466         class_def->Superclass()->GetIndex();
    467     class_def_buffer[3] = class_def->InterfacesOffset();
    468     class_def_buffer[4] = class_def->SourceFile() == nullptr ? DexFile::kDexNoIndex :
    469         class_def->SourceFile()->GetIndex();
    470     class_def_buffer[5] = class_def->Annotations() == nullptr ? 0 :
    471         class_def->Annotations()->GetOffset();
    472     class_def_buffer[6] = class_def->GetClassData() == nullptr ? 0 :
    473         class_def->GetClassData()->GetOffset();
    474     class_def_buffer[7] = class_def->StaticValues() == nullptr ? 0 :
    475         class_def->StaticValues()->GetOffset();
    476     size_t offset = class_def->GetOffset();
    477     Write(class_def_buffer, class_def->GetSize(), offset);
    478   }
    479 
    480   for (auto& class_data_pair : header_->GetCollections().ClassDatas()) {
    481     std::unique_ptr<dex_ir::ClassData>& class_data = class_data_pair.second;
    482     size_t offset = class_data->GetOffset();
    483     offset += WriteUleb128(class_data->StaticFields()->size(), offset);
    484     offset += WriteUleb128(class_data->InstanceFields()->size(), offset);
    485     offset += WriteUleb128(class_data->DirectMethods()->size(), offset);
    486     offset += WriteUleb128(class_data->VirtualMethods()->size(), offset);
    487     offset += WriteEncodedFields(class_data->StaticFields(), offset);
    488     offset += WriteEncodedFields(class_data->InstanceFields(), offset);
    489     offset += WriteEncodedMethods(class_data->DirectMethods(), offset);
    490     offset += WriteEncodedMethods(class_data->VirtualMethods(), offset);
    491   }
    492 }
    493 
    494 void DexWriter::WriteCallSites() {
    495   uint32_t call_site_off[1];
    496   for (std::unique_ptr<dex_ir::CallSiteId>& call_site_id :
    497       header_->GetCollections().CallSiteIds()) {
    498     call_site_off[0] = call_site_id->CallSiteItem()->GetOffset();
    499     Write(call_site_off, call_site_id->GetSize(), call_site_id->GetOffset());
    500   }
    501 }
    502 
    503 void DexWriter::WriteMethodHandles() {
    504   uint16_t method_handle_buff[4];
    505   for (std::unique_ptr<dex_ir::MethodHandleItem>& method_handle :
    506       header_->GetCollections().MethodHandleItems()) {
    507     method_handle_buff[0] = static_cast<uint16_t>(method_handle->GetMethodHandleType());
    508     method_handle_buff[1] = 0;  // unused.
    509     method_handle_buff[2] = method_handle->GetFieldOrMethodId()->GetIndex();
    510     method_handle_buff[3] = 0;  // unused.
    511     Write(method_handle_buff, method_handle->GetSize(), method_handle->GetOffset());
    512   }
    513 }
    514 
    515 struct MapItemContainer {
    516   MapItemContainer(uint32_t type, uint32_t size, uint32_t offset)
    517       : type_(type), size_(size), offset_(offset) { }
    518 
    519   bool operator<(const MapItemContainer& other) const {
    520     return offset_ > other.offset_;
    521   }
    522 
    523   uint32_t type_;
    524   uint32_t size_;
    525   uint32_t offset_;
    526 };
    527 
    528 void DexWriter::WriteMapItem() {
    529   dex_ir::Collections& collection = header_->GetCollections();
    530   std::priority_queue<MapItemContainer> queue;
    531 
    532   // Header and index section.
    533   queue.push(MapItemContainer(DexFile::kDexTypeHeaderItem, 1, 0));
    534   if (collection.StringIdsSize() != 0) {
    535     queue.push(MapItemContainer(DexFile::kDexTypeStringIdItem, collection.StringIdsSize(),
    536         collection.StringIdsOffset()));
    537   }
    538   if (collection.TypeIdsSize() != 0) {
    539     queue.push(MapItemContainer(DexFile::kDexTypeTypeIdItem, collection.TypeIdsSize(),
    540         collection.TypeIdsOffset()));
    541   }
    542   if (collection.ProtoIdsSize() != 0) {
    543     queue.push(MapItemContainer(DexFile::kDexTypeProtoIdItem, collection.ProtoIdsSize(),
    544         collection.ProtoIdsOffset()));
    545   }
    546   if (collection.FieldIdsSize() != 0) {
    547     queue.push(MapItemContainer(DexFile::kDexTypeFieldIdItem, collection.FieldIdsSize(),
    548         collection.FieldIdsOffset()));
    549   }
    550   if (collection.MethodIdsSize() != 0) {
    551     queue.push(MapItemContainer(DexFile::kDexTypeMethodIdItem, collection.MethodIdsSize(),
    552         collection.MethodIdsOffset()));
    553   }
    554   if (collection.ClassDefsSize() != 0) {
    555     queue.push(MapItemContainer(DexFile::kDexTypeClassDefItem, collection.ClassDefsSize(),
    556         collection.ClassDefsOffset()));
    557   }
    558   if (collection.CallSiteIdsSize() != 0) {
    559     queue.push(MapItemContainer(DexFile::kDexTypeCallSiteIdItem, collection.CallSiteIdsSize(),
    560         collection.CallSiteIdsOffset()));
    561   }
    562   if (collection.MethodHandleItemsSize() != 0) {
    563     queue.push(MapItemContainer(DexFile::kDexTypeMethodHandleItem,
    564         collection.MethodHandleItemsSize(), collection.MethodHandleItemsOffset()));
    565   }
    566 
    567   // Data section.
    568   queue.push(MapItemContainer(DexFile::kDexTypeMapList, 1, collection.MapListOffset()));
    569   if (collection.TypeListsSize() != 0) {
    570     queue.push(MapItemContainer(DexFile::kDexTypeTypeList, collection.TypeListsSize(),
    571         collection.TypeListsOffset()));
    572   }
    573   if (collection.AnnotationSetRefListsSize() != 0) {
    574     queue.push(MapItemContainer(DexFile::kDexTypeAnnotationSetRefList,
    575         collection.AnnotationSetRefListsSize(), collection.AnnotationSetRefListsOffset()));
    576   }
    577   if (collection.AnnotationSetItemsSize() != 0) {
    578     queue.push(MapItemContainer(DexFile::kDexTypeAnnotationSetItem,
    579         collection.AnnotationSetItemsSize(), collection.AnnotationSetItemsOffset()));
    580   }
    581   if (collection.ClassDatasSize() != 0) {
    582     queue.push(MapItemContainer(DexFile::kDexTypeClassDataItem, collection.ClassDatasSize(),
    583         collection.ClassDatasOffset()));
    584   }
    585   if (collection.CodeItemsSize() != 0) {
    586     queue.push(MapItemContainer(DexFile::kDexTypeCodeItem, collection.CodeItemsSize(),
    587         collection.CodeItemsOffset()));
    588   }
    589   if (collection.StringDatasSize() != 0) {
    590     queue.push(MapItemContainer(DexFile::kDexTypeStringDataItem, collection.StringDatasSize(),
    591         collection.StringDatasOffset()));
    592   }
    593   if (collection.DebugInfoItemsSize() != 0) {
    594     queue.push(MapItemContainer(DexFile::kDexTypeDebugInfoItem, collection.DebugInfoItemsSize(),
    595         collection.DebugInfoItemsOffset()));
    596   }
    597   if (collection.AnnotationItemsSize() != 0) {
    598     queue.push(MapItemContainer(DexFile::kDexTypeAnnotationItem, collection.AnnotationItemsSize(),
    599         collection.AnnotationItemsOffset()));
    600   }
    601   if (collection.EncodedArrayItemsSize() != 0) {
    602     queue.push(MapItemContainer(DexFile::kDexTypeEncodedArrayItem,
    603         collection.EncodedArrayItemsSize(), collection.EncodedArrayItemsOffset()));
    604   }
    605   if (collection.AnnotationsDirectoryItemsSize() != 0) {
    606     queue.push(MapItemContainer(DexFile::kDexTypeAnnotationsDirectoryItem,
    607         collection.AnnotationsDirectoryItemsSize(), collection.AnnotationsDirectoryItemsOffset()));
    608   }
    609 
    610   uint32_t offset = collection.MapListOffset();
    611   uint16_t uint16_buffer[2];
    612   uint32_t uint32_buffer[2];
    613   uint16_buffer[1] = 0;
    614   uint32_buffer[0] = queue.size();
    615   offset += Write(uint32_buffer, sizeof(uint32_t), offset);
    616   while (!queue.empty()) {
    617     const MapItemContainer& map_item = queue.top();
    618     uint16_buffer[0] = map_item.type_;
    619     uint32_buffer[0] = map_item.size_;
    620     uint32_buffer[1] = map_item.offset_;
    621     offset += Write(uint16_buffer, 2 * sizeof(uint16_t), offset);
    622     offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset);
    623     queue.pop();
    624   }
    625 }
    626 
    627 void DexWriter::WriteHeader() {
    628   uint32_t buffer[20];
    629   dex_ir::Collections& collections = header_->GetCollections();
    630   size_t offset = 0;
    631   offset += Write(header_->Magic(), 8 * sizeof(uint8_t), offset);
    632   buffer[0] = header_->Checksum();
    633   offset += Write(buffer, sizeof(uint32_t), offset);
    634   offset += Write(header_->Signature(), 20 * sizeof(uint8_t), offset);
    635   uint32_t file_size = header_->FileSize();
    636   buffer[0] = file_size;
    637   buffer[1] = header_->GetSize();
    638   buffer[2] = header_->EndianTag();
    639   buffer[3] = header_->LinkSize();
    640   buffer[4] = header_->LinkOffset();
    641   buffer[5] = collections.MapListOffset();
    642   buffer[6] = collections.StringIdsSize();
    643   buffer[7] = collections.StringIdsOffset();
    644   buffer[8] = collections.TypeIdsSize();
    645   buffer[9] = collections.TypeIdsOffset();
    646   buffer[10] = collections.ProtoIdsSize();
    647   buffer[11] = collections.ProtoIdsOffset();
    648   buffer[12] = collections.FieldIdsSize();
    649   buffer[13] = collections.FieldIdsOffset();
    650   buffer[14] = collections.MethodIdsSize();
    651   buffer[15] = collections.MethodIdsOffset();
    652   uint32_t class_defs_size = collections.ClassDefsSize();
    653   uint32_t class_defs_off = collections.ClassDefsOffset();
    654   buffer[16] = class_defs_size;
    655   buffer[17] = class_defs_off;
    656   buffer[18] = header_->DataSize();
    657   buffer[19] = header_->DataOffset();
    658   Write(buffer, 20 * sizeof(uint32_t), offset);
    659 }
    660 
    661 void DexWriter::WriteMemMap() {
    662   WriteStrings();
    663   WriteTypes();
    664   WriteTypeLists();
    665   WriteProtos();
    666   WriteFields();
    667   WriteMethods();
    668   WriteEncodedArrays();
    669   WriteAnnotations();
    670   WriteAnnotationSets();
    671   WriteAnnotationSetRefs();
    672   WriteAnnotationsDirectories();
    673   WriteDebugInfoItems();
    674   WriteCodeItems();
    675   WriteClasses();
    676   WriteCallSites();
    677   WriteMethodHandles();
    678   WriteMapItem();
    679   WriteHeader();
    680 }
    681 
    682 void DexWriter::Output(dex_ir::Header* header, MemMap* mem_map) {
    683   DexWriter dex_writer(header, mem_map);
    684   dex_writer.WriteMemMap();
    685 }
    686 
    687 }  // namespace art
    688