//===-- RegisterContextUnwind.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/Target/RegisterContextUnwind.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DWARFExpressionList.h"
#include "lldb/Symbol/ArmUnwindInfo.h"
#include "lldb/Symbol/CallFrameInfo.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/VASPrintf.h"
#include "lldb/lldb-private.h"
#include "llvm/Support/FormatAdapters.h"
#include <cassert>
#include <memory>

using namespace lldb;
using namespace lldb_private;

static ConstString GetSymbolOrFunctionName(const SymbolContext &sym_ctx) {
  if (sym_ctx.symbol)
    return sym_ctx.symbol->GetName();
  else if (sym_ctx.function)
    return sym_ctx.function->GetName();
  return ConstString();
}

static bool CallFrameAddressIsValid(ABISP abi_sp, lldb::addr_t cfa) {
  if (cfa == LLDB_INVALID_ADDRESS)
    return false;
  if (abi_sp)
    return abi_sp->CallFrameAddressIsValid(cfa);
  return cfa != 0 && cfa != 1;
}

/// Identify a clang outlined function by symbol name.
///
/// The unwind information in outlined functions from clang can be
/// incorrect, and because of when the outlining happens in the compilation,
/// it may not be possible to fix.  We will need to ignore any
/// instruction-emulation or compiler-sourced unwind plans for these
/// functions, and fall back to an ABI default unwindplan.
static bool IsClangOutlinedFunction(const SymbolContext &sym_ctx) {
  llvm::StringRef name = GetSymbolOrFunctionName(sym_ctx).GetStringRef();
  if (name.starts_with("OUTLINED_FUNCTION_"))
    return true;
  return false;
}

#define UNWIND_LOG_IMPL(LOG_FN, log, ...)                                      \
  LOG_FN(log, "{0}th{1}/fr{2} {3}",                                            \
         llvm::indent(std::min(m_frame_number, 100U)), m_thread.GetIndexID(),  \
         m_frame_number, llvm::formatv(__VA_ARGS__))

#define UNWIND_LOG(log, ...) UNWIND_LOG_IMPL(LLDB_LOG, log, __VA_ARGS__)

#define UNWIND_LOG_VERBOSE(log, ...)                                           \
  UNWIND_LOG_IMPL(LLDB_LOG_VERBOSE, log, __VA_ARGS__)

RegisterContextUnwind::RegisterContextUnwind(Thread &thread,
                                             const SharedPtr &next_frame,
                                             SymbolContext &sym_ctx,
                                             uint32_t frame_number,
                                             UnwindLLDB &unwind_lldb)
    : RegisterContext(thread, frame_number), m_thread(thread),
      m_fast_unwind_plan_sp(), m_full_unwind_plan_sp(),
      m_fallback_unwind_plan_sp(), m_all_registers_available(false),
      m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS),
      m_afa(LLDB_INVALID_ADDRESS), m_start_pc(), m_current_pc(),
      m_current_offset(), m_current_offset_backed_up_one(),
      m_behaves_like_zeroth_frame(false), m_sym_ctx(sym_ctx),
      m_sym_ctx_valid(false), m_frame_number(frame_number), m_registers(),
      m_parent_unwind(unwind_lldb) {
  m_sym_ctx.Clear(false);
  m_sym_ctx_valid = false;

  if (IsFrameZero()) {
    InitializeZerothFrame();
  } else {
    InitializeNonZerothFrame();
  }

  // This same code exists over in the GetFullUnwindPlanForFrame() but it may
  // not have been executed yet
  if (IsFrameZero() || next_frame->m_frame_type == eTrapHandlerFrame ||
      next_frame->m_frame_type == eDebuggerFrame) {
    m_all_registers_available = true;
  }
}

bool RegisterContextUnwind::IsUnwindPlanValidForCurrentPC(
    std::shared_ptr<const UnwindPlan> unwind_plan_sp) {
  if (!unwind_plan_sp)
    return false;

  // check if m_current_pc is valid
  if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
    // yes - current offset can be used as is
    return true;
  }

  // If don't have an offset or we're at the start of the function, we've got
  // nothing else to try.
  if (!m_current_offset || m_current_offset == 0)
    return false;

  // check pc - 1 to see if it's valid
  Address pc_minus_one(m_current_pc);
  pc_minus_one.Slide(-1);
  if (unwind_plan_sp->PlanValidAtAddress(pc_minus_one)) {
    return true;
  }

  return false;
}

// Initialize a RegisterContextUnwind which is the first frame of a stack -- the
// zeroth frame or currently executing frame.

void RegisterContextUnwind::InitializeZerothFrame() {
  Log *log = GetLog(LLDBLog::Unwind);
  ExecutionContext exe_ctx(m_thread.shared_from_this());
  RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext();

  if (reg_ctx_sp.get() == nullptr) {
    m_frame_type = eNotAValidFrame;
    UNWIND_LOG(log, "frame does not have a register context");
    return;
  }

  addr_t current_pc = reg_ctx_sp->GetPC();

  if (current_pc == LLDB_INVALID_ADDRESS) {
    m_frame_type = eNotAValidFrame;
    UNWIND_LOG(log, "frame does not have a pc");
    return;
  }

  Process *process = exe_ctx.GetProcessPtr();

  // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
  // this will strip bit zero in case we read a PC from memory or from the LR.
  // (which would be a no-op in frame 0 where we get it from the register set,
  // but still a good idea to make the call here for other ABIs that may
  // exist.)
  if (ABISP abi_sp = process->GetABI())
    current_pc = abi_sp->FixCodeAddress(current_pc);

  std::shared_ptr<const UnwindPlan> lang_runtime_plan_sp =
      LanguageRuntime::GetRuntimeUnwindPlan(m_thread, this,
                                            m_behaves_like_zeroth_frame);
  if (lang_runtime_plan_sp.get()) {
    UNWIND_LOG(log, "This is an async frame");
  }

  // Initialize m_current_pc, an Address object, based on current_pc, an
  // addr_t.
  m_current_pc.SetLoadAddress(current_pc, &process->GetTarget());

  // If we don't have a Module for some reason, we're not going to find
  // symbol/function information - just stick in some reasonable defaults and
  // hope we can unwind past this frame.
  ModuleSP pc_module_sp(m_current_pc.GetModule());
  if (!m_current_pc.IsValid() || !pc_module_sp) {
    UNWIND_LOG(log, "using architectural default unwind method");
  }

  m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx);

  if (m_sym_ctx.symbol) {
    UNWIND_LOG(log, "with pc value of {0:x}, symbol name is '{1}'", current_pc,
               GetSymbolOrFunctionName(m_sym_ctx));
  } else if (m_sym_ctx.function) {
    UNWIND_LOG(log, "with pc value of {0:x}, function name is '{1}'",
               current_pc, GetSymbolOrFunctionName(m_sym_ctx));
  } else {
    UNWIND_LOG(log, "with pc value of {0:x}, no symbol/function name is known.",
               current_pc);
  }

  if (IsTrapHandlerSymbol(process, m_sym_ctx)) {
    m_frame_type = eTrapHandlerFrame;
  } else {
    // FIXME:  Detect eDebuggerFrame here.
    m_frame_type = eNormalFrame;
  }

  // If we were able to find a symbol/function, set addr_range to the bounds of
  // that symbol/function. else treat the current pc value as the start_pc and
  // record no offset.
  if (m_sym_ctx_valid) {
    m_start_pc = m_sym_ctx.GetFunctionOrSymbolAddress();
    if (m_current_pc.GetModule() == m_start_pc.GetModule()) {
      m_current_offset =
          m_current_pc.GetFileAddress() - m_start_pc.GetFileAddress();
    }
    m_current_offset_backed_up_one = m_current_offset;
  } else {
    m_start_pc = m_current_pc;
    m_current_offset = std::nullopt;
    m_current_offset_backed_up_one = std::nullopt;
  }

  // We've set m_frame_type and m_sym_ctx before these calls.

  m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame();
  m_full_unwind_plan_sp = GetFullUnwindPlanForFrame();

  const UnwindPlan::Row *active_row = nullptr;
  lldb::RegisterKind row_register_kind = eRegisterKindGeneric;

  // If we have LanguageRuntime UnwindPlan for this unwind, use those
  // rules to find the caller frame instead of the function's normal
  // UnwindPlans.  The full unwind plan for this frame will be
  // the LanguageRuntime-provided unwind plan, and there will not be a
  // fast unwind plan.
  if (lang_runtime_plan_sp.get()) {
    active_row =
        lang_runtime_plan_sp->GetRowForFunctionOffset(m_current_offset);
    row_register_kind = lang_runtime_plan_sp->GetRegisterKind();
    if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(),
                          m_cfa)) {
      UNWIND_LOG(log, "Cannot set cfa");
    } else {
      m_full_unwind_plan_sp = lang_runtime_plan_sp;
      if (log) {
        StreamString active_row_strm;
        active_row->Dump(active_row_strm, lang_runtime_plan_sp.get(), &m_thread,
                         m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
        UNWIND_LOG(log, "async active row: {0}", active_row_strm.GetString());
      }
      UNWIND_LOG(log, "m_cfa = {0:x} m_afa = {1:x}", m_cfa, m_afa);
      UNWIND_LOG(log,
                 "initialized async frame current pc is {0:x} cfa is {1:x} afa "
                 "is {2:x}",
                 m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), m_cfa,
                 m_afa);

      return;
    }
  }

  if (m_full_unwind_plan_sp &&
      m_full_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
    active_row =
        m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
    row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
    PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
    if (active_row && log) {
      StreamString active_row_strm;
      active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread,
                       m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
      UNWIND_LOG(log, "{0}", active_row_strm.GetString());
    }
  }

  if (!active_row) {
    UNWIND_LOG(log, "could not find an unwindplan row for this frame's pc");
    m_frame_type = eNotAValidFrame;
    return;
  }

  if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) {
    // Try the fall back unwind plan since the
    // full unwind plan failed.
    FuncUnwindersSP func_unwinders_sp;
    std::shared_ptr<const UnwindPlan> call_site_unwind_plan;
    bool cfa_status = false;

    if (m_sym_ctx_valid) {
      func_unwinders_sp =
          pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress(
              m_current_pc, m_sym_ctx);
    }

    if (func_unwinders_sp.get() != nullptr)
      call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(
          process->GetTarget(), m_thread);

    if (call_site_unwind_plan != nullptr) {
      m_fallback_unwind_plan_sp = call_site_unwind_plan;
      if (TryFallbackUnwindPlan())
        cfa_status = true;
    }
    if (!cfa_status) {
      UNWIND_LOG(log, "could not read CFA value for first frame.");
      m_frame_type = eNotAValidFrame;
      return;
    }
  } else
    ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);

  if (m_cfa == LLDB_INVALID_ADDRESS && m_afa == LLDB_INVALID_ADDRESS) {
    UNWIND_LOG(log,
               "could not read CFA or AFA values for first frame, not valid.");
    m_frame_type = eNotAValidFrame;
    return;
  }

  // Give the Architecture a chance to replace the UnwindPlan.
  TryAdoptArchitectureUnwindPlan();

  UNWIND_LOG(log,
             "initialized frame current pc is {0:x} cfa is {1:x} afa is {2:x} "
             "using {3} UnwindPlan",
             m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), m_cfa, m_afa,
             m_full_unwind_plan_sp->GetSourceName());
}

// Initialize a RegisterContextUnwind for the non-zeroth frame -- rely on the
// RegisterContextUnwind "below" it to provide things like its current pc value.

