//===-- DWARFCallFrameInfo.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Timer.h"
#include <list>
#include <cstring>

using namespace lldb;
using namespace lldb_private;

// GetDwarfEHPtr
//
// Used for calls when the value type is specified by a DWARF EH Frame pointer
// encoding.
static uint64_t
GetGNUEHPointer(const DataExtractor &DE, offset_t *offset_ptr,
                uint32_t eh_ptr_enc, addr_t pc_rel_addr, addr_t text_addr,
                addr_t data_addr) //, BSDRelocs *data_relocs) const
{
  if (eh_ptr_enc == DW_EH_PE_omit)
    return ULLONG_MAX; // Value isn't in the buffer...

  uint64_t baseAddress = 0;
  uint64_t addressValue = 0;
  const uint32_t addr_size = DE.GetAddressByteSize();
  assert(addr_size == 4 || addr_size == 8);

  bool signExtendValue = false;
  // Decode the base part or adjust our offset
  switch (eh_ptr_enc & 0x70) {
  case DW_EH_PE_pcrel:
    signExtendValue = true;
    baseAddress = *offset_ptr;
    if (pc_rel_addr != LLDB_INVALID_ADDRESS)
      baseAddress += pc_rel_addr;
    //      else
    //          Log::GlobalWarning ("PC relative pointer encoding found with
    //          invalid pc relative address.");
    break;

  case DW_EH_PE_textrel:
    signExtendValue = true;
    if (text_addr != LLDB_INVALID_ADDRESS)
      baseAddress = text_addr;
    //      else
    //          Log::GlobalWarning ("text relative pointer encoding being
    //          decoded with invalid text section address, setting base address
    //          to zero.");
    break;

  case DW_EH_PE_datarel:
    signExtendValue = true;
    if (data_addr != LLDB_INVALID_ADDRESS)
      baseAddress = data_addr;
    //      else
    //          Log::GlobalWarning ("data relative pointer encoding being
    //          decoded with invalid data section address, setting base address
    //          to zero.");
    break;

  case DW_EH_PE_funcrel:
    signExtendValue = true;
    break;

  case DW_EH_PE_aligned: {
    // SetPointerSize should be called prior to extracting these so the pointer
    // size is cached
    assert(addr_size != 0);
    if (addr_size) {
      // Align to a address size boundary first
      uint32_t alignOffset = *offset_ptr % addr_size;
      if (alignOffset)
        offset_ptr += addr_size - alignOffset;
    }
  } break;

  default:
    break;
  }

  // Decode the value part
  switch (eh_ptr_enc & DW_EH_PE_MASK_ENCODING) {
  case DW_EH_PE_absptr: {
    addressValue = DE.GetAddress(offset_ptr);
    //          if (data_relocs)
    //              addressValue = data_relocs->Relocate(*offset_ptr -
    //              addr_size, *this, addressValue);
  } break;
  case DW_EH_PE_uleb128:
    addressValue = DE.GetULEB128(offset_ptr);
    break;
  case DW_EH_PE_udata2:
    addressValue = DE.GetU16(offset_ptr);
    break;
  case DW_EH_PE_udata4:
    addressValue = DE.GetU32(offset_ptr);
    break;
  case DW_EH_PE_udata8:
    addressValue = DE.GetU64(offset_ptr);
    break;
  case DW_EH_PE_sleb128:
    addressValue = DE.GetSLEB128(offset_ptr);
    break;
  case DW_EH_PE_sdata2:
    addressValue = (int16_t)DE.GetU16(offset_ptr);
    break;
  case DW_EH_PE_sdata4:
    addressValue = (int32_t)DE.GetU32(offset_ptr);
    break;
  case DW_EH_PE_sdata8:
    addressValue = (int64_t)DE.GetU64(offset_ptr);
    break;
  default:
    // Unhandled encoding type
    assert(eh_ptr_enc);
    break;
  }

  // Since we promote everything to 64 bit, we may need to sign extend
  if (signExtendValue && addr_size < sizeof(baseAddress)) {
    uint64_t sign_bit = 1ull << ((addr_size * 8ull) - 1ull);
    if (sign_bit & addressValue) {
      uint64_t mask = ~sign_bit + 1;
      addressValue |= mask;
    }
  }
  return baseAddress + addressValue;
}

DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile &objfile,
                                       SectionSP &section_sp, Type type)
    : m_objfile(objfile), m_section_sp(section_sp), m_type(type) {}

bool DWARFCallFrameInfo::GetUnwindPlan(const Address &addr,
                                       UnwindPlan &unwind_plan) {
  return GetUnwindPlan(AddressRange(addr, 1), unwind_plan);
}

