//===-- 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 lldb_private::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
        case DW_CFA_val_offset_sf: // 0x15
        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;
  }
}