void RegisterContextUnwind::InitializeNonZerothFrame() {
  Log *log = GetLog(LLDBLog::Unwind);
  if (IsFrameZero()) {
    m_frame_type = eNotAValidFrame;
    UNWIND_LOG(log, "non-zeroth frame tests positive for IsFrameZero -- that "
                    "shouldn't happen.");
    return;
  }

  if (!GetNextFrame().get() || !GetNextFrame()->IsValid()) {
    m_frame_type = eNotAValidFrame;
    UNWIND_LOG(log, "Could not get next frame, marking this frame as invalid.");
    return;
  }
  if (!m_thread.GetRegisterContext()) {
    m_frame_type = eNotAValidFrame;
    UNWIND_LOG(log, "Could not get register context for this thread, marking "
                    "this frame as invalid.");
    return;
  }

  ExecutionContext exe_ctx(m_thread.shared_from_this());
  Process *process = exe_ctx.GetProcessPtr();

  // Some languages may have a logical parent stack frame which is
  // not a real stack frame, but the programmer would consider it to
  // be the caller of the frame, e.g. Swift asynchronous frames.
  //
  // A LanguageRuntime may provide an UnwindPlan that is used in this
  // stack trace base on the RegisterContext contents, intsead
  // of the normal UnwindPlans we would use for the return-pc.
  std::shared_ptr<const UnwindPlan> lang_runtime_plan_sp =
      LanguageRuntime::GetRuntimeUnwindPlan(m_thread, this,
                                            m_behaves_like_zeroth_frame);
  if (lang_runtime_plan_sp.get()) {
    UNWIND_LOG(log, "This is an async frame");
  }

  addr_t pc;
  if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) {
    UNWIND_LOG(log, "could not get pc value");
    m_frame_type = eNotAValidFrame;
    return;
  }

  // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
  // this will strip bit zero in case we read a PC from memory or from the LR.
  ABISP abi_sp = process->GetABI();
  if (abi_sp)
    pc = abi_sp->FixCodeAddress(pc);

  if (log) {
    UNWIND_LOG(log, "pc = {0:x}", pc);
    addr_t reg_val;
    if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
      UNWIND_LOG(log, "fp = {0:x}", reg_val);
    if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
      UNWIND_LOG(log, "sp = {0:x}", reg_val);
  }

  // A pc of 0x0 means it's the end of the stack crawl unless we're above a trap
  // handler function
  bool above_trap_handler = false;
  if (GetNextFrame().get() && GetNextFrame()->IsValid() &&
      GetNextFrame()->IsTrapHandlerFrame())
    above_trap_handler = true;

  if (pc == 0 || pc == 0x1) {
    if (!above_trap_handler) {
      m_frame_type = eNotAValidFrame;
      UNWIND_LOG(log, "this frame has a pc of 0x0");
      return;
    }
  }

  const bool allow_section_end = true;
  m_current_pc.SetLoadAddress(pc, &process->GetTarget(), allow_section_end);

  // If we don't have a Module for some reason, we're not going to find
  // symbol/function information - just stick in some reasonable defaults and
  // hope we can unwind past this frame.  If we're above a trap handler,
  // we may be at a bogus address because we jumped through a bogus function
  // pointer and trapped, so don't force the arch default unwind plan in that
  // case.
  ModuleSP pc_module_sp(m_current_pc.GetModule());
  if ((!m_current_pc.IsValid() || !pc_module_sp) &&
      above_trap_handler == false) {
    UNWIND_LOG(log, "using architectural default unwind method");

    // Test the pc value to see if we know it's in an unmapped/non-executable
    // region of memory.
    uint32_t permissions;
    if (process->GetLoadAddressPermissions(pc, permissions) &&
        (permissions & ePermissionsExecutable) == 0) {
      // If this is the second frame off the stack, we may have unwound the
      // first frame incorrectly.  But using the architecture default unwind
      // plan may get us back on track -- albeit possibly skipping a real
      // frame.  Give this frame a clearly-invalid pc and see if we can get any
      // further.
      if (GetNextFrame().get() && GetNextFrame()->IsValid() &&
          GetNextFrame()->IsFrameZero()) {
        UNWIND_LOG(log,
                   "had a pc of {0:x} which is not in executable memory but on "
                   "frame 1 -- allowing it once.",
                   pc);
        m_frame_type = eSkipFrame;
      } else {
        // anywhere other than the second frame, a non-executable pc means
        // we're off in the weeds -- stop now.
        m_frame_type = eNotAValidFrame;
        UNWIND_LOG(log, "pc is in a non-executable section of memory and this "
                        "isn't the 2nd frame in the stack walk.");
        return;
      }
    }

    if (abi_sp) {
      m_fast_unwind_plan_sp.reset();
      m_full_unwind_plan_sp = abi_sp->CreateDefaultUnwindPlan();
      assert(((!m_full_unwind_plan_sp ||
               m_full_unwind_plan_sp->GetRowCount() == 0 ||
               m_full_unwind_plan_sp->GetRowAtIndex(0)
                   ->GetUnspecifiedRegistersAreUndefined())) &&
             "Default UnwindPlan must set "
             "UnspecifiedRegistersAreUndefined to true");
      if (m_frame_type != eSkipFrame) // don't override eSkipFrame
      {
        m_frame_type = eNormalFrame;
      }
      m_all_registers_available = false;
      m_current_offset = std::nullopt;
      m_current_offset_backed_up_one = std::nullopt;
      RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
      if (const UnwindPlan::Row *row =
              m_full_unwind_plan_sp->GetRowForFunctionOffset(0)) {
        if (!ReadFrameAddress(row_register_kind, row->GetCFAValue(), m_cfa)) {
          UNWIND_LOG(log, "failed to get cfa value");
          if (m_frame_type != eSkipFrame) // don't override eSkipFrame
          {
            m_frame_type = eNotAValidFrame;
          }
          return;
        }

        ReadFrameAddress(row_register_kind, row->GetAFAValue(), m_afa);

        // A couple of sanity checks..
        if (!CallFrameAddressIsValid(abi_sp, m_cfa)) {
          UNWIND_LOG(log, "could not find a valid cfa address");
          m_frame_type = eNotAValidFrame;
          return;
        }

        // m_cfa should point into the stack memory; if we can query memory
        // region permissions, see if the memory is allocated & readable.
        if (process->GetLoadAddressPermissions(m_cfa, permissions) &&
            (permissions & ePermissionsReadable) == 0) {
          m_frame_type = eNotAValidFrame;
          UNWIND_LOG(
              log, "the CFA points to a region of memory that is not readable");
          return;
        }
      } else {
        UNWIND_LOG(log, "could not find a row for function offset zero");
        m_frame_type = eNotAValidFrame;
        return;
      }

      if (CheckIfLoopingStack()) {
        TryFallbackUnwindPlan();
        if (CheckIfLoopingStack()) {
          UNWIND_LOG(log, "same CFA address as next frame, assuming the unwind "
                          "is looping - stopping");
          m_frame_type = eNotAValidFrame;
          return;
        }
      }

      // Give the Architecture a chance to replace the UnwindPlan.
      TryAdoptArchitectureUnwindPlan();

      UNWIND_LOG(log, "initialized frame cfa is {0:x} afa is {1:x}", m_cfa,
                 m_afa);
      return;
    }
    m_frame_type = eNotAValidFrame;
    UNWIND_LOG(log, "could not find any symbol for this pc, or a default "
                    "unwind plan, to continue unwind.");
    return;
  }

  m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx);

  if (m_sym_ctx.symbol) {
    UNWIND_LOG(log, "with pc value of {0:x}, symbol name is '{1}'", pc,
               GetSymbolOrFunctionName(m_sym_ctx));
  } else if (m_sym_ctx.function) {
    UNWIND_LOG(log, "with pc value of {0:x}, function name is '{1}'", pc,
               GetSymbolOrFunctionName(m_sym_ctx));
  } else {
    UNWIND_LOG(log, "with pc value of {0:x}, no symbol/function name is known.",
               pc);
  }

  bool decr_pc_and_recompute_addr_range;

  if (!m_sym_ctx_valid) {
    // Always decrement and recompute if the symbol lookup failed
    decr_pc_and_recompute_addr_range = true;
  } else if (GetNextFrame()->m_frame_type == eTrapHandlerFrame ||
             GetNextFrame()->m_frame_type == eDebuggerFrame) {
    // Don't decrement if we're "above" an asynchronous event like
    // sigtramp.
    decr_pc_and_recompute_addr_range = false;
  } else if (Address addr = m_sym_ctx.GetFunctionOrSymbolAddress();
             addr != m_current_pc) {
    // If our "current" pc isn't the start of a function, decrement the pc
    // if we're up the stack.
    if (m_behaves_like_zeroth_frame)
      decr_pc_and_recompute_addr_range = false;
    else
      decr_pc_and_recompute_addr_range = true;
  } else if (IsTrapHandlerSymbol(process, m_sym_ctx)) {
    // Signal dispatch may set the return address of the handler it calls to
    // point to the first byte of a return trampoline (like __kernel_rt_sigreturn),
    // so do not decrement and recompute if the symbol we already found is a trap
    // handler.
    decr_pc_and_recompute_addr_range = false;
  } else if (m_behaves_like_zeroth_frame) {
    decr_pc_and_recompute_addr_range = false;
  } else {
    // Decrement to find the function containing the call.
    decr_pc_and_recompute_addr_range = true;
  }

  // We need to back up the pc by 1 byte and re-search for the Symbol to handle
  // the case where the "saved pc" value is pointing to the next function, e.g.
  // if a function ends with a CALL instruction.
  // FIXME this may need to be an architectural-dependent behavior; if so we'll
  // need to add a member function
  // to the ABI plugin and consult that.
  if (decr_pc_and_recompute_addr_range) {
    UNWIND_LOG(log,
               "Backing up the pc value of {0:x} by 1 and re-doing symbol "
               "lookup; old symbol was {1}",
               pc, GetSymbolOrFunctionName(m_sym_ctx));
    Address temporary_pc;
    temporary_pc.SetLoadAddress(pc - 1, &process->GetTarget());
    m_sym_ctx.Clear(false);
    m_sym_ctx_valid = temporary_pc.ResolveFunctionScope(m_sym_ctx);

    UNWIND_LOG(log, "Symbol is now {0}", GetSymbolOrFunctionName(m_sym_ctx));
  }

  // If we were able to find a symbol/function, set addr_range_ptr to the
  // bounds of that symbol/function. else treat the current pc value as the
  // start_pc and record no offset.
  if (m_sym_ctx_valid) {
    m_start_pc = m_sym_ctx.GetFunctionOrSymbolAddress();
    m_current_offset = pc - m_start_pc.GetLoadAddress(&process->GetTarget());
    m_current_offset_backed_up_one = m_current_offset;
    if (decr_pc_and_recompute_addr_range &&
        m_current_offset_backed_up_one != 0) {
      --*m_current_offset_backed_up_one;
      if (m_sym_ctx_valid) {
        m_current_pc.SetLoadAddress(pc - 1, &process->GetTarget());
      }
    }
  } else {
    m_start_pc = m_current_pc;
    m_current_offset = std::nullopt;
    m_current_offset_backed_up_one = std::nullopt;
  }

  if (IsTrapHandlerSymbol(process, m_sym_ctx)) {
    m_frame_type = eTrapHandlerFrame;
  } else {
    // FIXME:  Detect eDebuggerFrame here.
    if (m_frame_type != eSkipFrame) // don't override eSkipFrame
    {
      m_frame_type = eNormalFrame;
    }
  }

  const UnwindPlan::Row *active_row;
  RegisterKind row_register_kind = eRegisterKindGeneric;

  // If we have LanguageRuntime UnwindPlan for this unwind, use those
  // rules to find the caller frame instead of the function's normal
  // UnwindPlans.  The full unwind plan for this frame will be
  // the LanguageRuntime-provided unwind plan, and there will not be a
  // fast unwind plan.
  if (lang_runtime_plan_sp.get()) {
    active_row =
        lang_runtime_plan_sp->GetRowForFunctionOffset(m_current_offset);
    row_register_kind = lang_runtime_plan_sp->GetRegisterKind();
    if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(),
                          m_cfa)) {
      UNWIND_LOG(log, "Cannot set cfa");
    } else {
      m_full_unwind_plan_sp = lang_runtime_plan_sp;
      if (log) {
        StreamString active_row_strm;
        active_row->Dump(active_row_strm, lang_runtime_plan_sp.get(), &m_thread,
                         m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
        UNWIND_LOG(log, "async active row: {0}", active_row_strm.GetString());
      }
      UNWIND_LOG(log, "m_cfa = {0:x} m_afa = {1:x}", m_cfa, m_afa);
      UNWIND_LOG(log,
                 "initialized async frame current pc is {0:x} cfa is {1:x} afa "
                 "is {2:x}",
                 m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), m_cfa,
                 m_afa);

      return;
    }
  }

  // We've set m_frame_type and m_sym_ctx before this call.
  m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame();

  // Try to get by with just the fast UnwindPlan if possible - the full
  // UnwindPlan may be expensive to get (e.g. if we have to parse the entire
  // eh_frame section of an ObjectFile for the first time.)

  if (m_fast_unwind_plan_sp &&
      m_fast_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
    active_row =
        m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
    row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind();
    PropagateTrapHandlerFlagFromUnwindPlan(m_fast_unwind_plan_sp);
    if (active_row && log) {
      StreamString active_row_strm;
      active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread,
                       m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
      UNWIND_LOG(log, "Using fast unwind plan '{0}'",
                 m_fast_unwind_plan_sp->GetSourceName());
      UNWIND_LOG(log, "active row: {0}", active_row_strm.GetString());
    }
  } else {
    m_full_unwind_plan_sp = GetFullUnwindPlanForFrame();
    if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp)) {
      active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset(
          m_current_offset_backed_up_one);
      row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
      PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
      if (active_row && log) {
        StreamString active_row_strm;
        active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(),
                         &m_thread,
                         m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
        UNWIND_LOG(log, "Using full unwind plan '{0}'",
                   m_full_unwind_plan_sp->GetSourceName());
        UNWIND_LOG(log, "active row: {0}", active_row_strm.GetString());
      }
    }
  }

  if (!active_row) {
    m_frame_type = eNotAValidFrame;
    UNWIND_LOG(log, "could not find unwind row for this pc");
    return;
  }

  if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) {
    UNWIND_LOG(log, "failed to get cfa");
    m_frame_type = eNotAValidFrame;
    return;
  }

  ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);

  UNWIND_LOG(log, "m_cfa = {0:x} m_afa = {1:x}", m_cfa, m_afa);

  if (CheckIfLoopingStack()) {
    TryFallbackUnwindPlan();
    if (CheckIfLoopingStack()) {
      UNWIND_LOG(log, "same CFA address as next frame, assuming the unwind is "
                      "looping - stopping");
      m_frame_type = eNotAValidFrame;
      return;
    }
  }

  // Give the Architecture a chance to replace the UnwindPlan.
  TryAdoptArchitectureUnwindPlan();

  UNWIND_LOG(log,
             "initialized frame current pc is {0:x} cfa is {1:x} afa is {2:x}",
             m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()), m_cfa, m_afa);
}

