/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "dex_writer.h"

#include <stdint.h>

#include <vector>

#include "cdex/compact_dex_file.h"
#include "compact_dex_writer.h"
#include "dex_file_layout.h"
#include "dex_file_types.h"
#include "dexlayout.h"
#include "standard_dex_file.h"
#include "utf.h"

namespace art {

static constexpr uint32_t kDataSectionAlignment = sizeof(uint32_t) * 2;
static constexpr uint32_t kDexSectionWordAlignment = 4;

static constexpr uint32_t SectionAlignment(DexFile::MapItemType type) {
  switch (type) {
    case DexFile::kDexTypeClassDataItem:
    case DexFile::kDexTypeStringDataItem:
    case DexFile::kDexTypeDebugInfoItem:
    case DexFile::kDexTypeAnnotationItem:
    case DexFile::kDexTypeEncodedArrayItem:
      return alignof(uint8_t);

    default:
      // All other sections are kDexAlignedSection.
      return kDexSectionWordAlignment;
  }
}


size_t EncodeIntValue(int32_t value, uint8_t* buffer) {
  size_t length = 0;
  if (value >= 0) {
    while (value > 0x7f) {
      buffer[length++] = static_cast<uint8_t>(value);
      value >>= 8;
    }
  } else {
    while (value < -0x80) {
      buffer[length++] = static_cast<uint8_t>(value);
      value >>= 8;
    }
  }
  buffer[length++] = static_cast<uint8_t>(value);
  return length;
}

size_t EncodeUIntValue(uint32_t value, uint8_t* buffer) {
  size_t length = 0;
  do {
    buffer[length++] = static_cast<uint8_t>(value);
    value >>= 8;
  } while (value != 0);
  return length;
}

size_t EncodeLongValue(int64_t value, uint8_t* buffer) {
  size_t length = 0;
  if (value >= 0) {
    while (value > 0x7f) {
      buffer[length++] = static_cast<uint8_t>(value);
      value >>= 8;
    }
  } else {
    while (value < -0x80) {
      buffer[length++] = static_cast<uint8_t>(value);
      value >>= 8;
    }
  }
  buffer[length++] = static_cast<uint8_t>(value);
  return length;
}

union FloatUnion {
  float f_;
  uint32_t i_;
};

size_t EncodeFloatValue(float value, uint8_t* buffer) {
  FloatUnion float_union;
  float_union.f_ = value;
  uint32_t int_value = float_union.i_;
  size_t index = 3;
  do {
    buffer[index--] = int_value >> 24;
    int_value <<= 8;
  } while (int_value != 0);
  return 3 - index;
}

union DoubleUnion {
  double d_;
  uint64_t l_;
};

size_t EncodeDoubleValue(double value, uint8_t* buffer) {
  DoubleUnion double_union;
  double_union.d_ = value;
  uint64_t long_value = double_union.l_;
  size_t index = 7;
  do {
    buffer[index--] = long_value >> 56;
    long_value <<= 8;
  } while (long_value != 0);
  return 7 - index;
}

size_t DexWriter::Write(const void* buffer, size_t length, size_t offset) {
  DCHECK_LE(offset + length, mem_map_->Size());
  memcpy(mem_map_->Begin() + offset, buffer, length);
  return length;
}

size_t DexWriter::WriteSleb128(uint32_t value, size_t offset) {
  uint8_t buffer[8];
  EncodeSignedLeb128(buffer, value);
  return Write(buffer, SignedLeb128Size(value), offset);
}

size_t DexWriter::WriteUleb128(uint32_t value, size_t offset) {
  uint8_t buffer[8];
  EncodeUnsignedLeb128(buffer, value);
  return Write(buffer, UnsignedLeb128Size(value), offset);
}

size_t DexWriter::WriteEncodedValue(dex_ir::EncodedValue* encoded_value, size_t offset) {
  size_t original_offset = offset;
  size_t start = 0;
  size_t length;
  uint8_t buffer[8];
  int8_t type = encoded_value->Type();
  switch (type) {
    case DexFile::kDexAnnotationByte:
      length = EncodeIntValue(encoded_value->GetByte(), buffer);
      break;
    case DexFile::kDexAnnotationShort:
      length = EncodeIntValue(encoded_value->GetShort(), buffer);
      break;
    case DexFile::kDexAnnotationChar:
      length = EncodeUIntValue(encoded_value->GetChar(), buffer);
      break;
    case DexFile::kDexAnnotationInt:
      length = EncodeIntValue(encoded_value->GetInt(), buffer);
      break;
    case DexFile::kDexAnnotationLong:
      length = EncodeLongValue(encoded_value->GetLong(), buffer);
      break;
    case DexFile::kDexAnnotationFloat:
      length = EncodeFloatValue(encoded_value->GetFloat(), buffer);
      start = 4 - length;
      break;
    case DexFile::kDexAnnotationDouble:
      length = EncodeDoubleValue(encoded_value->GetDouble(), buffer);
      start = 8 - length;
      break;
    case DexFile::kDexAnnotationMethodType:
      length = EncodeUIntValue(encoded_value->GetProtoId()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationMethodHandle:
      length = EncodeUIntValue(encoded_value->GetMethodHandle()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationString:
      length = EncodeUIntValue(encoded_value->GetStringId()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationType:
      length = EncodeUIntValue(encoded_value->GetTypeId()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationField:
    case DexFile::kDexAnnotationEnum:
      length = EncodeUIntValue(encoded_value->GetFieldId()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationMethod:
      length = EncodeUIntValue(encoded_value->GetMethodId()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationArray:
      offset += WriteEncodedValueHeader(type, 0, offset);
      offset += WriteEncodedArray(encoded_value->GetEncodedArray()->GetEncodedValues(), offset);
      return offset - original_offset;
    case DexFile::kDexAnnotationAnnotation:
      offset += WriteEncodedValueHeader(type, 0, offset);
      offset += WriteEncodedAnnotation(encoded_value->GetEncodedAnnotation(), offset);
      return offset - original_offset;
    case DexFile::kDexAnnotationNull:
      return WriteEncodedValueHeader(type, 0, offset);
    case DexFile::kDexAnnotationBoolean:
      return WriteEncodedValueHeader(type, encoded_value->GetBoolean() ? 1 : 0, offset);
    default:
      return 0;
  }
  offset += WriteEncodedValueHeader(type, length - 1, offset);
  offset += Write(buffer + start, length, offset);
  return offset - original_offset;
}

size_t DexWriter::WriteEncodedValueHeader(int8_t value_type, size_t value_arg, size_t offset) {
  uint8_t buffer[1] = { static_cast<uint8_t>((value_arg << 5) | value_type) };
  return Write(buffer, sizeof(uint8_t), offset);
}

size_t DexWriter::WriteEncodedArray(dex_ir::EncodedValueVector* values, size_t offset) {
  size_t original_offset = offset;
  offset += WriteUleb128(values->size(), offset);
  for (std::unique_ptr<dex_ir::EncodedValue>& value : *values) {
    offset += WriteEncodedValue(value.get(), offset);
  }
  return offset - original_offset;
}

size_t DexWriter::WriteEncodedAnnotation(dex_ir::EncodedAnnotation* annotation, size_t offset) {
  size_t original_offset = offset;
  offset += WriteUleb128(annotation->GetType()->GetIndex(), offset);
  offset += WriteUleb128(annotation->GetAnnotationElements()->size(), offset);
  for (std::unique_ptr<dex_ir::AnnotationElement>& annotation_element :
      *annotation->GetAnnotationElements()) {
    offset += WriteUleb128(annotation_element->GetName()->GetIndex(), offset);
    offset += WriteEncodedValue(annotation_element->GetValue(), offset);
  }
  return offset - original_offset;
}

size_t DexWriter::WriteEncodedFields(dex_ir::FieldItemVector* fields, size_t offset) {
  size_t original_offset = offset;
  uint32_t prev_index = 0;
  for (std::unique_ptr<dex_ir::FieldItem>& field : *fields) {
    uint32_t index = field->GetFieldId()->GetIndex();
    offset += WriteUleb128(index - prev_index, offset);
    offset += WriteUleb128(field->GetAccessFlags(), offset);
    prev_index = index;
  }
  return offset - original_offset;
}

size_t DexWriter::WriteEncodedMethods(dex_ir::MethodItemVector* methods, size_t offset) {
  size_t original_offset = offset;
  uint32_t prev_index = 0;
  for (std::unique_ptr<dex_ir::MethodItem>& method : *methods) {
    uint32_t index = method->GetMethodId()->GetIndex();
    uint32_t code_off = method->GetCodeItem() == nullptr ? 0 : method->GetCodeItem()->GetOffset();
    offset += WriteUleb128(index - prev_index, offset);
    offset += WriteUleb128(method->GetAccessFlags(), offset);
    offset += WriteUleb128(code_off, offset);
    prev_index = index;
  }
  return offset - original_offset;
}

// TODO: Refactor this to remove duplicated boiler plate. One way to do this is adding
// function that takes a CollectionVector<T> and uses overloading.
uint32_t DexWriter::WriteStringIds(uint32_t offset, bool reserve_only) {
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::StringId>& string_id : header_->GetCollections().StringIds()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeStringIdItem));
    if (reserve_only) {
      offset += string_id->GetSize();
    } else {
      uint32_t string_data_off = string_id->DataItem()->GetOffset();
      offset += Write(&string_data_off, string_id->GetSize(), offset);
    }
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetStringIdsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteStringDatas(uint32_t offset) {
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::StringData>& string_data : header_->GetCollections().StringDatas()) {
    ProcessOffset(&offset, string_data.get());
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeStringDataItem));
    offset += WriteUleb128(CountModifiedUtf8Chars(string_data->Data()), offset);
    // Skip null terminator (already zeroed out, no need to write).
    offset += Write(string_data->Data(), strlen(string_data->Data()), offset) + 1u;
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetStringDatasOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteTypeIds(uint32_t offset) {
  uint32_t descriptor_idx[1];
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::TypeId>& type_id : header_->GetCollections().TypeIds()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeTypeIdItem));
    ProcessOffset(&offset, type_id.get());
    descriptor_idx[0] = type_id->GetStringId()->GetIndex();
    offset += Write(descriptor_idx, type_id->GetSize(), offset);
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetTypeIdsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteTypeLists(uint32_t offset) {
  uint32_t size[1];
  uint16_t list[1];
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::TypeList>& type_list : header_->GetCollections().TypeLists()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeTypeList));
    size[0] = type_list->GetTypeList()->size();
    ProcessOffset(&offset, type_list.get());
    offset += Write(size, sizeof(uint32_t), offset);
    for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) {
      list[0] = type_id->GetIndex();
      offset += Write(list, sizeof(uint16_t), offset);
    }
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetTypeListsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteProtoIds(uint32_t offset, bool reserve_only) {
  uint32_t buffer[3];
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::ProtoId>& proto_id : header_->GetCollections().ProtoIds()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeProtoIdItem));
    ProcessOffset(&offset, proto_id.get());
    if (reserve_only) {
      offset += proto_id->GetSize();
    } else {
      buffer[0] = proto_id->Shorty()->GetIndex();
      buffer[1] = proto_id->ReturnType()->GetIndex();
      buffer[2] = proto_id->Parameters() == nullptr ? 0 : proto_id->Parameters()->GetOffset();
      offset += Write(buffer, proto_id->GetSize(), offset);
    }
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetProtoIdsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteFieldIds(uint32_t offset) {
  uint16_t buffer[4];
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::FieldId>& field_id : header_->GetCollections().FieldIds()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeFieldIdItem));
    ProcessOffset(&offset, field_id.get());
    buffer[0] = field_id->Class()->GetIndex();
    buffer[1] = field_id->Type()->GetIndex();
    buffer[2] = field_id->Name()->GetIndex();
    buffer[3] = field_id->Name()->GetIndex() >> 16;
    offset += Write(buffer, field_id->GetSize(), offset);
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetFieldIdsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteMethodIds(uint32_t offset) {
  uint16_t buffer[4];
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::MethodId>& method_id : header_->GetCollections().MethodIds()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeMethodIdItem));
    ProcessOffset(&offset, method_id.get());
    buffer[0] = method_id->Class()->GetIndex();
    buffer[1] = method_id->Proto()->GetIndex();
    buffer[2] = method_id->Name()->GetIndex();
    buffer[3] = method_id->Name()->GetIndex() >> 16;
    offset += Write(buffer, method_id->GetSize(), offset);
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetMethodIdsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteEncodedArrays(uint32_t offset) {
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::EncodedArrayItem>& encoded_array :
      header_->GetCollections().EncodedArrayItems()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeEncodedArrayItem));
    ProcessOffset(&offset, encoded_array.get());
    offset += WriteEncodedArray(encoded_array->GetEncodedValues(), offset);
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetEncodedArrayItemsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteAnnotations(uint32_t offset) {
  uint8_t visibility[1];
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::AnnotationItem>& annotation :
      header_->GetCollections().AnnotationItems()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeAnnotationItem));
    visibility[0] = annotation->GetVisibility();
    ProcessOffset(&offset, annotation.get());
    offset += Write(visibility, sizeof(uint8_t), offset);
    offset += WriteEncodedAnnotation(annotation->GetAnnotation(), offset);
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetAnnotationItemsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteAnnotationSets(uint32_t offset) {
  uint32_t size[1];
  uint32_t annotation_off[1];
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::AnnotationSetItem>& annotation_set :
      header_->GetCollections().AnnotationSetItems()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeAnnotationSetItem));
    size[0] = annotation_set->GetItems()->size();
    ProcessOffset(&offset, annotation_set.get());
    offset += Write(size, sizeof(uint32_t), offset);
    for (dex_ir::AnnotationItem* annotation : *annotation_set->GetItems()) {
      annotation_off[0] = annotation->GetOffset();
      offset += Write(annotation_off, sizeof(uint32_t), offset);
    }
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetAnnotationSetItemsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteAnnotationSetRefs(uint32_t offset) {
  uint32_t size[1];
  uint32_t annotations_off[1];
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::AnnotationSetRefList>& annotation_set_ref :
      header_->GetCollections().AnnotationSetRefLists()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeAnnotationSetRefList));
    size[0] = annotation_set_ref->GetItems()->size();
    ProcessOffset(&offset, annotation_set_ref.get());
    offset += Write(size, sizeof(uint32_t), offset);
    for (dex_ir::AnnotationSetItem* annotation_set : *annotation_set_ref->GetItems()) {
      annotations_off[0] = annotation_set == nullptr ? 0 : annotation_set->GetOffset();
      offset += Write(annotations_off, sizeof(uint32_t), offset);
    }
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetAnnotationSetRefListsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteAnnotationsDirectories(uint32_t offset) {
  uint32_t directory_buffer[4];
  uint32_t annotation_buffer[2];
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::AnnotationsDirectoryItem>& annotations_directory :
      header_->GetCollections().AnnotationsDirectoryItems()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeAnnotationsDirectoryItem));
    ProcessOffset(&offset, annotations_directory.get());
    directory_buffer[0] = annotations_directory->GetClassAnnotation() == nullptr ? 0 :
        annotations_directory->GetClassAnnotation()->GetOffset();
    directory_buffer[1] = annotations_directory->GetFieldAnnotations() == nullptr ? 0 :
        annotations_directory->GetFieldAnnotations()->size();
    directory_buffer[2] = annotations_directory->GetMethodAnnotations() == nullptr ? 0 :
        annotations_directory->GetMethodAnnotations()->size();
    directory_buffer[3] = annotations_directory->GetParameterAnnotations() == nullptr ? 0 :
        annotations_directory->GetParameterAnnotations()->size();
    offset += Write(directory_buffer, 4 * sizeof(uint32_t), offset);
    if (annotations_directory->GetFieldAnnotations() != nullptr) {
      for (std::unique_ptr<dex_ir::FieldAnnotation>& field :
          *annotations_directory->GetFieldAnnotations()) {
        annotation_buffer[0] = field->GetFieldId()->GetIndex();
        annotation_buffer[1] = field->GetAnnotationSetItem()->GetOffset();
        offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
      }
    }
    if (annotations_directory->GetMethodAnnotations() != nullptr) {
      for (std::unique_ptr<dex_ir::MethodAnnotation>& method :
          *annotations_directory->GetMethodAnnotations()) {
        annotation_buffer[0] = method->GetMethodId()->GetIndex();
        annotation_buffer[1] = method->GetAnnotationSetItem()->GetOffset();
        offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
      }
    }
    if (annotations_directory->GetParameterAnnotations() != nullptr) {
      for (std::unique_ptr<dex_ir::ParameterAnnotation>& parameter :
          *annotations_directory->GetParameterAnnotations()) {
        annotation_buffer[0] = parameter->GetMethodId()->GetIndex();
        annotation_buffer[1] = parameter->GetAnnotations()->GetOffset();
        offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset);
      }
    }
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetAnnotationsDirectoryItemsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteDebugInfoItems(uint32_t offset) {
  const uint32_t start = offset;
  for (std::unique_ptr<dex_ir::DebugInfoItem>& debug_info :
      header_->GetCollections().DebugInfoItems()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeDebugInfoItem));
    ProcessOffset(&offset, debug_info.get());
    offset += Write(debug_info->GetDebugInfo(), debug_info->GetDebugInfoSize(), offset);
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetDebugInfoItemsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteCodeItems(uint32_t offset, bool reserve_only) {
  DexLayoutSection* code_section = nullptr;
  if (!reserve_only && dex_layout_ != nullptr) {
    code_section = &dex_layout_->GetSections().sections_[static_cast<size_t>(
        DexLayoutSections::SectionType::kSectionTypeCode)];
  }
  uint16_t uint16_buffer[4] = {};
  uint32_t uint32_buffer[2] = {};
  uint32_t start = offset;
  for (auto& code_item : header_->GetCollections().CodeItems()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeCodeItem));
    ProcessOffset(&offset, code_item.get());
    if (!reserve_only) {
      uint16_buffer[0] = code_item->RegistersSize();
      uint16_buffer[1] = code_item->InsSize();
      uint16_buffer[2] = code_item->OutsSize();
      uint16_buffer[3] = code_item->TriesSize();
      uint32_buffer[0] = code_item->DebugInfo() == nullptr ? 0 :
          code_item->DebugInfo()->GetOffset();
      uint32_buffer[1] = code_item->InsnsSize();
      // Only add the section hotness info once.
      if (code_section != nullptr) {
        auto it = dex_layout_->LayoutHotnessInfo().code_item_layout_.find(code_item.get());
        if (it != dex_layout_->LayoutHotnessInfo().code_item_layout_.end()) {
          code_section->parts_[static_cast<size_t>(it->second)].CombineSection(
              code_item->GetOffset(), code_item->GetOffset() + code_item->GetSize());
        }
      }
    }
    offset += Write(uint16_buffer, 4 * sizeof(uint16_t), offset);
    offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset);
    offset += Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t), offset);
    if (code_item->TriesSize() != 0) {
      if (code_item->InsnsSize() % 2 != 0) {
        uint16_t padding[1] = { 0 };
        offset += Write(padding, sizeof(uint16_t), offset);
      }
      uint32_t start_addr[1];
      uint16_t insn_count_and_handler_off[2];
      for (std::unique_ptr<const dex_ir::TryItem>& try_item : *code_item->Tries()) {
        start_addr[0] = try_item->StartAddr();
        insn_count_and_handler_off[0] = try_item->InsnCount();
        insn_count_and_handler_off[1] = try_item->GetHandlers()->GetListOffset();
        offset += Write(start_addr, sizeof(uint32_t), offset);
        offset += Write(insn_count_and_handler_off, 2 * sizeof(uint16_t), offset);
      }
      // Leave offset pointing to the end of the try items.
      UNUSED(WriteUleb128(code_item->Handlers()->size(), offset));
      for (std::unique_ptr<const dex_ir::CatchHandler>& handlers : *code_item->Handlers()) {
        size_t list_offset = offset + handlers->GetListOffset();
        uint32_t size = handlers->HasCatchAll() ? (handlers->GetHandlers()->size() - 1) * -1 :
            handlers->GetHandlers()->size();
        list_offset += WriteSleb128(size, list_offset);
        for (std::unique_ptr<const dex_ir::TypeAddrPair>& handler : *handlers->GetHandlers()) {
          if (handler->GetTypeId() != nullptr) {
            list_offset += WriteUleb128(handler->GetTypeId()->GetIndex(), list_offset);
          }
          list_offset += WriteUleb128(handler->GetAddress(), list_offset);
        }
      }
    }
    // TODO: Clean this up to properly calculate the size instead of assuming it doesn't change.
    offset = code_item->GetOffset() + code_item->GetSize();
  }

  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetCodeItemsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteClassDefs(uint32_t offset, bool reserve_only) {
  const uint32_t start = offset;
  uint32_t class_def_buffer[8];
  for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeClassDefItem));
    if (reserve_only) {
      offset += class_def->GetSize();
    } else {
      class_def_buffer[0] = class_def->ClassType()->GetIndex();
      class_def_buffer[1] = class_def->GetAccessFlags();
      class_def_buffer[2] = class_def->Superclass() == nullptr ? dex::kDexNoIndex :
          class_def->Superclass()->GetIndex();
      class_def_buffer[3] = class_def->InterfacesOffset();
      class_def_buffer[4] = class_def->SourceFile() == nullptr ? dex::kDexNoIndex :
          class_def->SourceFile()->GetIndex();
      class_def_buffer[5] = class_def->Annotations() == nullptr ? 0 :
          class_def->Annotations()->GetOffset();
      class_def_buffer[6] = class_def->GetClassData() == nullptr ? 0 :
          class_def->GetClassData()->GetOffset();
      class_def_buffer[7] = class_def->StaticValues() == nullptr ? 0 :
          class_def->StaticValues()->GetOffset();
      offset += Write(class_def_buffer, class_def->GetSize(), offset);
    }
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetClassDefsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteClassDatas(uint32_t offset) {
  const uint32_t start = offset;
  for (const std::unique_ptr<dex_ir::ClassData>& class_data :
      header_->GetCollections().ClassDatas()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeClassDataItem));
    ProcessOffset(&offset, class_data.get());
    offset += WriteUleb128(class_data->StaticFields()->size(), offset);
    offset += WriteUleb128(class_data->InstanceFields()->size(), offset);
    offset += WriteUleb128(class_data->DirectMethods()->size(), offset);
    offset += WriteUleb128(class_data->VirtualMethods()->size(), offset);
    offset += WriteEncodedFields(class_data->StaticFields(), offset);
    offset += WriteEncodedFields(class_data->InstanceFields(), offset);
    offset += WriteEncodedMethods(class_data->DirectMethods(), offset);
    offset += WriteEncodedMethods(class_data->VirtualMethods(), offset);
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetClassDatasOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteCallSiteIds(uint32_t offset, bool reserve_only) {
  const uint32_t start = offset;
  uint32_t call_site_off[1];
  for (std::unique_ptr<dex_ir::CallSiteId>& call_site_id :
      header_->GetCollections().CallSiteIds()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeCallSiteIdItem));
    if (reserve_only) {
      offset += call_site_id->GetSize();
    } else {
      call_site_off[0] = call_site_id->CallSiteItem()->GetOffset();
      offset += Write(call_site_off, call_site_id->GetSize(), offset);
    }
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetCallSiteIdsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteMethodHandles(uint32_t offset) {
  const uint32_t start = offset;
  uint16_t method_handle_buff[4];
  for (std::unique_ptr<dex_ir::MethodHandleItem>& method_handle :
      header_->GetCollections().MethodHandleItems()) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeMethodHandleItem));
    method_handle_buff[0] = static_cast<uint16_t>(method_handle->GetMethodHandleType());
    method_handle_buff[1] = 0;  // unused.
    method_handle_buff[2] = method_handle->GetFieldOrMethodId()->GetIndex();
    method_handle_buff[3] = 0;  // unused.
    offset += Write(method_handle_buff, method_handle->GetSize(), offset);
  }
  if (compute_offsets_ && start != offset) {
    header_->GetCollections().SetMethodHandleItemsOffset(start);
  }
  return offset - start;
}

