/*
 * Copyright (C) 2015 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.
 */

#ifndef ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_
#define ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_

#include "debug_frame_opcode_writer.h"
#include "dwarf.h"
#include "writer.h"

namespace art {
namespace dwarf {

// Writer for the .eh_frame section (which extends .debug_frame specification).
template<typename Allocator = std::allocator<uint8_t>>
class DebugFrameWriter FINAL : private Writer<Allocator> {
 public:
  void WriteCIE(Reg return_address_register,
                const uint8_t* initial_opcodes,
                int initial_opcodes_size) {
    DCHECK(cie_header_start_ == ~0u);
    cie_header_start_ = this->data()->size();
    if (use_64bit_address_) {
      // TODO: This is not related to being 64bit.
      this->PushUint32(0xffffffff);
      this->PushUint64(0);  // Length placeholder.
      this->PushUint64(0);  // CIE id.
    } else {
      this->PushUint32(0);  // Length placeholder.
      this->PushUint32(0);  // CIE id.
    }
    this->PushUint8(1);   // Version.
    this->PushString("zR");
    this->PushUleb128(DebugFrameOpCodeWriter<Allocator>::kCodeAlignmentFactor);
    this->PushSleb128(DebugFrameOpCodeWriter<Allocator>::kDataAlignmentFactor);
    this->PushUleb128(return_address_register.num());  // ubyte in DWARF2.
    this->PushUleb128(1);  // z: Augmentation data size.
    if (use_64bit_address_) {
      this->PushUint8(0x04);  // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata8).
    } else {
      this->PushUint8(0x03);  // R: ((DW_EH_PE_absptr << 4) | DW_EH_PE_udata4).
    }
    this->PushData(initial_opcodes, initial_opcodes_size);
    this->Pad(use_64bit_address_ ? 8 : 4);
    if (use_64bit_address_) {
      this->UpdateUint64(cie_header_start_ + 4, this->data()->size() - cie_header_start_ - 12);
    } else {
      this->UpdateUint32(cie_header_start_, this->data()->size() - cie_header_start_ - 4);
    }
  }

  void WriteCIE(Reg return_address_register,
                const DebugFrameOpCodeWriter<Allocator>& opcodes) {
    WriteCIE(return_address_register, opcodes.data()->data(), opcodes.data()->size());
  }

  void WriteFDE(uint64_t initial_address,
                uint64_t address_range,
                const uint8_t* unwind_opcodes,
                int unwind_opcodes_size) {
    DCHECK(cie_header_start_ != ~0u);
    size_t fde_header_start = this->data()->size();
    if (use_64bit_address_) {
      // TODO: This is not related to being 64bit.
      this->PushUint32(0xffffffff);
      this->PushUint64(0);  // Length placeholder.
      this->PushUint64(this->data()->size() - cie_header_start_);  // 'CIE_pointer'
    } else {
      this->PushUint32(0);  // Length placeholder.
      this->PushUint32(static_cast<uint32_t>(this->data()->size() - cie_header_start_));  // 'CIE_pointer'
    }
    if (use_64bit_address_) {
      this->PushUint64(initial_address);
      this->PushUint64(address_range);
    } else {
      this->PushUint32(initial_address);
      this->PushUint32(address_range);
    }
    this->PushUleb128(0);  // Augmentation data size.
    this->PushData(unwind_opcodes, unwind_opcodes_size);
    this->Pad(use_64bit_address_ ? 8 : 4);
    if (use_64bit_address_) {
      this->UpdateUint64(fde_header_start + 4, this->data()->size() - fde_header_start - 12);
    } else {
      this->UpdateUint32(fde_header_start, this->data()->size() - fde_header_start - 4);
    }
  }

  DebugFrameWriter(std::vector<uint8_t, Allocator>* buffer, bool use_64bit_address)
      : Writer<Allocator>(buffer),
        use_64bit_address_(use_64bit_address),
        cie_header_start_(~0u) {
  }

 private:
  bool use_64bit_address_;
  size_t cie_header_start_;

  DISALLOW_COPY_AND_ASSIGN(DebugFrameWriter);
};

}  // namespace dwarf
}  // namespace art

#endif  // ART_COMPILER_DWARF_DEBUG_FRAME_WRITER_H_