bool RegisterContextUnwind::CheckIfLoopingStack() {
  // If we have a bad stack setup, we can get the same CFA value multiple times
  // -- or even more devious, we can actually oscillate between two CFA values.
  // Detect that here and break out to avoid a possible infinite loop in lldb
  // trying to unwind the stack. To detect when we have the same CFA value
  // multiple times, we compare the
  // CFA of the current
  // frame with the 2nd next frame because in some specail case (e.g. signal
  // hanlders, hand written assembly without ABI compliance) we can have 2
  // frames with the same
  // CFA (in theory we
  // can have arbitrary number of frames with the same CFA, but more then 2 is
  // very unlikely)

  RegisterContextUnwind::SharedPtr next_frame = GetNextFrame();
  if (next_frame) {
    RegisterContextUnwind::SharedPtr next_next_frame =
        next_frame->GetNextFrame();
    addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS;
    if (next_next_frame && next_next_frame->GetCFA(next_next_frame_cfa)) {
      if (next_next_frame_cfa == m_cfa) {
        // We have a loop in the stack unwind
        return true;
      }
    }
  }
  return false;
}

bool RegisterContextUnwind::IsFrameZero() const { return m_frame_number == 0; }

bool RegisterContextUnwind::BehavesLikeZerothFrame() const {
  if (m_frame_number == 0)
    return true;
  if (m_behaves_like_zeroth_frame)
    return true;
  return false;
}

// Find a fast unwind plan for this frame, if possible.
//
// On entry to this method,
//
//   1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame
//   if either of those are correct,
//   2. m_sym_ctx should already be filled in, and
//   3. m_current_pc should have the current pc value for this frame
//   4. m_current_offset_backed_up_one should have the current byte offset into
//   the function, maybe backed up by 1, std::nullopt if unknown

std::shared_ptr<const UnwindPlan>
RegisterContextUnwind::GetFastUnwindPlanForFrame() {
  ModuleSP pc_module_sp(m_current_pc.GetModule());

  if (!m_current_pc.IsValid() || !pc_module_sp ||
      pc_module_sp->GetObjectFile() == nullptr)
    return nullptr;

  if (IsFrameZero())
    return nullptr;

  FuncUnwindersSP func_unwinders_sp(
      pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress(
          m_current_pc, m_sym_ctx));
  if (!func_unwinders_sp)
    return nullptr;

  // If we're in _sigtramp(), unwinding past this frame requires special
  // knowledge.
  if (m_frame_type == eTrapHandlerFrame || m_frame_type == eDebuggerFrame)
    return nullptr;

  if (std::shared_ptr<const UnwindPlan> unwind_plan_sp =
          func_unwinders_sp->GetUnwindPlanFastUnwind(
              *m_thread.CalculateTarget(), m_thread)) {
    if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
      m_frame_type = eNormalFrame;
      return unwind_plan_sp;
    }
  }
  return nullptr;
}

// On entry to this method,
//
//   1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame
//   if either of those are correct,
//   2. m_sym_ctx should already be filled in, and
//   3. m_current_pc should have the current pc value for this frame
//   4. m_current_offset_backed_up_one should have the current byte offset into
//   the function, maybe backed up by 1, std::nullopt if unknown