uint32_t DexWriter::WriteMapItems(uint32_t offset, MapItemQueue* queue) {
  // All the sections should already have been added.
  uint16_t uint16_buffer[2];
  uint32_t uint32_buffer[2];
  uint16_buffer[1] = 0;
  uint32_buffer[0] = queue->size();
  const uint32_t start = offset;
  offset += Write(uint32_buffer, sizeof(uint32_t), offset);
  while (!queue->empty()) {
    const MapItem& map_item = queue->top();
    uint16_buffer[0] = map_item.type_;
    uint32_buffer[0] = map_item.size_;
    uint32_buffer[1] = map_item.offset_;
    offset += Write(uint16_buffer, 2 * sizeof(uint16_t), offset);
    offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset);
    queue->pop();
  }
  return offset - start;
}

uint32_t DexWriter::GenerateAndWriteMapItems(uint32_t offset) {
  dex_ir::Collections& collection = header_->GetCollections();
  MapItemQueue queue;

  // Header and index section.
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeHeaderItem, 1, 0));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringIdItem,
                              collection.StringIdsSize(),
                              collection.StringIdsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeIdItem,
                              collection.TypeIdsSize(),
                              collection.TypeIdsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeProtoIdItem,
                              collection.ProtoIdsSize(),
                              collection.ProtoIdsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeFieldIdItem,
                              collection.FieldIdsSize(),
                              collection.FieldIdsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodIdItem,
                              collection.MethodIdsSize(),
                              collection.MethodIdsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDefItem,
                              collection.ClassDefsSize(),
                              collection.ClassDefsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCallSiteIdItem,
                              collection.CallSiteIdsSize(),
                              collection.CallSiteIdsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodHandleItem,
                              collection.MethodHandleItemsSize(),
                              collection.MethodHandleItemsOffset()));
  // Data section.
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMapList, 1, collection.MapListOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeList,
                              collection.TypeListsSize(),
                              collection.TypeListsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetRefList,
                              collection.AnnotationSetRefListsSize(),
                              collection.AnnotationSetRefListsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetItem,
                              collection.AnnotationSetItemsSize(),
                              collection.AnnotationSetItemsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDataItem,
                              collection.ClassDatasSize(),
                              collection.ClassDatasOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCodeItem,
                              collection.CodeItemsSize(),
                              collection.CodeItemsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringDataItem,
                              collection.StringDatasSize(),
                              collection.StringDatasOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeDebugInfoItem,
                              collection.DebugInfoItemsSize(),
                              collection.DebugInfoItemsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationItem,
                              collection.AnnotationItemsSize(),
                              collection.AnnotationItemsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeEncodedArrayItem,
                              collection.EncodedArrayItemsSize(),
                              collection.EncodedArrayItemsOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationsDirectoryItem,
                              collection.AnnotationsDirectoryItemsSize(),
                              collection.AnnotationsDirectoryItemsOffset()));

  // Write the map items.
  return WriteMapItems(offset, &queue);
}