bool DWARFCallFrameInfo::GetUnwindPlan(const AddressRange &range,
                                       UnwindPlan &unwind_plan) {
  FDEEntryMap::Entry fde_entry;
  Address addr = range.GetBaseAddress();

  // Make sure that the Address we're searching for is the same object file as
  // this DWARFCallFrameInfo, we only store File offsets in m_fde_index.
  ModuleSP module_sp = addr.GetModule();
  if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr ||
      module_sp->GetObjectFile() != &m_objfile)
    return false;

  if (llvm::Optional<FDEEntryMap::Entry> entry = GetFirstFDEEntryInRange(range))
    return FDEToUnwindPlan(entry->data, addr, unwind_plan);
  return false;
}

bool DWARFCallFrameInfo::GetAddressRange(Address addr, AddressRange &range) {

  // Make sure that the Address we're searching for is the same object file as
  // this DWARFCallFrameInfo, we only store File offsets in m_fde_index.
  ModuleSP module_sp = addr.GetModule();
  if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr ||
      module_sp->GetObjectFile() != &m_objfile)
    return false;

  if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
    return false;
  GetFDEIndex();
  FDEEntryMap::Entry *fde_entry =
      m_fde_index.FindEntryThatContains(addr.GetFileAddress());
  if (!fde_entry)
    return false;

  range = AddressRange(fde_entry->base, fde_entry->size,
                       m_objfile.GetSectionList());
  return true;
}

llvm::Optional<DWARFCallFrameInfo::FDEEntryMap::Entry>
DWARFCallFrameInfo::GetFirstFDEEntryInRange(const AddressRange &range) {
  if (!m_section_sp || m_section_sp->IsEncrypted())
    return llvm::None;

  GetFDEIndex();

  addr_t start_file_addr = range.GetBaseAddress().GetFileAddress();
  const FDEEntryMap::Entry *fde =
      m_fde_index.FindEntryThatContainsOrFollows(start_file_addr);
  if (fde && fde->DoesIntersect(
                 FDEEntryMap::Range(start_file_addr, range.GetByteSize())))
    return *fde;

  return llvm::None;
}

void DWARFCallFrameInfo::GetFunctionAddressAndSizeVector(
    FunctionAddressAndSizeVector &function_info) {
  GetFDEIndex();
  const size_t count = m_fde_index.GetSize();
  function_info.Clear();
  if (count > 0)
    function_info.Reserve(count);
  for (size_t i = 0; i < count; ++i) {
    const FDEEntryMap::Entry *func_offset_data_entry =
        m_fde_index.GetEntryAtIndex(i);
    if (func_offset_data_entry) {
      FunctionAddressAndSizeVector::Entry function_offset_entry(
          func_offset_data_entry->base, func_offset_data_entry->size);
      function_info.Append(function_offset_entry);
    }
  }
}

const DWARFCallFrameInfo::CIE *
DWARFCallFrameInfo::GetCIE(dw_offset_t cie_offset) {
  cie_map_t::iterator pos = m_cie_map.find(cie_offset);

  if (pos != m_cie_map.end()) {
    // Parse and cache the CIE
    if (pos->second == nullptr)
      pos->second = ParseCIE(cie_offset);

    return pos->second.get();
  }
  return nullptr;
}