std::shared_ptr<const UnwindPlan>
RegisterContextUnwind::GetFullUnwindPlanForFrame() {
  Log *log = GetLog(LLDBLog::Unwind);
  std::shared_ptr<const UnwindPlan> arch_default_unwind_plan_sp;
  ExecutionContext exe_ctx(m_thread.shared_from_this());
  Process *process = exe_ctx.GetProcessPtr();
  ABI *abi = process ? process->GetABI().get() : nullptr;
  if (abi) {
    arch_default_unwind_plan_sp = abi->CreateDefaultUnwindPlan();
    assert(((!arch_default_unwind_plan_sp ||
             arch_default_unwind_plan_sp->GetRowCount() == 0 ||
             arch_default_unwind_plan_sp->GetRowAtIndex(0)
                 ->GetUnspecifiedRegistersAreUndefined())) &&
           "Default UnwindPlan must set "
           "UnspecifiedRegistersAreUndefined to true");
  } else {
    UNWIND_LOG(
        log, "unable to get architectural default UnwindPlan from ABI plugin");
  }

  if (IsFrameZero() || GetNextFrame()->m_frame_type == eTrapHandlerFrame ||
      GetNextFrame()->m_frame_type == eDebuggerFrame) {
    m_behaves_like_zeroth_frame = true;
    // If this frame behaves like a 0th frame (currently executing or
    // interrupted asynchronously), all registers can be retrieved.
    m_all_registers_available = true;
  }

  // If we've done a jmp 0x0 / bl 0x0 (called through a null function pointer)
  // so the pc is 0x0 in the zeroth frame, we need to use the "unwind at first
  // instruction" arch default UnwindPlan Also, if this Process can report on
  // memory region attributes, any non-executable region means we jumped
  // through a bad function pointer - handle the same way as 0x0. Note, if we
  // have a symbol context & a symbol, we don't want to follow this code path.
  // This is for jumping to memory regions without any information available.

  if ((!m_sym_ctx_valid ||
       (m_sym_ctx.function == nullptr && m_sym_ctx.symbol == nullptr)) &&
      m_behaves_like_zeroth_frame && m_current_pc.IsValid()) {
    uint32_t permissions;
    addr_t current_pc_addr =
        m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr());
    if (current_pc_addr == 0 ||
        (process &&
         process->GetLoadAddressPermissions(current_pc_addr, permissions) &&
         (permissions & ePermissionsExecutable) == 0)) {
      if (abi) {
        m_frame_type = eNormalFrame;
        return abi->CreateFunctionEntryUnwindPlan();
      }
    }
  }

  // No Module for the current pc, try using the architecture default unwind.
  ModuleSP pc_module_sp(m_current_pc.GetModule());
  if (!m_current_pc.IsValid() || !pc_module_sp ||
      pc_module_sp->GetObjectFile() == nullptr) {
    m_frame_type = eNormalFrame;
    return arch_default_unwind_plan_sp;
  }

  // Function outlining is a clang feature where common blocks of instructions
  // from separate functions can be put in a separate utility function, and
  // the original functions call into the utility function to execute them,
  // resulting in fewer bytes used for the code section overall.
  //
  // The call to the OUTLINED_FUNCTION may not be a normal ABI call (e.g.
  // on RISCV it might be called `jal t0, OUTLINED_FUNCTION_<nn>` putting the
  // return address in a temporary register instead of $ra).  The unwind
  // instructions in eh_frame/debug_frame are not correct today for an
  // OUTLINED_FUNCTION, even when a normal ABI call is made.
  // CFI may be absent or incorrect; instruction emulation may be incorrect
  // because it assumes a normal ABI call was made.
  if (m_sym_ctx_valid && arch_default_unwind_plan_sp) {
    if (IsClangOutlinedFunction(m_sym_ctx)) {
      UNWIND_LOG(log,
                 "Overriding full unwind plan, using architectural default for "
                 "function {0}",
                 GetSymbolOrFunctionName(m_sym_ctx));
      return arch_default_unwind_plan_sp;
    }
  }

  FuncUnwindersSP func_unwinders_sp;
  if (m_sym_ctx_valid) {
    func_unwinders_sp =
        pc_module_sp->GetUnwindTable().GetFuncUnwindersContainingAddress(
            m_current_pc, m_sym_ctx);
  }

  // No FuncUnwinders available for this pc (stripped function symbols, lldb
  // could not augment its function table with another source, like
  // LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO). See if eh_frame or the
  // .ARM.exidx tables have unwind information for this address, else fall back
  // to the architectural default unwind.
  if (!func_unwinders_sp) {
    m_frame_type = eNormalFrame;

    if (!pc_module_sp || !pc_module_sp->GetObjectFile() ||
        !m_current_pc.IsValid())
      return arch_default_unwind_plan_sp;

    // Even with -fomit-frame-pointer, we can try eh_frame to get back on
    // track.
    if (DWARFCallFrameInfo *eh_frame =
            pc_module_sp->GetUnwindTable().GetEHFrameInfo()) {
      if (std::unique_ptr<UnwindPlan> plan_up =
              eh_frame->GetUnwindPlan(m_current_pc))
        return plan_up;
    }

    ArmUnwindInfo *arm_exidx =
        pc_module_sp->GetUnwindTable().GetArmUnwindInfo();
    if (arm_exidx) {
      auto unwind_plan_sp =
          std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
      if (arm_exidx->GetUnwindPlan(exe_ctx.GetTargetRef(), m_current_pc,
                                   *unwind_plan_sp))
        return unwind_plan_sp;
    }

    CallFrameInfo *object_file_unwind =
        pc_module_sp->GetUnwindTable().GetObjectFileUnwindInfo();
    if (object_file_unwind) {
      if (std::unique_ptr<UnwindPlan> plan_up =
              object_file_unwind->GetUnwindPlan(m_current_pc))
        return plan_up;
    }

    return arch_default_unwind_plan_sp;
  }

  if (m_frame_type == eTrapHandlerFrame && process) {
    m_fast_unwind_plan_sp.reset();

    // On some platforms the unwind information for signal handlers is not
    // present or correct. Give the platform plugins a chance to provide
    // substitute plan. Otherwise, use eh_frame.
    if (m_sym_ctx_valid) {
      lldb::PlatformSP platform = process->GetTarget().GetPlatform();
      const ArchSpec arch = process->GetTarget().GetArchitecture();
      if (auto unwind_plan_sp = platform->GetTrapHandlerUnwindPlan(
              arch, GetSymbolOrFunctionName(m_sym_ctx)))
        return unwind_plan_sp;
    }

    auto unwind_plan_sp =
        func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget());
    if (!unwind_plan_sp)
      unwind_plan_sp =
          func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget());
    if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc) &&
        unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) {
      return unwind_plan_sp;
    }
  }

  // Ask the DynamicLoader if the eh_frame CFI should be trusted in this frame
  // even when it's frame zero This comes up if we have hand-written functions
  // in a Module and hand-written eh_frame.  The assembly instruction
  // inspection may fail and the eh_frame CFI were probably written with some
  // care to do the right thing.  It'd be nice if there was a way to ask the
  // eh_frame directly if it is asynchronous (can be trusted at every
  // instruction point) or synchronous (the normal case - only at call sites).
  // But there is not.
  if (process && process->GetDynamicLoader() &&
      process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo(m_sym_ctx)) {
    // We must specifically call the GetEHFrameUnwindPlan() method here --
    // normally we would call GetUnwindPlanAtCallSite() -- because CallSite may
    // return an unwind plan sourced from either eh_frame (that's what we
    // intend) or compact unwind (this won't work)
    auto unwind_plan_sp =
        func_unwinders_sp->GetEHFrameUnwindPlan(process->GetTarget());
    if (!unwind_plan_sp)
      unwind_plan_sp =
          func_unwinders_sp->GetObjectFileUnwindPlan(process->GetTarget());
    if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
      UNWIND_LOG_VERBOSE(log,
                         "frame uses {0} for full UnwindPlan because the "
                         "DynamicLoader suggested we prefer it",
                         unwind_plan_sp->GetSourceName());
      return unwind_plan_sp;
    }
  }

  // Typically the NonCallSite UnwindPlan is the unwind created by inspecting
  // the assembly language instructions
  if (m_behaves_like_zeroth_frame && process) {
    auto unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite(
        process->GetTarget(), m_thread);
    if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
      if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) {
        // We probably have an UnwindPlan created by inspecting assembly
        // instructions. The assembly profilers work really well with compiler-
        // generated functions but hand- written assembly can be problematic.
        // We set the eh_frame based unwind plan as our fallback unwind plan if
        // instruction emulation doesn't work out even for non call sites if it
        // is available and use the architecture default unwind plan if it is
        // not available. The eh_frame unwind plan is more reliable even on non
        // call sites then the architecture default plan and for hand written
        // assembly code it is often written in a way that it valid at all
        // location what helps in the most common cases when the instruction
        // emulation fails.
        std::shared_ptr<const UnwindPlan> call_site_unwind_plan =
            func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(),
                                                       m_thread);
        if (call_site_unwind_plan &&
            call_site_unwind_plan.get() != unwind_plan_sp.get() &&
            call_site_unwind_plan->GetSourceName() !=
                unwind_plan_sp->GetSourceName()) {
          m_fallback_unwind_plan_sp = call_site_unwind_plan;
        } else {
          m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp;
        }
      }
      UNWIND_LOG_VERBOSE(
          log,
          "frame uses {0} for full UnwindPlan because this is the non-call "
          "site unwind plan and this is a zeroth frame",
          unwind_plan_sp->GetSourceName());
      return unwind_plan_sp;
    }

    // If we're on the first instruction of a function, and we have an
    // architectural default UnwindPlan for the initial instruction of a
    // function, use that.
    if (m_current_offset == 0) {
      unwind_plan_sp =
          func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry(
              m_thread);
      if (unwind_plan_sp) {
        UNWIND_LOG_VERBOSE(log,
                           "frame uses {0} for full UnwindPlan because we are "
                           "at the first instruction of a function",
                           unwind_plan_sp->GetSourceName());
        return unwind_plan_sp;
      }
    }
  }

  std::shared_ptr<const UnwindPlan> unwind_plan_sp;
  // Typically this is unwind info from an eh_frame section intended for
  // exception handling; only valid at call sites
  if (process) {
    unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite(
        process->GetTarget(), m_thread);
  }
  if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp)) {
    UNWIND_LOG_VERBOSE(log,
                       "frame uses {0} for full UnwindPlan because this is the "
                       "call-site unwind plan",
                       unwind_plan_sp->GetSourceName());
    return unwind_plan_sp;
  }

  // We'd prefer to use an UnwindPlan intended for call sites when we're at a
  // call site but if we've struck out on that, fall back to using the non-
  // call-site assembly inspection UnwindPlan if possible.
  if (process) {
    unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite(
        process->GetTarget(), m_thread);
  }
  if (unwind_plan_sp &&
      unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) {
    // We probably have an UnwindPlan created by inspecting assembly
    // instructions. The assembly profilers work really well with compiler-
    // generated functions but hand- written assembly can be problematic. We
    // set the eh_frame based unwind plan as our fallback unwind plan if
    // instruction emulation doesn't work out even for non call sites if it is
    // available and use the architecture default unwind plan if it is not
    // available. The eh_frame unwind plan is more reliable even on non call
    // sites then the architecture default plan and for hand written assembly
    // code it is often written in a way that it valid at all location what
    // helps in the most common cases when the instruction emulation fails.
    std::shared_ptr<const UnwindPlan> call_site_unwind_plan =
        func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(),
                                                   m_thread);
    if (call_site_unwind_plan &&
        call_site_unwind_plan.get() != unwind_plan_sp.get() &&
        call_site_unwind_plan->GetSourceName() !=
            unwind_plan_sp->GetSourceName()) {
      m_fallback_unwind_plan_sp = call_site_unwind_plan;
    } else {
      m_fallback_unwind_plan_sp = arch_default_unwind_plan_sp;
    }
  }

  if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp)) {
    UNWIND_LOG_VERBOSE(log,
                       "frame uses {0} for full UnwindPlan because we failed "
                       "to find a call-site unwind plan that would work",
                       unwind_plan_sp->GetSourceName());
    return unwind_plan_sp;
  }

  // If nothing else, use the architectural default UnwindPlan and hope that
  // does the job.
  if (arch_default_unwind_plan_sp)
    UNWIND_LOG_VERBOSE(log,
                       "frame uses {0} for full UnwindPlan because we are "
                       "falling back to the arch default plan",
                       arch_default_unwind_plan_sp->GetSourceName());
  else
    UNWIND_LOG(log,
               "Unable to find any UnwindPlan for full unwind of this frame.");

  return arch_default_unwind_plan_sp;
}

void RegisterContextUnwind::InvalidateAllRegisters() {
  m_frame_type = eNotAValidFrame;
}

size_t RegisterContextUnwind::GetRegisterCount() {
  return m_thread.GetRegisterContext()->GetRegisterCount();
}

const RegisterInfo *RegisterContextUnwind::GetRegisterInfoAtIndex(size_t reg) {
  return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg);
}

size_t RegisterContextUnwind::GetRegisterSetCount() {
  return m_thread.GetRegisterContext()->GetRegisterSetCount();
}

const RegisterSet *RegisterContextUnwind::GetRegisterSet(size_t reg_set) {
  return m_thread.GetRegisterContext()->GetRegisterSet(reg_set);
}

uint32_t RegisterContextUnwind::ConvertRegisterKindToRegisterNumber(
    lldb::RegisterKind kind, uint32_t num) {
  return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
      kind, num);
}

bool RegisterContextUnwind::ReadRegisterValueFromRegisterLocation(
    lldb_private::UnwindLLDB::ConcreteRegisterLocation regloc,
    const RegisterInfo *reg_info, RegisterValue &value) {
  if (!IsValid())
    return false;
  bool success = false;

  switch (regloc.type) {
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterInLiveRegisterContext: {
    const RegisterInfo *other_reg_info =
        GetRegisterInfoAtIndex(regloc.location.register_number);

    if (!other_reg_info)
      return false;

    success =
        m_thread.GetRegisterContext()->ReadRegister(other_reg_info, value);
  } break;
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterInRegister: {
    const RegisterInfo *other_reg_info =
        GetRegisterInfoAtIndex(regloc.location.register_number);

    if (!other_reg_info)
      return false;

    if (IsFrameZero()) {
      success =
          m_thread.GetRegisterContext()->ReadRegister(other_reg_info, value);
    } else {
      success = GetNextFrame()->ReadRegister(other_reg_info, value);
    }
  } break;
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterIsRegisterPlusOffset: {
    auto regnum = regloc.location.reg_plus_offset.register_number;
    const RegisterInfo *other_reg_info =
        GetRegisterInfoAtIndex(regloc.location.reg_plus_offset.register_number);

    if (!other_reg_info)
      return false;

    if (IsFrameZero()) {
      success =
          m_thread.GetRegisterContext()->ReadRegister(other_reg_info, value);
    } else {
      success = GetNextFrame()->ReadRegister(other_reg_info, value);
    }
    if (success) {
      Log *log = GetLog(LLDBLog::Unwind);
      UNWIND_LOG(log, "read ({0})'s location", regnum);
      value = value.GetAsUInt64(~0ull, &success) +
              regloc.location.reg_plus_offset.offset;
      UNWIND_LOG(log, "success {0}", success ? "yes" : "no");
    }
  } break;
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterValueInferred:
    success =
        value.SetUInt(regloc.location.inferred_value, reg_info->byte_size);
    break;

  case UnwindLLDB::ConcreteRegisterLocation::eRegisterNotSaved:
    break;
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterSavedAtHostMemoryLocation:
    llvm_unreachable("FIXME debugger inferior function call unwind");
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterSavedAtMemoryLocation: {
    Status error(ReadRegisterValueFromMemory(
        reg_info, regloc.location.target_memory_location, reg_info->byte_size,
        value));
    success = error.Success();
  } break;
  default:
    llvm_unreachable("Unknown ConcreteRegisterLocation type.");
  }
  return success;
}

bool RegisterContextUnwind::WriteRegisterValueToRegisterLocation(
    lldb_private::UnwindLLDB::ConcreteRegisterLocation regloc,
    const RegisterInfo *reg_info, const RegisterValue &value) {
  if (!IsValid())
    return false;

  bool success = false;

  switch (regloc.type) {
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterInLiveRegisterContext: {
    const RegisterInfo *other_reg_info =
        GetRegisterInfoAtIndex(regloc.location.register_number);
    success =
        m_thread.GetRegisterContext()->WriteRegister(other_reg_info, value);
  } break;
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterInRegister: {
    const RegisterInfo *other_reg_info =
        GetRegisterInfoAtIndex(regloc.location.register_number);
    if (IsFrameZero()) {
      success =
          m_thread.GetRegisterContext()->WriteRegister(other_reg_info, value);
    } else {
      success = GetNextFrame()->WriteRegister(other_reg_info, value);
    }
  } break;
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterIsRegisterPlusOffset:
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterValueInferred:
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterNotSaved:
    break;
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterSavedAtHostMemoryLocation:
    llvm_unreachable("FIXME debugger inferior function call unwind");
  case UnwindLLDB::ConcreteRegisterLocation::eRegisterSavedAtMemoryLocation: {
    Status error(WriteRegisterValueToMemory(
        reg_info, regloc.location.target_memory_location, reg_info->byte_size,
        value));
    success = error.Success();
  } break;
  default:
    llvm_unreachable("Unknown ConcreteRegisterLocation type.");
  }
  return success;
}