void DexWriter::WriteHeader() {
  StandardDexFile::Header header;
  static constexpr size_t kMagicAndVersionLen =
      StandardDexFile::kDexMagicSize + StandardDexFile::kDexVersionLen;
  std::copy_n(header_->Magic(), kMagicAndVersionLen, header.magic_);
  header.checksum_ = header_->Checksum();
  std::copy_n(header_->Signature(), DexFile::kSha1DigestSize, header.signature_);
  header.file_size_ = header_->FileSize();
  header.header_size_ = header_->GetSize();
  header.endian_tag_ = header_->EndianTag();
  header.link_size_ = header_->LinkSize();
  header.link_off_ = header_->LinkOffset();
  const dex_ir::Collections& collections = header_->GetCollections();
  header.map_off_ = collections.MapListOffset();
  header.string_ids_size_ = collections.StringIdsSize();
  header.string_ids_off_ = collections.StringIdsOffset();
  header.type_ids_size_ = collections.TypeIdsSize();
  header.type_ids_off_ = collections.TypeIdsOffset();
  header.proto_ids_size_ = collections.ProtoIdsSize();
  header.proto_ids_off_ = collections.ProtoIdsOffset();
  header.field_ids_size_ = collections.FieldIdsSize();
  header.field_ids_off_ = collections.FieldIdsOffset();
  header.method_ids_size_ = collections.MethodIdsSize();
  header.method_ids_off_ = collections.MethodIdsOffset();
  header.class_defs_size_ = collections.ClassDefsSize();
  header.class_defs_off_ = collections.ClassDefsOffset();
  header.data_size_ = header_->DataSize();
  header.data_off_ = header_->DataOffset();

  static_assert(sizeof(header) == 0x70, "Size doesn't match dex spec");
  UNUSED(Write(reinterpret_cast<uint8_t*>(&header), sizeof(header), 0u));
}