DWARFCallFrameInfo::CIESP
DWARFCallFrameInfo::ParseCIE(const dw_offset_t cie_offset) {
  CIESP cie_sp(new CIE(cie_offset));
  lldb::offset_t offset = cie_offset;
  if (!m_cfi_data_initialized)
    GetCFIData();
  uint32_t length = m_cfi_data.GetU32(&offset);
  dw_offset_t cie_id, end_offset;
  bool is_64bit = (length == UINT32_MAX);
  if (is_64bit) {
    length = m_cfi_data.GetU64(&offset);
    cie_id = m_cfi_data.GetU64(&offset);
    end_offset = cie_offset + length + 12;
  } else {
    cie_id = m_cfi_data.GetU32(&offset);
    end_offset = cie_offset + length + 4;
  }
  if (length > 0 && ((m_type == DWARF && cie_id == UINT32_MAX) ||
                     (m_type == EH && cie_id == 0ul))) {
    size_t i;
    //    cie.offset = cie_offset;
    //    cie.length = length;
    //    cie.cieID = cieID;
    cie_sp->ptr_encoding = DW_EH_PE_absptr; // default
    cie_sp->version = m_cfi_data.GetU8(&offset);
    if (cie_sp->version > CFI_VERSION4) {
      Host::SystemLog(Host::eSystemLogError,
                      "CIE parse error: CFI version %d is not supported\n",
                      cie_sp->version);
      return nullptr;
    }

    for (i = 0; i < CFI_AUG_MAX_SIZE; ++i) {
      cie_sp->augmentation[i] = m_cfi_data.GetU8(&offset);
      if (cie_sp->augmentation[i] == '\0') {
        // Zero out remaining bytes in augmentation string
        for (size_t j = i + 1; j < CFI_AUG_MAX_SIZE; ++j)
          cie_sp->augmentation[j] = '\0';

        break;
      }
    }

    if (i == CFI_AUG_MAX_SIZE &&
        cie_sp->augmentation[CFI_AUG_MAX_SIZE - 1] != '\0') {
      Host::SystemLog(Host::eSystemLogError,
                      "CIE parse error: CIE augmentation string was too large "
                      "for the fixed sized buffer of %d bytes.\n",
                      CFI_AUG_MAX_SIZE);
      return nullptr;
    }

    // m_cfi_data uses address size from target architecture of the process may
    // ignore these fields?
    if (m_type == DWARF && cie_sp->version >= CFI_VERSION4) {
      cie_sp->address_size = m_cfi_data.GetU8(&offset);
      cie_sp->segment_size = m_cfi_data.GetU8(&offset);
    }

    cie_sp->code_align = (uint32_t)m_cfi_data.GetULEB128(&offset);
    cie_sp->data_align = (int32_t)m_cfi_data.GetSLEB128(&offset);

    cie_sp->return_addr_reg_num =
        m_type == DWARF && cie_sp->version >= CFI_VERSION3
            ? static_cast<uint32_t>(m_cfi_data.GetULEB128(&offset))
            : m_cfi_data.GetU8(&offset);

    if (cie_sp->augmentation[0]) {
      // Get the length of the eh_frame augmentation data which starts with a
      // ULEB128 length in bytes
      const size_t aug_data_len = (size_t)m_cfi_data.GetULEB128(&offset);
      const size_t aug_data_end = offset + aug_data_len;
      const size_t aug_str_len = strlen(cie_sp->augmentation);
      // A 'z' may be present as the first character of the string.
      // If present, the Augmentation Data field shall be present. The contents
      // of the Augmentation Data shall be interpreted according to other
      // characters in the Augmentation String.
      if (cie_sp->augmentation[0] == 'z') {
        // Extract the Augmentation Data
        size_t aug_str_idx = 0;
        for (aug_str_idx = 1; aug_str_idx < aug_str_len; aug_str_idx++) {
          char aug = cie_sp->augmentation[aug_str_idx];
          switch (aug) {
          case 'L':
            // Indicates the presence of one argument in the Augmentation Data
            // of the CIE, and a corresponding argument in the Augmentation
            // Data of the FDE. The argument in the Augmentation Data of the
            // CIE is 1-byte and represents the pointer encoding used for the
            // argument in the Augmentation Data of the FDE, which is the
            // address of a language-specific data area (LSDA). The size of the
            // LSDA pointer is specified by the pointer encoding used.
            cie_sp->lsda_addr_encoding = m_cfi_data.GetU8(&offset);
            break;

          case 'P':
            // Indicates the presence of two arguments in the Augmentation Data
            // of the CIE. The first argument is 1-byte and represents the
            // pointer encoding used for the second argument, which is the
            // address of a personality routine handler. The size of the
            // personality routine pointer is specified by the pointer encoding
            // used.
            //
            // The address of the personality function will be stored at this
            // location.  Pre-execution, it will be all zero's so don't read it
            // until we're trying to do an unwind & the reloc has been
            // resolved.
            {
              uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset);
              const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
              cie_sp->personality_loc = GetGNUEHPointer(
                  m_cfi_data, &offset, arg_ptr_encoding, pc_rel_addr,
                  LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS);
            }
            break;

          case 'R':
            // A 'R' may be present at any position after the
            // first character of the string. The Augmentation Data shall
            // include a 1 byte argument that represents the pointer encoding
            // for the address pointers used in the FDE. Example: 0x1B ==
            // DW_EH_PE_pcrel | DW_EH_PE_sdata4
            cie_sp->ptr_encoding = m_cfi_data.GetU8(&offset);
            break;
          }
        }
      } else if (strcmp(cie_sp->augmentation, "eh") == 0) {
        // If the Augmentation string has the value "eh", then the EH Data
        // field shall be present
      }

      // Set the offset to be the end of the augmentation data just in case we
      // didn't understand any of the data.
      offset = (uint32_t)aug_data_end;
    }

    if (end_offset > offset) {
      cie_sp->inst_offset = offset;
      cie_sp->inst_length = end_offset - offset;
    }
    while (offset < end_offset) {
      uint8_t inst = m_cfi_data.GetU8(&offset);
      uint8_t primary_opcode = inst & 0xC0;
      uint8_t extended_opcode = inst & 0x3F;

      if (!HandleCommonDwarfOpcode(primary_opcode, extended_opcode,
                                   cie_sp->data_align, offset,
                                   cie_sp->initial_row))
        break; // Stop if we hit an unrecognized opcode
    }
  }

  return cie_sp;
}

