//===-- 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/Debugger.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/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Timer.h"
#include <cstring>
#include <list>
#include <optional>

using namespace lldb;
using namespace lldb_private;
using namespace llvm::dwarf;

// GetDwarfEHPtr
//
// Used for calls when the value type is specified by a DWARF EH Frame pointer
// encoding.
static uint64_t
GetGNUEHPointer(const DataExtractor &DE, lldb::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) {}

std::unique_ptr<UnwindPlan>
DWARFCallFrameInfo::GetUnwindPlan(const Address &addr) {
  return GetUnwindPlan({AddressRange(addr, 1)}, addr);
}

std::unique_ptr<UnwindPlan>
DWARFCallFrameInfo::GetUnwindPlan(llvm::ArrayRef<AddressRange> ranges,
                                  const Address &addr) {
  FDEEntryMap::Entry fde_entry;

  // 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 nullptr;

  std::vector<AddressRange> valid_ranges;

  auto result = std::make_unique<UnwindPlan>(GetRegisterKind());
  result->SetSourceName(m_type == EH ? "eh_frame CFI" : "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.
  result->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
  result->SetSourcedFromCompiler(eLazyBoolYes);
  result->SetUnwindPlanForSignalTrap(eLazyBoolNo);
  for (const AddressRange &range : ranges) {
    std::optional<FDEEntryMap::Entry> entry = GetFirstFDEEntryInRange(range);
    if (!entry)
      continue;
    std::optional<FDE> fde = ParseFDE(entry->data, addr);
    if (!fde)
      continue;
    int64_t slide =
        fde->range.GetBaseAddress().GetFileAddress() - addr.GetFileAddress();
    valid_ranges.push_back(std::move(fde->range));
    if (fde->for_signal_trap)
      result->SetUnwindPlanForSignalTrap(eLazyBoolYes);
    result->SetReturnAddressRegister(fde->return_addr_reg_num);
    for (UnwindPlan::Row &row : fde->rows) {
      row.SlideOffset(slide);
      result->AppendRow(std::move(row));
    }
  }
  result->SetPlanValidAddressRanges(std::move(valid_ranges));
  if (result->GetRowCount() == 0)
    return nullptr;
  return result;
}

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;
}

std::optional<DWARFCallFrameInfo::FDEEntryMap::Entry>
DWARFCallFrameInfo::GetFirstFDEEntryInRange(const AddressRange &range) {
  if (!m_section_sp || m_section_sp->IsEncrypted())
    return std::nullopt;

  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 std::nullopt;
}

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) {
      Debugger::ReportError(
          llvm::formatv("CIE parse error: CFI version {0} is not supported",
                        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') {
      Debugger::ReportError(llvm::formatv(
          "CIE parse error: CIE augmentation string was too large "
          "for the fixed sized buffer of {0} bytes.",
          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 = GetLog(LLDBLog::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", 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) {
      Debugger::ReportError(llvm::formatv("Invalid fde/cie next entry offset "
                                          "of {0:x} found in cie/fde at {1:x}",
                                          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()) {
      Debugger::ReportError(llvm::formatv("Invalid cie offset of {0:x} "
                                          "found in cie/fde at {1:x}",
                                          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 {
      Debugger::ReportError(llvm::formatv(
          "unable to find CIE at {0:x} for cie_id = {1:x} for entry at {2:x}.",
          cie_offset, cie_id, current_entry));
    }
    offset = next_entry;
  }
  m_fde_index.Sort();
  m_fde_index_initialized = true;
}

std::optional<DWARFCallFrameInfo::FDE>
DWARFCallFrameInfo::ParseFDE(dw_offset_t dwarf_offset,
                             const Address &startaddr) {
  Log *log = GetLog(LLDBLog::Unwind);
  lldb::offset_t offset = dwarf_offset;
  lldb::offset_t current_entry = offset;

  if (!m_section_sp || m_section_sp->IsEncrypted())
    return std::nullopt;

  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)
    cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset;

  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);

  // Skip the LSDA, if present.
  if (cie->augmentation[0] == 'z')
    offset += (uint32_t)m_cfi_data.GetULEB128(&offset);

  FDE fde;
  fde.for_signal_trap = strchr(cie->augmentation, 'S') != nullptr;
  fde.range = range;
  fde.return_addr_reg_num = cie->return_addr_reg_num;

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

  UnwindPlan::Row row = cie->initial_row;
  std::vector<UnwindPlan::Row> stack;

  UnwindPlan::Row::AbstractRegisterLocation 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.
          fde.rows.push_back(row);
          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 (fde.rows[0].GetRegisterInfo(reg_num, reg_location))
            row.SetRegisterInfo(reg_num, reg_location);
          else {
            // If the register was not set in the first row, remove the
            // register info to keep the unmodified value from the caller.
            row.RemoveRegisterInfo(reg_num);
          }
          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.
          fde.rows.push_back(row);
          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.
          fde.rows.push_back(row);
          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.
          fde.rows.push_back(row);
          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.
          fde.rows.push_back(row);
          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 (fde.rows[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);
          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_LOG(log,
                     "DWARFCallFrameInfo::{0}(dwarf_offset: "
                     "{1:x16}, startaddr: [{2:x16}] encountered "
                     "DW_CFA_restore_state but state stack "
                     "is empty. Corrupt unwind info?",
                     __FUNCTION__, dwarf_offset, startaddr.GetFileAddress());
            break;
          }
          int64_t offset = row.GetOffset();
          row = std::move(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
          // takes two unsigned LEB128 operands representing a register number
          // and a factored offset. The required action is to change the rule
          // for the register indicated by the register number to be a
          // val_offset(N) rule where the value of N is factored_offset*
          // data_alignment_factor
          uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
          int32_t op_offset =
              (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;
          reg_location.SetIsCFAPlusOffset(op_offset);
          row.SetRegisterInfo(reg_num, reg_location);
          break;
        }
        case DW_CFA_val_offset_sf: { // 0x15
          // takes two operands: an unsigned LEB128 value representing a
          // register number and a signed LEB128 factored offset. This
          // instruction is identical to DW_CFA_val_offset except that the
          // second operand is signed and factored. The resulting offset is
          // factored_offset* data_alignment_factor.
          uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
          int32_t op_offset =
              (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
          reg_location.SetIsCFAPlusOffset(op_offset);
          row.SetRegisterInfo(reg_num, reg_location);
          break;
        }
        default:
          break;
        }
      }
    }
  }
  fde.rows.push_back(row);
  return fde;
}

bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
                                                 uint8_t extended_opcode,
                                                 int32_t data_align,
                                                 lldb::offset_t &offset,
                                                 UnwindPlan::Row &row) {
  UnwindPlan::Row::AbstractRegisterLocation 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::AbstractRegisterLocation 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::AbstractRegisterLocation 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::AbstractRegisterLocation 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::AbstractRegisterLocation 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::AbstractRegisterLocation 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::AbstractRegisterLocation 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;
  }
}