void DexWriter::WriteMemMap() {
  // Starting offset is right after the header.
  uint32_t offset = sizeof(StandardDexFile::Header);

  dex_ir::Collections& collection = header_->GetCollections();

  // Based on: https://source.android.com/devices/tech/dalvik/dex-format
  // Since the offsets may not be calculated already, the writing must be done in the correct order.
  const uint32_t string_ids_offset = offset;
  offset += WriteStringIds(offset, /*reserve_only*/ true);
  offset += WriteTypeIds(offset);
  const uint32_t proto_ids_offset = offset;
  offset += WriteProtoIds(offset, /*reserve_only*/ true);
  offset += WriteFieldIds(offset);
  offset += WriteMethodIds(offset);
  const uint32_t class_defs_offset = offset;
  offset += WriteClassDefs(offset, /*reserve_only*/ true);
  const uint32_t call_site_ids_offset = offset;
  offset += WriteCallSiteIds(offset, /*reserve_only*/ true);
  offset += WriteMethodHandles(offset);

  uint32_t data_offset_ = 0u;
  if (compute_offsets_) {
    // Data section.
    offset = RoundUp(offset, kDataSectionAlignment);
    data_offset_ = offset;
  }

  // Write code item first to minimize the space required for encoded methods.
  // Reserve code item space since we need the debug offsets to actually write them.
  const uint32_t code_items_offset = offset;
  offset += WriteCodeItems(offset, /*reserve_only*/ true);
  // Write debug info section.
  offset += WriteDebugInfoItems(offset);
  // Actually write code items since debug info offsets are calculated now.
  WriteCodeItems(code_items_offset, /*reserve_only*/ false);

  offset += WriteEncodedArrays(offset);
  offset += WriteAnnotations(offset);
  offset += WriteAnnotationSets(offset);
  offset += WriteAnnotationSetRefs(offset);
  offset += WriteAnnotationsDirectories(offset);
  offset += WriteTypeLists(offset);
  offset += WriteClassDatas(offset);
  offset += WriteStringDatas(offset);

  // Write delayed id sections that depend on data sections.
  WriteStringIds(string_ids_offset, /*reserve_only*/ false);
  WriteProtoIds(proto_ids_offset, /*reserve_only*/ false);
  WriteClassDefs(class_defs_offset, /*reserve_only*/ false);
  WriteCallSiteIds(call_site_ids_offset, /*reserve_only*/ false);

  // Write the map list.
  if (compute_offsets_) {
    offset = RoundUp(offset, SectionAlignment(DexFile::kDexTypeMapList));
    collection.SetMapListOffset(offset);
  } else {
    offset = collection.MapListOffset();
  }
  offset += GenerateAndWriteMapItems(offset);
  offset = RoundUp(offset, kDataSectionAlignment);

  // Map items are included in the data section.
  if (compute_offsets_) {
    header_->SetDataSize(offset - data_offset_);
    if (header_->DataSize() != 0) {
      // Offset must be zero when the size is zero.
      header_->SetDataOffset(data_offset_);
    } else {
      header_->SetDataOffset(0u);
    }
  }

  // Write link data if it exists.
  const std::vector<uint8_t>& link_data = collection.LinkData();
  if (link_data.size() > 0) {
    CHECK_EQ(header_->LinkSize(), static_cast<uint32_t>(link_data.size()));
    if (compute_offsets_) {
      header_->SetLinkOffset(offset);
    }
    offset += Write(&link_data[0], link_data.size(), header_->LinkOffset());
  }

  // Write header last.
  if (compute_offsets_) {
    header_->SetFileSize(offset);
  }
  WriteHeader();
}

void DexWriter::Output(dex_ir::Header* header,
                       MemMap* mem_map,
                       DexLayout* dex_layout,
                       bool compute_offsets,
                       CompactDexLevel compact_dex_level) {
  CHECK(dex_layout != nullptr);
  std::unique_ptr<DexWriter> writer;
  if (compact_dex_level != CompactDexLevel::kCompactDexLevelNone) {
    writer.reset(new CompactDexWriter(header, mem_map, dex_layout, compact_dex_level));
  } else {
    writer.reset(new DexWriter(header, mem_map, dex_layout, compute_offsets));
  }
  writer->WriteMemMap();
}

void MapItemQueue::AddIfNotEmpty(const MapItem& item) {
  if (item.size_ != 0) {
    push(item);
  }
}

}  // namespace art