void DWARFCallFrameInfo::GetCFIData() {
  if (!m_cfi_data_initialized) {
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
    if (log)
      m_objfile.GetModule()->LogMessage(log, "Reading EH frame info");
    m_objfile.ReadSectionData(m_section_sp.get(), m_cfi_data);
    m_cfi_data_initialized = true;
  }
}
// Scan through the eh_frame or debug_frame section looking for FDEs and noting
// the start/end addresses of the functions and a pointer back to the
// function's FDE for later expansion. Internalize CIEs as we come across them.

void DWARFCallFrameInfo::GetFDEIndex() {
  if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
    return;

  if (m_fde_index_initialized)
    return;

  std::lock_guard<std::mutex> guard(m_fde_index_mutex);

  if (m_fde_index_initialized) // if two threads hit the locker
    return;

  LLDB_SCOPED_TIMERF("%s - %s", LLVM_PRETTY_FUNCTION,
                     m_objfile.GetFileSpec().GetFilename().AsCString(""));

  bool clear_address_zeroth_bit = false;
  if (ArchSpec arch = m_objfile.GetArchitecture()) {
    if (arch.GetTriple().getArch() == llvm::Triple::arm ||
        arch.GetTriple().getArch() == llvm::Triple::thumb)
      clear_address_zeroth_bit = true;
  }

  lldb::offset_t offset = 0;
  if (!m_cfi_data_initialized)
    GetCFIData();
  while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8)) {
    const dw_offset_t current_entry = offset;
    dw_offset_t cie_id, next_entry, cie_offset;
    uint32_t len = m_cfi_data.GetU32(&offset);
    bool is_64bit = (len == UINT32_MAX);
    if (is_64bit) {
      len = m_cfi_data.GetU64(&offset);
      cie_id = m_cfi_data.GetU64(&offset);
      next_entry = current_entry + len + 12;
      cie_offset = current_entry + 12 - cie_id;
    } else {
      cie_id = m_cfi_data.GetU32(&offset);
      next_entry = current_entry + len + 4;
      cie_offset = current_entry + 4 - cie_id;
    }

    if (next_entry > m_cfi_data.GetByteSize() + 1) {
      Host::SystemLog(Host::eSystemLogError, "error: Invalid fde/cie next "
                                             "entry offset of 0x%x found in "
                                             "cie/fde at 0x%x\n",
                      next_entry, current_entry);
      // Don't trust anything in this eh_frame section if we find blatantly
      // invalid data.
      m_fde_index.Clear();
      m_fde_index_initialized = true;
      return;
    }

    // An FDE entry contains CIE_pointer in debug_frame in same place as cie_id
    // in eh_frame. CIE_pointer is an offset into the .debug_frame section. So,
    // variable cie_offset should be equal to cie_id for debug_frame.
    // FDE entries with cie_id == 0 shouldn't be ignored for it.
    if ((cie_id == 0 && m_type == EH) || cie_id == UINT32_MAX || len == 0) {
      auto cie_sp = ParseCIE(current_entry);
      if (!cie_sp) {
        // Cannot parse, the reason is already logged
        m_fde_index.Clear();
        m_fde_index_initialized = true;
        return;
      }

      m_cie_map[current_entry] = std::move(cie_sp);
      offset = next_entry;
      continue;
    }

    if (m_type == DWARF)
      cie_offset = cie_id;

    if (cie_offset > m_cfi_data.GetByteSize()) {
      Host::SystemLog(Host::eSystemLogError,
                      "error: Invalid cie offset of 0x%x "
                      "found in cie/fde at 0x%x\n",
                      cie_offset, current_entry);
      // Don't trust anything in this eh_frame section if we find blatantly
      // invalid data.
      m_fde_index.Clear();
      m_fde_index_initialized = true;
      return;
    }

    const CIE *cie = GetCIE(cie_offset);
    if (cie) {
      const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
      const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
      const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;

      lldb::addr_t addr =
          GetGNUEHPointer(m_cfi_data, &offset, cie->ptr_encoding, pc_rel_addr,
                          text_addr, data_addr);
      if (clear_address_zeroth_bit)
        addr &= ~1ull;

      lldb::addr_t length = GetGNUEHPointer(
          m_cfi_data, &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING,
          pc_rel_addr, text_addr, data_addr);
      FDEEntryMap::Entry fde(addr, length, current_entry);
      m_fde_index.Append(fde);
    } else {
      Host::SystemLog(Host::eSystemLogError, "error: unable to find CIE at "
                                             "0x%8.8x for cie_id = 0x%8.8x for "
                                             "entry at 0x%8.8x.\n",
                      cie_offset, cie_id, current_entry);
    }
    offset = next_entry;
  }
  m_fde_index.Sort();
  m_fde_index_initialized = true;
}

bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
                                         Address startaddr,
                                         UnwindPlan &unwind_plan) {
  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND);
  lldb::offset_t offset = dwarf_offset;
  lldb::offset_t current_entry = offset;

  if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
    return false;

  if (!m_cfi_data_initialized)
    GetCFIData();

  uint32_t length = m_cfi_data.GetU32(&offset);
  dw_offset_t cie_offset;
  bool is_64bit = (length == UINT32_MAX);
  if (is_64bit) {
    length = m_cfi_data.GetU64(&offset);
    cie_offset = m_cfi_data.GetU64(&offset);
  } else {
    cie_offset = m_cfi_data.GetU32(&offset);
  }

  // FDE entries with zeroth cie_offset may occur for debug_frame.
  assert(!(m_type == EH && 0 == cie_offset) && cie_offset != UINT32_MAX);

  // Translate the CIE_id from the eh_frame format, which is relative to the
  // FDE offset, into a __eh_frame section offset
  if (m_type == EH) {
    unwind_plan.SetSourceName("eh_frame CFI");
    cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset;
    unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
  } else {
    unwind_plan.SetSourceName("DWARF CFI");
    // In theory the debug_frame info should be valid at all call sites
    // ("asynchronous unwind info" as it is sometimes called) but in practice
    // gcc et al all emit call frame info for the prologue and call sites, but
    // not for the epilogue or all the other locations during the function
    // reliably.
    unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
  }
  unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);

  const CIE *cie = GetCIE(cie_offset);
  assert(cie != nullptr);

  const dw_offset_t end_offset = current_entry + length + (is_64bit ? 12 : 4);

  const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
  const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
  const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
  lldb::addr_t range_base =
      GetGNUEHPointer(m_cfi_data, &offset, cie->ptr_encoding, pc_rel_addr,
                      text_addr, data_addr);
  lldb::addr_t range_len = GetGNUEHPointer(
      m_cfi_data, &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING,
      pc_rel_addr, text_addr, data_addr);
  AddressRange range(range_base, m_objfile.GetAddressByteSize(),
                     m_objfile.GetSectionList());
  range.SetByteSize(range_len);

  addr_t lsda_data_file_address = LLDB_INVALID_ADDRESS;

  if (cie->augmentation[0] == 'z') {
    uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
    if (aug_data_len != 0 && cie->lsda_addr_encoding != DW_EH_PE_omit) {
      offset_t saved_offset = offset;
      lsda_data_file_address =
          GetGNUEHPointer(m_cfi_data, &offset, cie->lsda_addr_encoding,
                          pc_rel_addr, text_addr, data_addr);
      if (offset - saved_offset != aug_data_len) {
        // There is more in the augmentation region than we know how to process;
        // don't read anything.
        lsda_data_file_address = LLDB_INVALID_ADDRESS;
      }
      offset = saved_offset;
    }
    offset += aug_data_len;
  }
  unwind_plan.SetUnwindPlanForSignalTrap(
    strchr(cie->augmentation, 'S') ? eLazyBoolYes : eLazyBoolNo);

  Address lsda_data;
  Address personality_function_ptr;

  if (lsda_data_file_address != LLDB_INVALID_ADDRESS &&
      cie->personality_loc != LLDB_INVALID_ADDRESS) {
    m_objfile.GetModule()->ResolveFileAddress(lsda_data_file_address,
                                              lsda_data);
    m_objfile.GetModule()->ResolveFileAddress(cie->personality_loc,
                                              personality_function_ptr);
  }

  if (lsda_data.IsValid() && personality_function_ptr.IsValid()) {
    unwind_plan.SetLSDAAddress(lsda_data);
    unwind_plan.SetPersonalityFunctionPtr(personality_function_ptr);
  }

  uint32_t code_align = cie->code_align;
  int32_t data_align = cie->data_align;

  unwind_plan.SetPlanValidAddressRange(range);
  UnwindPlan::Row *cie_initial_row = new UnwindPlan::Row;
  *cie_initial_row = cie->initial_row;
  UnwindPlan::RowSP row(cie_initial_row);

  unwind_plan.SetRegisterKind(GetRegisterKind());
  unwind_plan.SetReturnAddressRegister(cie->return_addr_reg_num);

  std::vector<UnwindPlan::RowSP> stack;

  UnwindPlan::Row::RegisterLocation reg_location;
  while (m_cfi_data.ValidOffset(offset) && offset < end_offset) {
    uint8_t inst = m_cfi_data.GetU8(&offset);
    uint8_t primary_opcode = inst & 0xC0;
    uint8_t extended_opcode = inst & 0x3F;

    if (!HandleCommonDwarfOpcode(primary_opcode, extended_opcode, data_align,
                                 offset, *row)) {
      if (primary_opcode) {
        switch (primary_opcode) {
        case DW_CFA_advance_loc: // (Row Creation Instruction)
        { // 0x40 - high 2 bits are 0x1, lower 6 bits are delta
          // takes a single argument that represents a constant delta. The
          // required action is to create a new table row with a location value
          // that is computed by taking the current entry's location value and
          // adding (delta * code_align). All other values in the new row are
          // initially identical to the current row.
          unwind_plan.AppendRow(row);
          UnwindPlan::Row *newrow = new UnwindPlan::Row;
          *newrow = *row.get();
          row.reset(newrow);
          row->SlideOffset(extended_opcode * code_align);
          break;
        }

        case DW_CFA_restore: { // 0xC0 - high 2 bits are 0x3, lower 6 bits are
                               // register
          // takes a single argument that represents a register number. The
          // required action is to change the rule for the indicated register
          // to the rule assigned it by the initial_instructions in the CIE.
          uint32_t reg_num = extended_opcode;
          // We only keep enough register locations around to unwind what is in
          // our thread, and these are organized by the register index in that
          // state, so we need to convert our eh_frame register number from the
          // EH frame info, to a register index

          if (unwind_plan.IsValidRowIndex(0) &&
              unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num,
                                                            reg_location))
            row->SetRegisterInfo(reg_num, reg_location);
          break;
        }
        }
      } else {
        switch (extended_opcode) {
        case DW_CFA_set_loc: // 0x1 (Row Creation Instruction)
        {
          // DW_CFA_set_loc takes a single argument that represents an address.
          // The required action is to create a new table row using the
          // specified address as the location. All other values in the new row
          // are initially identical to the current row. The new location value
          // should always be greater than the current one.
          unwind_plan.AppendRow(row);
          UnwindPlan::Row *newrow = new UnwindPlan::Row;
          *newrow = *row.get();
          row.reset(newrow);
          row->SetOffset(m_cfi_data.GetAddress(&offset) -
                         startaddr.GetFileAddress());
          break;
        }

        case DW_CFA_advance_loc1: // 0x2 (Row Creation Instruction)
        {
          // takes a single uword argument that represents a constant delta.
          // This instruction is identical to DW_CFA_advance_loc except for the
          // encoding and size of the delta argument.
          unwind_plan.AppendRow(row);
          UnwindPlan::Row *newrow = new UnwindPlan::Row;
          *newrow = *row.get();
          row.reset(newrow);
          row->SlideOffset(m_cfi_data.GetU8(&offset) * code_align);
          break;
        }

        case DW_CFA_advance_loc2: // 0x3 (Row Creation Instruction)
        {
          // takes a single uword argument that represents a constant delta.
          // This instruction is identical to DW_CFA_advance_loc except for the
          // encoding and size of the delta argument.
          unwind_plan.AppendRow(row);
          UnwindPlan::Row *newrow = new UnwindPlan::Row;
          *newrow = *row.get();
          row.reset(newrow);
          row->SlideOffset(m_cfi_data.GetU16(&offset) * code_align);
          break;
        }

        case DW_CFA_advance_loc4: // 0x4 (Row Creation Instruction)
        {
          // takes a single uword argument that represents a constant delta.
          // This instruction is identical to DW_CFA_advance_loc except for the
          // encoding and size of the delta argument.
          unwind_plan.AppendRow(row);
          UnwindPlan::Row *newrow = new UnwindPlan::Row;
          *newrow = *row.get();
          row.reset(newrow);
          row->SlideOffset(m_cfi_data.GetU32(&offset) * code_align);
          break;
        }

        case DW_CFA_restore_extended: // 0x6
        {
          // takes a single unsigned LEB128 argument that represents a register
          // number. This instruction is identical to DW_CFA_restore except for
          // the encoding and size of the register argument.
          uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
          if (unwind_plan.IsValidRowIndex(0) &&
              unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num,
                                                            reg_location))
            row->SetRegisterInfo(reg_num, reg_location);
          break;
        }

        case DW_CFA_remember_state: // 0xA
        {
          // These instructions define a stack of information. Encountering the
          // DW_CFA_remember_state instruction means to save the rules for
          // every register on the current row on the stack. Encountering the
          // DW_CFA_restore_state instruction means to pop the set of rules off
          // the stack and place them in the current row. (This operation is
          // useful for compilers that move epilogue code into the body of a
          // function.)
          stack.push_back(row);
          UnwindPlan::Row *newrow = new UnwindPlan::Row;
          *newrow = *row.get();
          row.reset(newrow);
          break;
        }

        case DW_CFA_restore_state: // 0xB
        {
          // These instructions define a stack of information. Encountering the
          // DW_CFA_remember_state instruction means to save the rules for
          // every register on the current row on the stack. Encountering the
          // DW_CFA_restore_state instruction means to pop the set of rules off
          // the stack and place them in the current row. (This operation is
          // useful for compilers that move epilogue code into the body of a
          // function.)
          if (stack.empty()) {
            LLDB_LOGF(log,
                      "DWARFCallFrameInfo::%s(dwarf_offset: %" PRIx32
                      ", startaddr: %" PRIx64
                      " encountered DW_CFA_restore_state but state stack "
                      "is empty. Corrupt unwind info?",
                      __FUNCTION__, dwarf_offset, startaddr.GetFileAddress());
            break;
          }
          lldb::addr_t offset = row->GetOffset();
          row = stack.back();
          stack.pop_back();
          row->SetOffset(offset);
          break;
        }

        case DW_CFA_GNU_args_size: // 0x2e
        {
          // The DW_CFA_GNU_args_size instruction takes an unsigned LEB128
          // operand representing an argument size. This instruction specifies
          // the total of the size of the arguments which have been pushed onto
          // the stack.

          // TODO: Figure out how we should handle this.
          m_cfi_data.GetULEB128(&offset);
          break;
        }

        case DW_CFA_val_offset:    // 0x14
        case DW_CFA_val_offset_sf: // 0x15
        default:
          break;
        }
      }
    }
  }
  unwind_plan.AppendRow(row);

  return true;
}

bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
                                                 uint8_t extended_opcode,
                                                 int32_t data_align,
                                                 lldb::offset_t &offset,
                                                 UnwindPlan::Row &row) {
  UnwindPlan::Row::RegisterLocation reg_location;

  if (primary_opcode) {
    switch (primary_opcode) {
    case DW_CFA_offset: { // 0x80 - high 2 bits are 0x2, lower 6 bits are
                          // register
      // takes two arguments: an unsigned LEB128 constant representing a
      // factored offset and a register number. The required action is to
      // change the rule for the register indicated by the register number to
      // be an offset(N) rule with a value of (N = factored offset *
      // data_align).
      uint8_t reg_num = extended_opcode;
      int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;
      reg_location.SetAtCFAPlusOffset(op_offset);
      row.SetRegisterInfo(reg_num, reg_location);
      return true;
    }
    }
  } else {
    switch (extended_opcode) {
    case DW_CFA_nop: // 0x0
      return true;

    case DW_CFA_offset_extended: // 0x5
    {
      // takes two unsigned LEB128 arguments representing a register number and
      // a factored offset. This instruction is identical to DW_CFA_offset
      // except for the encoding and size of the register argument.
      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
      int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;
      UnwindPlan::Row::RegisterLocation reg_location;
      reg_location.SetAtCFAPlusOffset(op_offset);
      row.SetRegisterInfo(reg_num, reg_location);
      return true;
    }

    case DW_CFA_undefined: // 0x7
    {
      // takes a single unsigned LEB128 argument that represents a register
      // number. The required action is to set the rule for the specified
      // register to undefined.
      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
      UnwindPlan::Row::RegisterLocation reg_location;
      reg_location.SetUndefined();
      row.SetRegisterInfo(reg_num, reg_location);
      return true;
    }

    case DW_CFA_same_value: // 0x8
    {
      // takes a single unsigned LEB128 argument that represents a register
      // number. The required action is to set the rule for the specified
      // register to same value.
      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
      UnwindPlan::Row::RegisterLocation reg_location;
      reg_location.SetSame();
      row.SetRegisterInfo(reg_num, reg_location);
      return true;
    }

    case DW_CFA_register: // 0x9
    {
      // takes two unsigned LEB128 arguments representing register numbers. The
      // required action is to set the rule for the first register to be the
      // second register.
      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
      uint32_t other_reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
      UnwindPlan::Row::RegisterLocation reg_location;
      reg_location.SetInRegister(other_reg_num);
      row.SetRegisterInfo(reg_num, reg_location);
      return true;
    }

    case DW_CFA_def_cfa: // 0xC    (CFA Definition Instruction)
    {
      // Takes two unsigned LEB128 operands representing a register number and
      // a (non-factored) offset. The required action is to define the current
      // CFA rule to use the provided register and offset.
      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
      int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
      row.GetCFAValue().SetIsRegisterPlusOffset(reg_num, op_offset);
      return true;
    }

    case DW_CFA_def_cfa_register: // 0xD    (CFA Definition Instruction)
    {
      // takes a single unsigned LEB128 argument representing a register
      // number. The required action is to define the current CFA rule to use
      // the provided register (but to keep the old offset).
      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
      row.GetCFAValue().SetIsRegisterPlusOffset(reg_num,
                                                row.GetCFAValue().GetOffset());
      return true;
    }

    case DW_CFA_def_cfa_offset: // 0xE    (CFA Definition Instruction)
    {
      // Takes a single unsigned LEB128 operand representing a (non-factored)
      // offset. The required action is to define the current CFA rule to use
      // the provided offset (but to keep the old register).
      int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
      row.GetCFAValue().SetIsRegisterPlusOffset(
          row.GetCFAValue().GetRegisterNumber(), op_offset);
      return true;
    }

    case DW_CFA_def_cfa_expression: // 0xF    (CFA Definition Instruction)
    {
      size_t block_len = (size_t)m_cfi_data.GetULEB128(&offset);
      const uint8_t *block_data =
          static_cast<const uint8_t *>(m_cfi_data.GetData(&offset, block_len));
      row.GetCFAValue().SetIsDWARFExpression(block_data, block_len);
      return true;
    }

    case DW_CFA_expression: // 0x10
    {
      // Takes two operands: an unsigned LEB128 value representing a register
      // number, and a DW_FORM_block value representing a DWARF expression. The
      // required action is to change the rule for the register indicated by
      // the register number to be an expression(E) rule where E is the DWARF
      // expression. That is, the DWARF expression computes the address. The
      // value of the CFA is pushed on the DWARF evaluation stack prior to
      // execution of the DWARF expression.
      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
      uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
      const uint8_t *block_data =
          static_cast<const uint8_t *>(m_cfi_data.GetData(&offset, block_len));
      UnwindPlan::Row::RegisterLocation reg_location;
      reg_location.SetAtDWARFExpression(block_data, block_len);
      row.SetRegisterInfo(reg_num, reg_location);
      return true;
    }

    case DW_CFA_offset_extended_sf: // 0x11
    {
      // takes two operands: an unsigned LEB128 value representing a register
      // number and a signed LEB128 factored offset. This instruction is
      // identical to DW_CFA_offset_extended except that the second operand is
      // signed and factored.
      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
      int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
      UnwindPlan::Row::RegisterLocation reg_location;
      reg_location.SetAtCFAPlusOffset(op_offset);
      row.SetRegisterInfo(reg_num, reg_location);
      return true;
    }

    case DW_CFA_def_cfa_sf: // 0x12   (CFA Definition Instruction)
    {
      // Takes two operands: an unsigned LEB128 value representing a register
      // number and a signed LEB128 factored offset. This instruction is
      // identical to DW_CFA_def_cfa except that the second operand is signed
      // and factored.
      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
      int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
      row.GetCFAValue().SetIsRegisterPlusOffset(reg_num, op_offset);
      return true;
    }

    case DW_CFA_def_cfa_offset_sf: // 0x13   (CFA Definition Instruction)
    {
      // takes a signed LEB128 operand representing a factored offset. This
      // instruction is identical to  DW_CFA_def_cfa_offset except that the
      // operand is signed and factored.
      int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
      uint32_t cfa_regnum = row.GetCFAValue().GetRegisterNumber();
      row.GetCFAValue().SetIsRegisterPlusOffset(cfa_regnum, op_offset);
      return true;
    }

    case DW_CFA_val_expression: // 0x16
    {
      // takes two operands: an unsigned LEB128 value representing a register
      // number, and a DW_FORM_block value representing a DWARF expression. The
      // required action is to change the rule for the register indicated by
      // the register number to be a val_expression(E) rule where E is the
      // DWARF expression. That is, the DWARF expression computes the value of
      // the given register. The value of the CFA is pushed on the DWARF
      // evaluation stack prior to execution of the DWARF expression.
      uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
      uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
      const uint8_t *block_data =
          (const uint8_t *)m_cfi_data.GetData(&offset, block_len);
      reg_location.SetIsDWARFExpression(block_data, block_len);
      row.SetRegisterInfo(reg_num, reg_location);
      return true;
    }
    }
  }
  return false;
}

void DWARFCallFrameInfo::ForEachFDEEntries(
    const std::function<bool(lldb::addr_t, uint32_t, dw_offset_t)> &callback) {
  GetFDEIndex();

  for (size_t i = 0, c = m_fde_index.GetSize(); i < c; ++i) {
    const FDEEntryMap::Entry &entry = m_fde_index.GetEntryRef(i);
    if (!callback(entry.base, entry.size, entry.data))
      break;
  }
}