bool RegisterContextUnwind::IsValid() const {
  return m_frame_type != eNotAValidFrame;
}

// After the final stack frame in a stack walk we'll get one invalid
// (eNotAValidFrame) stack frame -- one past the end of the stack walk.  But
// higher-level code will need to tell the difference between "the unwind plan
// below this frame failed" versus "we successfully completed the stack walk"
// so this method helps to disambiguate that.

bool RegisterContextUnwind::IsTrapHandlerFrame() const {
  return m_frame_type == eTrapHandlerFrame;
}

// A skip frame is a bogus frame on the stack -- but one where we're likely to
// find a real frame farther
// up the stack if we keep looking.  It's always the second frame in an unwind
// (i.e. the first frame after frame zero) where unwinding can be the
// trickiest.  Ideally we'll mark up this frame in some way so the user knows
// we're displaying bad data and we may have skipped one frame of their real
// program in the process of getting back on track.

bool RegisterContextUnwind::IsSkipFrame() const {
  return m_frame_type == eSkipFrame;
}

bool RegisterContextUnwind::IsTrapHandlerSymbol(
    lldb_private::Process *process,
    const lldb_private::SymbolContext &m_sym_ctx) const {
  PlatformSP platform_sp(process->GetTarget().GetPlatform());
  if (platform_sp) {
    const std::vector<ConstString> trap_handler_names(
        platform_sp->GetTrapHandlerSymbolNames());
    for (ConstString name : trap_handler_names) {
      if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) ||
          (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) {
        return true;
      }
    }
  }
  const std::vector<ConstString> user_specified_trap_handler_names(
      m_parent_unwind.GetUserSpecifiedTrapHandlerFunctionNames());
  for (ConstString name : user_specified_trap_handler_names) {
    if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) ||
        (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name)) {
      return true;
    }
  }

  return false;
}

// Search this stack frame's UnwindPlans for the AbstractRegisterLocation
// for this register.
//
// \param[in] lldb_regnum
//     The register number (in the eRegisterKindLLDB register numbering)
//     we are searching for.
//
// \param[out] kind
//     Set to the RegisterKind of the UnwindPlan which is the basis for
//     the returned AbstractRegisterLocation; if the location is in terms
//     of another register number, this Kind is needed to interpret it
//     correctly.
//
// \return
//     An empty optional indicaTes that there was an error in processing
//     the request.
//
//     If there is no unwind rule for a volatile (caller-preserved) register,
//     the returned AbstractRegisterLocation will be IsUndefined,
//     indicating that we should stop searching.
//
//     If there is no unwind rule for a non-volatile (callee-preserved)
//     register, the returned AbstractRegisterLocation will be IsSame.
//     In frame 0, IsSame means get the value from the live register context.
//     Else it means to continue descending down the stack to more-live frames
//     looking for a location/value.
//
//     If an AbstractRegisterLocation is found in an UnwindPlan, that will
//     be returned, with no consideration of the current ABI rules for
//     registers.  Functions using an alternate ABI calling convention
//     will work as long as the UnwindPlans are exhaustive about what
//     registers are volatile/non-volatile.
std::optional<UnwindPlan::Row::AbstractRegisterLocation>
RegisterContextUnwind::GetAbstractRegisterLocation(uint32_t lldb_regnum,
                                                   lldb::RegisterKind &kind) {
  RegisterNumber regnum(m_thread, eRegisterKindLLDB, lldb_regnum);
  Log *log = GetLog(LLDBLog::Unwind);

  kind = eRegisterKindLLDB;
  UnwindPlan::Row::AbstractRegisterLocation unwindplan_regloc;

  // First, try to find a register location via the FastUnwindPlan
  if (m_fast_unwind_plan_sp) {
    const UnwindPlan::Row *active_row =
        m_fast_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
    if (regnum.GetAsKind(kind) == LLDB_INVALID_REGNUM) {
      UNWIND_LOG(log,
                 "could not convert lldb regnum {0} ({1}) into {2} "
                 "RegisterKind reg numbering scheme",
                 regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), kind);
      return {};
    }
    kind = m_fast_unwind_plan_sp->GetRegisterKind();
    // The Fast UnwindPlan typically only provides fp & pc as we move up
    // the stack, without requiring additional parsing or memory reads.
    // It may mark all other registers as IsUndefined() because, indicating
    // that it doesn't know if they were spilled to stack or not.
    // If this case, for an IsUndefined register, we should continue on
    // to the Full UnwindPlan which may have more accurate information
    // about register locations of all registers.
    if (active_row &&
        active_row->GetRegisterInfo(regnum.GetAsKind(kind),
                                    unwindplan_regloc) &&
        !unwindplan_regloc.IsUndefined()) {
      UNWIND_LOG(
          log,
          "supplying caller's saved {0} ({1})'s location using FastUnwindPlan",
          regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
      return unwindplan_regloc;
    }
  }

  // Second, try to find a register location via the FullUnwindPlan.
  bool got_new_full_unwindplan = false;
  if (!m_full_unwind_plan_sp) {
    m_full_unwind_plan_sp = GetFullUnwindPlanForFrame();
    got_new_full_unwindplan = true;
  }
  if (m_full_unwind_plan_sp) {
    RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric,
                             LLDB_REGNUM_GENERIC_PC);

    const UnwindPlan::Row *active_row =
        m_full_unwind_plan_sp->GetRowForFunctionOffset(
            m_current_offset_backed_up_one);
    kind = m_full_unwind_plan_sp->GetRegisterKind();

    if (got_new_full_unwindplan && active_row && log) {
      StreamString active_row_strm;
      ExecutionContext exe_ctx(m_thread.shared_from_this());
      active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread,
                       m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
      UNWIND_LOG(log, "Using full unwind plan '{0}'",
                 m_full_unwind_plan_sp->GetSourceName());
      UNWIND_LOG(log, "active row: {0}", active_row_strm.GetString());
    }

    if (regnum.GetAsKind(kind) == LLDB_INVALID_REGNUM) {
      if (kind == eRegisterKindGeneric)
        UNWIND_LOG(log,
                   "could not convert lldb regnum {0} ({1}) into "
                   "eRegisterKindGeneric reg numbering scheme",
                   regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
      else
        UNWIND_LOG(log,
                   "could not convert lldb regnum {0} ({1}) into {2} "
                   "RegisterKind reg numbering scheme",
                   regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), kind);
      if (active_row && active_row->GetUnspecifiedRegistersAreUndefined()) {
        UNWIND_LOG(
            log,
            "marking register {0} ({1}) as Undefined (volatile) in this "
            "stack frame because this row is UnspecifiedRegistersAreUndefined.",
            regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
        unwindplan_regloc.SetUndefined();
        return unwindplan_regloc;
      }
      return {};
    }

    if (regnum.IsValid() && active_row &&
        active_row->GetRegisterInfo(regnum.GetAsKind(kind),
                                    unwindplan_regloc)) {
      UNWIND_LOG(
          log,
          "supplying caller's saved {0} ({1})'s location using {2} UnwindPlan",
          regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB),
          m_full_unwind_plan_sp->GetSourceName());
      return unwindplan_regloc;
    }

    // When asking for the caller's pc, and did not find a register
    // location for PC above in the UnwindPlan.  Check if we have a
    // Return Address register on this target.
    //
    // On a Return Address Register architecture like arm/mips/riscv,
    // the caller's pc is in the RA register, and will be spilled to
    // stack before any other function is called.  If no function
    // has been called yet, the return address may still be in the
    // live RA reg.
    //
    // There's a lot of variety of what we might see in an UnwindPlan.
    // We may have
    //   ra=IsSame {unncessary}
    //   ra=StackAddr {caller's return addr spilled to stack}
    // or no reg location for pc or ra at all, in a frameless function -
    // the caller's return address is in live ra reg.
    //
    // If a function has been interrupted in a non-call way --
    // async signal/sigtramp, or a hardware exception / interrupt / fault --
    // then the "pc" and "ra" are two distinct values, and must be
    // handled separately.  The "pc" is the pc value at the point
    // the function was interrupted.  The "ra" is the return address
    // register value at that point.
    // The UnwindPlan for the sigtramp/trap handler will normally have
    // register loations for both pc and lr, and so we'll have already
    // fetched them above.
    if (pc_regnum.IsValid() && pc_regnum == regnum) {
      uint32_t return_address_regnum = LLDB_INVALID_REGNUM;

      // Get the return address register number from the UnwindPlan
      // or the register set definition.
      if (m_full_unwind_plan_sp->GetReturnAddressRegister() !=
          LLDB_INVALID_REGNUM) {
        return_address_regnum =
            m_full_unwind_plan_sp->GetReturnAddressRegister();
      } else {
        RegisterNumber arch_default_ra_regnum(m_thread, eRegisterKindGeneric,
                                              LLDB_REGNUM_GENERIC_RA);
        return_address_regnum = arch_default_ra_regnum.GetAsKind(kind);
      }

      // This system is using a return address register.
      if (return_address_regnum != LLDB_INVALID_REGNUM) {
        RegisterNumber return_address_reg;
        return_address_reg.init(m_thread,
                                m_full_unwind_plan_sp->GetRegisterKind(),
                                return_address_regnum);
        UNWIND_LOG(log,
                   "requested caller's saved PC but this UnwindPlan uses a RA "
                   "reg; getting {0} ({1}) instead",
                   return_address_reg.GetName(),
                   return_address_reg.GetAsKind(eRegisterKindLLDB));

        // Do we have a location for the ra register?
        if (active_row &&
            active_row->GetRegisterInfo(return_address_reg.GetAsKind(kind),
                                        unwindplan_regloc)) {
          UNWIND_LOG(log,
                     "supplying caller's saved {0} ({1})'s location using {2} "
                     "UnwindPlan",
                     return_address_reg.GetName(),
                     return_address_reg.GetAsKind(eRegisterKindLLDB),
                     m_full_unwind_plan_sp->GetSourceName());
          // If we have "ra=IsSame", rewrite to "ra=InRegister(ra)" because the
          // calling function thinks it is fetching "pc" and if we return an
          // IsSame register location, it will try to read pc.
          if (unwindplan_regloc.IsSame())
            unwindplan_regloc.SetInRegister(return_address_reg.GetAsKind(kind));
          return unwindplan_regloc;
        } else {
          // No unwind rule for the return address reg on frame 0, or an
          // interrupted function, means that the caller's address is still in
          // RA reg (0th frame) or the trap handler below this one (sigtramp
          // etc) has a save location for the RA reg.
          if (BehavesLikeZerothFrame()) {
            unwindplan_regloc.SetInRegister(return_address_reg.GetAsKind(kind));
            return unwindplan_regloc;
          }
        }
      }
    }
    if (active_row && active_row->GetUnspecifiedRegistersAreUndefined()) {
      UNWIND_LOG(
          log,
          "marking register {0} ({1}) as Undefined (volatile) in this "
          "stack frame because this row is UnspecifiedRegistersAreUndefined.",
          regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
      unwindplan_regloc.SetUndefined();
      return unwindplan_regloc;
    }
  }

  ExecutionContext exe_ctx(m_thread.shared_from_this());
  Process *process = exe_ctx.GetProcessPtr();

  // Third, try finding a register location via the ABI
  // FallbackRegisterLocation.
  //
  // If the UnwindPlan failed to give us an unwind location for this
  // register, we may be able to fall back to some ABI-defined default.  For
  // example, some ABIs allow to determine the caller's SP via the CFA. Also,
  // the ABI willset volatile registers to the undefined state.
  ABI *abi = process ? process->GetABI().get() : nullptr;
  if (abi) {
    const RegisterInfo *reg_info =
        GetRegisterInfoAtIndex(regnum.GetAsKind(eRegisterKindLLDB));
    if (reg_info &&
        abi->GetFallbackRegisterLocation(reg_info, unwindplan_regloc)) {
      if (!unwindplan_regloc.IsUndefined())
        UNWIND_LOG(
            log,
            "supplying caller's saved {0} ({1})'s location using ABI default",
            regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
      // ABI defined volatile registers with no register location
      // will be returned as IsUndefined, stopping the search down
      // the stack.
      return unwindplan_regloc;
    }
  }

  // We have no AbstractRegisterLocation, and the ABI says this is a
  // non-volatile / callee-preserved register.  Continue down the stack
  // or to frame 0 & the live RegisterContext.
  std::string unwindplan_name;
  if (m_full_unwind_plan_sp) {
    unwindplan_name += "via '";
    unwindplan_name += m_full_unwind_plan_sp->GetSourceName().AsCString("");
    unwindplan_name += "'";
  }
  UNWIND_LOG(log, "no save location for {0} ({1}) {2}", regnum.GetName(),
             regnum.GetAsKind(eRegisterKindLLDB), unwindplan_name);

  unwindplan_regloc.SetSame();
  return unwindplan_regloc;
}

// Answer the question: Where did THIS frame save the CALLER frame ("previous"
// frame)'s register value?

enum UnwindLLDB::RegisterSearchResult
RegisterContextUnwind::SavedLocationForRegister(
    uint32_t lldb_regnum,
    lldb_private::UnwindLLDB::ConcreteRegisterLocation &regloc) {
  RegisterNumber regnum(m_thread, eRegisterKindLLDB, lldb_regnum);
  Log *log = GetLog(LLDBLog::Unwind);

  // Have we already found this register location?
  if (!m_registers.empty()) {
    auto iterator = m_registers.find(regnum.GetAsKind(eRegisterKindLLDB));
    if (iterator != m_registers.end()) {
      regloc = iterator->second;
      UNWIND_LOG(log, "supplying caller's saved {0} ({1})'s location, cached",
                 regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
      return UnwindLLDB::RegisterSearchResult::eRegisterFound;
    }
  }

  RegisterKind abs_regkind;
  std::optional<UnwindPlan::Row::AbstractRegisterLocation> abs_regloc =
      GetAbstractRegisterLocation(lldb_regnum, abs_regkind);

  if (!abs_regloc)
    return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;

  if (abs_regloc->IsUndefined()) {
    UNWIND_LOG(
        log, "did not supply reg location for {0} ({1}) because it is volatile",
        regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
    return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
  }

  ExecutionContext exe_ctx(m_thread.shared_from_this());
  Process *process = exe_ctx.GetProcessPtr();
  // abs_regloc has valid contents about where to retrieve the register
  if (abs_regloc->IsUnspecified()) {
    lldb_private::UnwindLLDB::ConcreteRegisterLocation new_regloc = {};
    new_regloc.type = UnwindLLDB::ConcreteRegisterLocation::eRegisterNotSaved;
    m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc;
    UNWIND_LOG(log,
               "save location for {0} ({1}) is unspecified, continue searching",
               regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
    return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
  }

  if (abs_regloc->IsSame()) {
    if (IsFrameZero()) {
      regloc.type =
          UnwindLLDB::ConcreteRegisterLocation::eRegisterInLiveRegisterContext;
      regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB);
      m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
      UNWIND_LOG(log,
                 "supplying caller's register {0} ({1}) from the live "
                 "RegisterContext at frame 0",
                 regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
      return UnwindLLDB::RegisterSearchResult::eRegisterFound;
    }
    // PC/RA reg don't follow the usual "callee-saved aka non-volatile" versus
    // "caller saved aka volatile" system.  A stack frame can provide its caller
    // return address, but if we don't find a rule for pc/RA mid-stack, we
    // never want to iterate further down the stack looking for it.
    // Defensively prevent iterating down the stack for these two.
    if (!BehavesLikeZerothFrame() &&
        (regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_PC ||
         regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_RA)) {
      UNWIND_LOG(log,
                 "register {0} ({1}) is marked as 'IsSame' - it is a pc or "
                 "return address reg on a frame which does not have all "
                 "registers available -- treat as if we have no information",
                 regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
      return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
    }

    regloc.type = UnwindLLDB::ConcreteRegisterLocation::eRegisterInRegister;
    regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB);
    m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
    UNWIND_LOG(log,
               "supplying caller's register {0} ({1}) value is unmodified in "
               "this frame",
               regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
  }

  if (abs_regloc->IsCFAPlusOffset()) {
    int offset = abs_regloc->GetOffset();
    regloc.type = UnwindLLDB::ConcreteRegisterLocation::eRegisterValueInferred;
    regloc.location.inferred_value = m_cfa + offset;
    m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
    UNWIND_LOG(log,
               "supplying caller's register {0} ({1}), value is CFA plus "
               "offset {2} [value is {3:x}]",
               regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
               regloc.location.inferred_value);
    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
  }

  if (abs_regloc->IsAtCFAPlusOffset()) {
    int offset = abs_regloc->GetOffset();
    regloc.type =
        UnwindLLDB::ConcreteRegisterLocation::eRegisterSavedAtMemoryLocation;
    regloc.location.target_memory_location = m_cfa + offset;
    m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
    UNWIND_LOG(log,
               "supplying caller's register {0} ({1}) from the stack, saved at "
               "CFA plus offset {2} [saved at {3:x}]",
               regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
               regloc.location.target_memory_location);
    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
  }

  if (abs_regloc->IsAFAPlusOffset()) {
    if (m_afa == LLDB_INVALID_ADDRESS)
        return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;

    int offset = abs_regloc->GetOffset();
    regloc.type = UnwindLLDB::ConcreteRegisterLocation::eRegisterValueInferred;
    regloc.location.inferred_value = m_afa + offset;
    m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
    UNWIND_LOG(log,
               "supplying caller's register {0} ({1}), value is AFA plus "
               "offset {2} [value is {3:x}]",
               regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
               regloc.location.inferred_value);
    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
  }

  if (abs_regloc->IsAtAFAPlusOffset()) {
    if (m_afa == LLDB_INVALID_ADDRESS)
        return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;

    int offset = abs_regloc->GetOffset();
    regloc.type =
        UnwindLLDB::ConcreteRegisterLocation::eRegisterSavedAtMemoryLocation;
    regloc.location.target_memory_location = m_afa + offset;
    m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
    UNWIND_LOG(log,
               "supplying caller's register {0} ({1}) from the stack, saved at "
               "AFA plus offset {2} [saved at {3:x}]",
               regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
               regloc.location.target_memory_location);
    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
  }

  if (abs_regloc->IsInOtherRegister()) {
    RegisterNumber row_regnum(m_thread, abs_regkind,
                              abs_regloc->GetRegisterNumber());
    if (row_regnum.GetAsKind(eRegisterKindLLDB) == LLDB_INVALID_REGNUM) {
      UNWIND_LOG(log,
                 "could not supply caller's {0} ({1}) location - was saved in "
                 "another reg but couldn't convert that regnum",
                 regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
      return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
    }
    regloc.type = UnwindLLDB::ConcreteRegisterLocation::eRegisterInRegister;
    regloc.location.register_number = row_regnum.GetAsKind(eRegisterKindLLDB);
    m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
    UNWIND_LOG(
        log,
        "supplying caller's register {0} ({1}), saved in register {2} ({3})",
        regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB),
        row_regnum.GetName(), row_regnum.GetAsKind(eRegisterKindLLDB));
    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
  }

  if (abs_regloc->IsDWARFExpression() || abs_regloc->IsAtDWARFExpression()) {
    DataExtractor dwarfdata(abs_regloc->GetDWARFExpressionBytes(),
                            abs_regloc->GetDWARFExpressionLength(),
                            process->GetByteOrder(),
                            process->GetAddressByteSize());
    ModuleSP opcode_ctx;
    DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr);
    dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind(abs_regkind);
    Value cfa_val = Scalar(m_cfa);
    cfa_val.SetValueType(Value::ValueType::LoadAddress);
    llvm::Expected<Value> result =
        dwarfexpr.Evaluate(&exe_ctx, this, 0, &cfa_val, nullptr);
    if (!result) {
      LLDB_LOG_ERROR(log, result.takeError(),
                     "DWARF expression failed to evaluate: {0}");
    } else {
      addr_t val;
      val = result->GetScalar().ULongLong();
      if (abs_regloc->IsDWARFExpression()) {
        regloc.type =
            UnwindLLDB::ConcreteRegisterLocation::eRegisterValueInferred;
        regloc.location.inferred_value = val;
        m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
        UNWIND_LOG(log,
                   "supplying caller's register {0} ({1}) via DWARF expression "
                   "(IsDWARFExpression)",
                   regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
        return UnwindLLDB::RegisterSearchResult::eRegisterFound;
      } else {
        regloc.type = UnwindLLDB::ConcreteRegisterLocation::
            eRegisterSavedAtMemoryLocation;
        regloc.location.target_memory_location = val;
        m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
        UNWIND_LOG(log,
                   "supplying caller's register {0} ({1}) via DWARF expression "
                   "(IsAtDWARFExpression)",
                   regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
        return UnwindLLDB::RegisterSearchResult::eRegisterFound;
      }
    }
    UNWIND_LOG(log,
               "tried to use IsDWARFExpression or IsAtDWARFExpression for {0} "
               "({1}) but failed",
               regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
    return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
  }

  if (abs_regloc->IsConstant()) {
    regloc.type = UnwindLLDB::ConcreteRegisterLocation::eRegisterValueInferred;
    regloc.location.inferred_value = abs_regloc->GetConstant();
    m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
    UNWIND_LOG(log, "supplying caller's register {0} ({1}) via constant value",
               regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
  }

  UNWIND_LOG(log, "no save location for {0} ({1}) in this stack frame",
             regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));

  // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are
  // unsupported.

  return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}

UnwindPlanSP RegisterContextUnwind::TryAdoptArchitectureUnwindPlan() {
  if (!m_full_unwind_plan_sp)
    return {};
  ProcessSP process_sp = m_thread.GetProcess();
  if (!process_sp)
    return {};

  UnwindPlanSP arch_override_plan_sp;
  if (Architecture *arch = process_sp->GetTarget().GetArchitecturePlugin())
    arch_override_plan_sp =
        arch->GetArchitectureUnwindPlan(m_thread, this, m_full_unwind_plan_sp);

  if (arch_override_plan_sp) {
    m_full_unwind_plan_sp = arch_override_plan_sp;
    PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
    m_registers.clear();
    if (Log *log = GetLog(LLDBLog::Unwind)) {
      UNWIND_LOG(
          log, "Replacing Full Unwindplan with Architecture UnwindPlan, '{0}'",
          m_full_unwind_plan_sp->GetSourceName());
      const UnwindPlan::Row *active_row =
          m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);
      if (active_row) {
        StreamString active_row_strm;
        active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(),
                         &m_thread,
                         m_start_pc.GetLoadAddress(&process_sp->GetTarget()));
        UNWIND_LOG(log, "{0}", active_row_strm.GetString());
      }
    }
  }

  return {};
}

// TryFallbackUnwindPlan() -- this method is a little tricky.
//
// When this is called, the frame above -- the caller frame, the "previous"
// frame -- is invalid or bad.
//
// Instead of stopping the stack walk here, we'll try a different UnwindPlan
// and see if we can get a valid frame above us.
//
// This most often happens when an unwind plan based on assembly instruction
// inspection is not correct -- mostly with hand-written assembly functions or
// functions where the stack frame is set up "out of band", e.g. the kernel
// saved the register context and then called an asynchronous trap handler like
// _sigtramp.
//
// Often in these cases, if we just do a dumb stack walk we'll get past this
// tricky frame and our usual techniques can continue to be used.

bool RegisterContextUnwind::TryFallbackUnwindPlan() {
  if (m_fallback_unwind_plan_sp == nullptr)
    return false;

  if (m_full_unwind_plan_sp == nullptr)
    return false;

  if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() ||
      m_full_unwind_plan_sp->GetSourceName() ==
          m_fallback_unwind_plan_sp->GetSourceName()) {
    return false;
  }

  // If a compiler generated unwind plan failed, trying the arch default
  // unwindplan isn't going to do any better.
  if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes)
    return false;

  // Get the caller's pc value and our own CFA value. Swap in the fallback
  // unwind plan, re-fetch the caller's pc value and CFA value. If they're the
  // same, then the fallback unwind plan provides no benefit.

  RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric,
                           LLDB_REGNUM_GENERIC_PC);

  addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS;
  addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS;
  UnwindLLDB::ConcreteRegisterLocation regloc = {};
  if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
                               regloc) ==
      UnwindLLDB::RegisterSearchResult::eRegisterFound) {
    const RegisterInfo *reg_info =
        GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB));
    if (reg_info) {
      RegisterValue reg_value;
      if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
        old_caller_pc_value = reg_value.GetAsUInt64();
        if (ProcessSP process_sp = m_thread.GetProcess()) {
          if (ABISP abi_sp = process_sp->GetABI())
            old_caller_pc_value = abi_sp->FixCodeAddress(old_caller_pc_value);
        }
      }
    }
  }

  // This is a tricky wrinkle!  If SavedLocationForRegister() detects a really
  // impossible register location for the full unwind plan, it may call
  // ForceSwitchToFallbackUnwindPlan() which in turn replaces the full
  // unwindplan with the fallback... in short, we're done, we're using the
  // fallback UnwindPlan. We checked if m_fallback_unwind_plan_sp was nullptr
  // at the top -- the only way it became nullptr since then is via
  // SavedLocationForRegister().
  if (m_fallback_unwind_plan_sp == nullptr)
    return true;

  // Switch the full UnwindPlan to be the fallback UnwindPlan.  If we decide
  // this isn't working, we need to restore. We'll also need to save & restore
  // the value of the m_cfa ivar.  Save is down below a bit in 'old_cfa'.
  std::shared_ptr<const UnwindPlan> original_full_unwind_plan_sp =
      m_full_unwind_plan_sp;
  addr_t old_cfa = m_cfa;
  addr_t old_afa = m_afa;

  m_registers.clear();

  m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;

  const UnwindPlan::Row *active_row =
      m_fallback_unwind_plan_sp->GetRowForFunctionOffset(
          m_current_offset_backed_up_one);

  Log *log = GetLog(LLDBLog::Unwind);
  if (active_row &&
      active_row->GetCFAValue().GetValueType() !=
          UnwindPlan::Row::FAValue::unspecified) {
    addr_t new_cfa;
    ProcessSP process_sp = m_thread.GetProcess();
    ABISP abi_sp = process_sp ? process_sp->GetABI() : nullptr;
    if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
                          active_row->GetCFAValue(), new_cfa) ||
        !CallFrameAddressIsValid(abi_sp, new_cfa)) {
      UNWIND_LOG(log, "failed to get cfa with fallback unwindplan");
      m_fallback_unwind_plan_sp.reset();
      m_full_unwind_plan_sp = original_full_unwind_plan_sp;
      return false;
    }
    m_cfa = new_cfa;

    ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
                     active_row->GetAFAValue(), m_afa);

    if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
                                 regloc) ==
        UnwindLLDB::RegisterSearchResult::eRegisterFound) {
      const RegisterInfo *reg_info =
          GetRegisterInfoAtIndex(pc_regnum.GetAsKind(eRegisterKindLLDB));
      if (reg_info) {
        RegisterValue reg_value;
        if (ReadRegisterValueFromRegisterLocation(regloc, reg_info,
                                                  reg_value)) {
          new_caller_pc_value = reg_value.GetAsUInt64();
          if (process_sp)
            new_caller_pc_value =
                process_sp->FixCodeAddress(new_caller_pc_value);
        }
      }
    }

    if (new_caller_pc_value == LLDB_INVALID_ADDRESS) {
      UNWIND_LOG(log, "failed to get a pc value for the caller frame with the "
                      "fallback unwind plan");
      m_fallback_unwind_plan_sp.reset();
      m_full_unwind_plan_sp = original_full_unwind_plan_sp;
      m_cfa = old_cfa;
      m_afa = old_afa;
      return false;
    }

    if (old_caller_pc_value == new_caller_pc_value &&
        m_cfa == old_cfa &&
        m_afa == old_afa) {
      UNWIND_LOG(log, "fallback unwind plan got the same values for this frame "
                      "CFA and caller frame pc, not using");
      m_fallback_unwind_plan_sp.reset();
      m_full_unwind_plan_sp = original_full_unwind_plan_sp;
      return false;
    }

    UNWIND_LOG(log,
               "trying to unwind from this function with the UnwindPlan '{0}' "
               "because UnwindPlan '{1}' failed.",
               m_fallback_unwind_plan_sp->GetSourceName(),
               original_full_unwind_plan_sp->GetSourceName());

    // We've copied the fallback unwind plan into the full - now clear the
    // fallback.
    m_fallback_unwind_plan_sp.reset();
    PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);
  }

  return true;
}

bool RegisterContextUnwind::ForceSwitchToFallbackUnwindPlan() {
  if (m_fallback_unwind_plan_sp == nullptr)
    return false;

  if (m_full_unwind_plan_sp == nullptr)
    return false;

  if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() ||
      m_full_unwind_plan_sp->GetSourceName() ==
          m_fallback_unwind_plan_sp->GetSourceName()) {
    return false;
  }

  const UnwindPlan::Row *active_row =
      m_fallback_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset);

  if (active_row &&
      active_row->GetCFAValue().GetValueType() !=
          UnwindPlan::Row::FAValue::unspecified) {
    addr_t new_cfa;
    ProcessSP process_sp = m_thread.GetProcess();
    ABISP abi_sp = process_sp ? process_sp->GetABI() : nullptr;
    if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
                          active_row->GetCFAValue(), new_cfa) ||
        !CallFrameAddressIsValid(abi_sp, new_cfa)) {
      UNWIND_LOG(GetLog(LLDBLog::Unwind),
                 "failed to get cfa with fallback unwindplan");
      m_fallback_unwind_plan_sp.reset();
      return false;
    }

    ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
                     active_row->GetAFAValue(), m_afa);

    m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
    m_fallback_unwind_plan_sp.reset();

    m_registers.clear();

    m_cfa = new_cfa;

    PropagateTrapHandlerFlagFromUnwindPlan(m_full_unwind_plan_sp);

    UNWIND_LOG(GetLog(LLDBLog::Unwind),
               "switched unconditionally to the fallback unwindplan {0}",
               m_full_unwind_plan_sp->GetSourceName());
    return true;
  }
  return false;
}

void RegisterContextUnwind::PropagateTrapHandlerFlagFromUnwindPlan(
    std::shared_ptr<const UnwindPlan> unwind_plan) {
  if (unwind_plan->GetUnwindPlanForSignalTrap() != eLazyBoolYes) {
    // Unwind plan does not indicate trap handler.  Do nothing.  We may
    // already be flagged as trap handler flag due to the symbol being
    // in the trap handler symbol list, and that should take precedence.
    return;
  } else if (m_frame_type != eNormalFrame) {
    // If this is already a trap handler frame, nothing to do.
    // If this is a skip or debug or invalid frame, don't override that.
    return;
  }

  m_frame_type = eTrapHandlerFrame;

  Log *log = GetLog(LLDBLog::Unwind);
  UNWIND_LOG(log, "This frame is marked as a trap handler via its UnwindPlan");

  if (m_current_offset_backed_up_one != m_current_offset) {
    // We backed up the pc by 1 to compute the symbol context, but
    // now need to undo that because the pc of the trap handler
    // frame may in fact be the first instruction of a signal return
    // trampoline, rather than the instruction after a call.  This
    // happens on systems where the signal handler dispatch code, rather
    // than calling the handler and being returned to, jumps to the
    // handler after pushing the address of a return trampoline on the
    // stack -- on these systems, when the handler returns, control will
    // be transferred to the return trampoline, so that's the best
    // symbol we can present in the callstack.
    UNWIND_LOG(log,
               "Resetting current offset and re-doing symbol lookup; old "
               "symbol was {0}",
               GetSymbolOrFunctionName(m_sym_ctx));
    m_current_offset_backed_up_one = m_current_offset;

    m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx);

    UNWIND_LOG(log, "Symbol is now {0}", GetSymbolOrFunctionName(m_sym_ctx));

    ExecutionContext exe_ctx(m_thread.shared_from_this());
    Process *process = exe_ctx.GetProcessPtr();
    Target *target = &process->GetTarget();

    if (m_sym_ctx_valid) {
      m_start_pc = m_sym_ctx.GetFunctionOrSymbolAddress();
      m_current_offset = m_current_pc.GetLoadAddress(target) -
                         m_start_pc.GetLoadAddress(target);
    }
  }
}

bool RegisterContextUnwind::ReadFrameAddress(
    lldb::RegisterKind row_register_kind, const UnwindPlan::Row::FAValue &fa,
    addr_t &address) {
  RegisterValue reg_value;

  address = LLDB_INVALID_ADDRESS;
  addr_t cfa_reg_contents;
  ABISP abi_sp = m_thread.GetProcess()->GetABI();

  Log *log = GetLog(LLDBLog::Unwind);
  switch (fa.GetValueType()) {
  case UnwindPlan::Row::FAValue::isRegisterDereferenced: {
    UNWIND_LOG(log, "CFA value via dereferencing reg");
    RegisterNumber regnum_to_deref(m_thread, row_register_kind,
                                   fa.GetRegisterNumber());
    addr_t reg_to_deref_contents;
    if (ReadGPRValue(regnum_to_deref, reg_to_deref_contents)) {
      const RegisterInfo *reg_info =
          GetRegisterInfoAtIndex(regnum_to_deref.GetAsKind(eRegisterKindLLDB));
      RegisterValue reg_value;
      if (reg_info) {
        Status error = ReadRegisterValueFromMemory(
            reg_info, reg_to_deref_contents, reg_info->byte_size, reg_value);
        if (error.Success()) {
          address = reg_value.GetAsUInt64();
          UNWIND_LOG(log,
                     "CFA value via dereferencing reg {0} ({1}): reg has val "
                     "{2:x}, CFA value is {3:x}",
                     regnum_to_deref.GetName(),
                     regnum_to_deref.GetAsKind(eRegisterKindLLDB),
                     reg_to_deref_contents, address);
          return true;
        } else {
          UNWIND_LOG(
              log,
              "Tried to deref reg {0} ({1}) [{2:x}] but memory read failed.",
              regnum_to_deref.GetName(),
              regnum_to_deref.GetAsKind(eRegisterKindLLDB),
              reg_to_deref_contents);
        }
      }
    }
    break;
  }
  case UnwindPlan::Row::FAValue::isRegisterPlusOffset: {
    UNWIND_LOG(log, "CFA value via register plus offset");
    RegisterNumber cfa_reg(m_thread, row_register_kind,
                           fa.GetRegisterNumber());
    if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
      if (!CallFrameAddressIsValid(abi_sp, cfa_reg_contents)) {
        UNWIND_LOG(
            log,
            "Got an invalid CFA register value - reg {0} ({1}), value {2:x}",
            cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
            cfa_reg_contents);
        return false;
      }
      address = cfa_reg_contents + fa.GetOffset();
      UNWIND_LOG(
          log,
          "CFA is {0:x}: Register {1} ({2}) contents are {3:x}, offset is {4}",
          address, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
          cfa_reg_contents, fa.GetOffset());
      return true;
    }
    UNWIND_LOG(log, "unable to read CFA register {0} ({1})", cfa_reg.GetName(),
               cfa_reg.GetAsKind(eRegisterKindLLDB));
    break;
  }
  case UnwindPlan::Row::FAValue::isDWARFExpression: {
    UNWIND_LOG(log, "CFA value via DWARF expression");
    ExecutionContext exe_ctx(m_thread.shared_from_this());
    Process *process = exe_ctx.GetProcessPtr();
    DataExtractor dwarfdata(fa.GetDWARFExpressionBytes(),
                            fa.GetDWARFExpressionLength(),
                            process->GetByteOrder(),
                            process->GetAddressByteSize());
    ModuleSP opcode_ctx;
    DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr);
    dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind(
        row_register_kind);
    llvm::Expected<Value> result =
        dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr);
    if (result) {
      address = result->GetScalar().ULongLong();
      UNWIND_LOG(log, "CFA value set by DWARF expression is {0:x}", address);
      return true;
    }
    LLDB_LOG_ERROR(log, result.takeError(),
                   "Failed to set CFA value via DWARF expression: {0}");
    break;
  }
  case UnwindPlan::Row::FAValue::isRaSearch: {
    UNWIND_LOG(log, "CFA value via heuristic search");
    Process &process = *m_thread.GetProcess();
    lldb::addr_t return_address_hint = GetReturnAddressHint(fa.GetOffset());
    if (return_address_hint == LLDB_INVALID_ADDRESS)
      return false;
    const unsigned max_iterations = 256;
    for (unsigned i = 0; i < max_iterations; ++i) {
      Status st;
      lldb::addr_t candidate_addr =
          return_address_hint + i * process.GetAddressByteSize();
      lldb::addr_t candidate =
          process.ReadPointerFromMemory(candidate_addr, st);
      if (st.Fail()) {
        UNWIND_LOG(log, "Cannot read memory at {0:x}: {1}", candidate_addr, st);
        return false;
      }
      Address addr;
      uint32_t permissions;
      if (process.GetLoadAddressPermissions(candidate, permissions) &&
          permissions & lldb::ePermissionsExecutable) {
        address = candidate_addr;
        UNWIND_LOG(log, "Heuristically found CFA: {0:x}", address);
        return true;
      }
    }
    UNWIND_LOG(log, "No suitable CFA found");
    break;
  }
  case UnwindPlan::Row::FAValue::isConstant: {
    address = fa.GetConstant();
    UNWIND_LOG(log, "CFA value set by constant is {0:x}", address);
    return true;
  }
  default:
    return false;
  }
  return false;
}

lldb::addr_t RegisterContextUnwind::GetReturnAddressHint(int32_t plan_offset) {
  addr_t hint;
  if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, hint))
    return LLDB_INVALID_ADDRESS;
  if (!m_sym_ctx.module_sp || !m_sym_ctx.symbol)
    return LLDB_INVALID_ADDRESS;
  if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
    hint = abi_sp->FixCodeAddress(hint);

  hint += plan_offset;

  if (auto next = GetNextFrame()) {
    if (!next->m_sym_ctx.module_sp || !next->m_sym_ctx.symbol)
      return LLDB_INVALID_ADDRESS;
    if (auto expected_size =
            next->m_sym_ctx.module_sp->GetSymbolFile()->GetParameterStackSize(
                *next->m_sym_ctx.symbol))
      hint += *expected_size;
    else {
      LLDB_LOG_ERRORV(GetLog(LLDBLog::Unwind), expected_size.takeError(),
                      "Could not retrieve parameter size: {0}");
      return LLDB_INVALID_ADDRESS;
    }
  }
  return hint;
}

// Retrieve a general purpose register value for THIS frame, as saved by the
// NEXT frame, i.e. the frame that
// this frame called.  e.g.
//
//  foo () { }
//  bar () { foo (); }
//  main () { bar (); }
//
//  stopped in foo() so
//     frame 0 - foo
//     frame 1 - bar
//     frame 2 - main
//  and this RegisterContext is for frame 1 (bar) - if we want to get the pc
//  value for frame 1, we need to ask
//  where frame 0 (the "next" frame) saved that and retrieve the value.

bool RegisterContextUnwind::ReadGPRValue(lldb::RegisterKind register_kind,
                                         uint32_t regnum, addr_t &value) {
  if (!IsValid())
    return false;

  uint32_t lldb_regnum;
  if (register_kind == eRegisterKindLLDB) {
    lldb_regnum = regnum;
  } else if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
                 register_kind, regnum, eRegisterKindLLDB, lldb_regnum)) {
    return false;
  }

  const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
  assert(reg_info);
  if (!reg_info) {
    UNWIND_LOG(
        GetLog(LLDBLog::Unwind),
        "Could not find RegisterInfo definition for lldb register number {0}",
        lldb_regnum);
    return false;
  }

  uint32_t generic_regnum = LLDB_INVALID_REGNUM;
  if (register_kind == eRegisterKindGeneric)
    generic_regnum = regnum;
  else
    m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds(
        register_kind, regnum, eRegisterKindGeneric, generic_regnum);
  ABISP abi_sp = m_thread.GetProcess()->GetABI();

  RegisterValue reg_value;
  // if this is frame 0 (currently executing frame), get the requested reg
  // contents from the actual thread registers
  if (IsFrameZero()) {
    if (m_thread.GetRegisterContext()->ReadRegister(reg_info, reg_value)) {
      value = reg_value.GetAsUInt64();
      if (abi_sp && generic_regnum != LLDB_INVALID_REGNUM) {
        if (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
            generic_regnum == LLDB_REGNUM_GENERIC_RA)
          value = abi_sp->FixCodeAddress(value);
      }
      return true;
    }
    return false;
  }

  bool pc_register = false;
  if (generic_regnum != LLDB_INVALID_REGNUM &&
      (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
       generic_regnum == LLDB_REGNUM_GENERIC_RA))
    pc_register = true;

  lldb_private::UnwindLLDB::ConcreteRegisterLocation regloc;
  if (!m_parent_unwind.SearchForSavedLocationForRegister(
          lldb_regnum, regloc, m_frame_number - 1, pc_register)) {
    return false;
  }
  if (ReadRegisterValueFromRegisterLocation(regloc, reg_info, reg_value)) {
    value = reg_value.GetAsUInt64();
    if (pc_register) {
      if (ABISP abi_sp = m_thread.GetProcess()->GetABI()) {
        value = abi_sp->FixCodeAddress(value);
      }
    }
    return true;
  }
  return false;
}

bool RegisterContextUnwind::ReadGPRValue(const RegisterNumber &regnum,
                                         addr_t &value) {
  return ReadGPRValue(regnum.GetRegisterKind(), regnum.GetRegisterNumber(),
                      value);
}

// Find the value of a register in THIS frame

bool RegisterContextUnwind::ReadRegister(const RegisterInfo *reg_info,
                                         RegisterValue &value) {
  if (!IsValid())
    return false;

  const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
  Log *log = GetLog(LLDBLog::Unwind);
  UNWIND_LOG_VERBOSE(log, "looking for register saved location for reg {0}",
                     lldb_regnum);

  // If this is the 0th frame, hand this over to the live register context
  if (IsFrameZero()) {
    UNWIND_LOG_VERBOSE(log,
                       "passing along to the live register context for reg {0}",
                       lldb_regnum);
    return m_thread.GetRegisterContext()->ReadRegister(reg_info, value);
  }

  bool is_pc_regnum = false;
  if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC ||
      reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA) {
    is_pc_regnum = true;
  }

  lldb_private::UnwindLLDB::ConcreteRegisterLocation regloc;
  // Find out where the NEXT frame saved THIS frame's register contents
  if (!m_parent_unwind.SearchForSavedLocationForRegister(
          lldb_regnum, regloc, m_frame_number - 1, is_pc_regnum))
    return false;

  bool result = ReadRegisterValueFromRegisterLocation(regloc, reg_info, value);
  if (result) {
    if (is_pc_regnum && value.GetType() == RegisterValue::eTypeUInt64) {
      addr_t reg_value = value.GetAsUInt64(LLDB_INVALID_ADDRESS);
      if (reg_value != LLDB_INVALID_ADDRESS) {
        if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
          value = abi_sp->FixCodeAddress(reg_value);
      }
    }
  }
  return result;
}

bool RegisterContextUnwind::WriteRegister(const RegisterInfo *reg_info,
                                          const RegisterValue &value) {
  if (!IsValid())
    return false;

  const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
  Log *log = GetLog(LLDBLog::Unwind);
  UNWIND_LOG_VERBOSE(log, "looking for register saved location for reg {0}",
                     lldb_regnum);

  // If this is the 0th frame, hand this over to the live register context
  if (IsFrameZero()) {
    UNWIND_LOG_VERBOSE(log,
                       "passing along to the live register context for reg {0}",
                       lldb_regnum);
    return m_thread.GetRegisterContext()->WriteRegister(reg_info, value);
  }

  lldb_private::UnwindLLDB::ConcreteRegisterLocation regloc;
  // Find out where the NEXT frame saved THIS frame's register contents
  if (!m_parent_unwind.SearchForSavedLocationForRegister(
          lldb_regnum, regloc, m_frame_number - 1, false))
    return false;

  return WriteRegisterValueToRegisterLocation(regloc, reg_info, value);
}

// Don't need to implement this one
bool RegisterContextUnwind::ReadAllRegisterValues(
    lldb::WritableDataBufferSP &data_sp) {
  return false;
}

// Don't need to implement this one
bool RegisterContextUnwind::WriteAllRegisterValues(
    const lldb::DataBufferSP &data_sp) {
  return false;
}

// Retrieve the pc value for THIS from

bool RegisterContextUnwind::GetCFA(addr_t &cfa) {
  if (!IsValid()) {
    return false;
  }
  if (m_cfa == LLDB_INVALID_ADDRESS) {
    return false;
  }
  cfa = m_cfa;
  return true;
}

RegisterContextUnwind::SharedPtr RegisterContextUnwind::GetNextFrame() const {
  RegisterContextUnwind::SharedPtr regctx;
  if (m_frame_number == 0)
    return regctx;
  return m_parent_unwind.GetRegisterContextForFrameNum(m_frame_number - 1);
}

RegisterContextUnwind::SharedPtr RegisterContextUnwind::GetPrevFrame() const {
  RegisterContextUnwind::SharedPtr regctx;
  return m_parent_unwind.GetRegisterContextForFrameNum(m_frame_number + 1);
}

// Retrieve the address of the start of the function of THIS frame

bool RegisterContextUnwind::GetStartPC(addr_t &start_pc) {
  if (!IsValid())
    return false;

  if (!m_start_pc.IsValid()) {
        bool read_successfully = ReadPC (start_pc);
        if (read_successfully)
        {
            ProcessSP process_sp (m_thread.GetProcess());
            if (process_sp)
            {
              if (ABISP abi_sp = process_sp->GetABI())
                start_pc = abi_sp->FixCodeAddress(start_pc);
            }
        }
        return read_successfully;
  }
  start_pc = m_start_pc.GetLoadAddress(CalculateTarget().get());
  return true;
}

// Retrieve the current pc value for THIS frame, as saved by the NEXT frame.

bool RegisterContextUnwind::ReadPC(addr_t &pc) {
  if (!IsValid())
    return false;

  bool above_trap_handler = false;
  if (GetNextFrame().get() && GetNextFrame()->IsValid() &&
      GetNextFrame()->IsTrapHandlerFrame())
    above_trap_handler = true;

  if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) {
    // A pc value of 0 or 1 is impossible in the middle of the stack -- it
    // indicates the end of a stack walk.
    // On the currently executing frame (or such a frame interrupted
    // asynchronously by sigtramp et al) this may occur if code has jumped
    // through a NULL pointer -- we want to be able to unwind past that frame
    // to help find the bug.

    if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
      pc = abi_sp->FixCodeAddress(pc);

    return !(m_all_registers_available == false &&
             above_trap_handler == false && (pc == 0 || pc == 1));
  } else {
    return false;
  }
}
