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

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(0), m_current_offset_backed_up_one(0),
      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.SetOffset(m_current_pc.GetOffset() - 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;
    UnwindLogMsg("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;
    UnwindLogMsg("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()) {
    UnwindLogMsg("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) {
    UnwindLogMsg("using architectural default unwind method");
  }

  m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx);

  if (m_sym_ctx.symbol) {
    UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'",
                 current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
  } else if (m_sym_ctx.function) {
    UnwindLogMsg("with pc value of 0x%" PRIx64 ", function name is '%s'",
                 current_pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
  } else {
    UnwindLogMsg("with pc value of 0x%" PRIx64
                 ", 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)) {
      UnwindLogMsg("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()));
        UnwindLogMsg("async active row: %s", active_row_strm.GetData());
      }
      UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa);
      UnwindLogMsg(
          "initialized async frame current pc is 0x%" PRIx64
          " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
          (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
          (uint64_t)m_cfa, (uint64_t)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()));
      UnwindLogMsg("%s", active_row_strm.GetData());
    }
  }

  if (!active_row) {
    UnwindLogMsg("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) {
      UnwindLogMsg("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) {
    UnwindLogMsg(
        "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();

  UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64
               " afa is 0x%" PRIx64 " using %s UnwindPlan",
               (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
               (uint64_t)m_cfa,
               (uint64_t)m_afa,
               m_full_unwind_plan_sp->GetSourceName().GetCString());
}

// 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;
    UnwindLogMsg("non-zeroth frame tests positive for IsFrameZero -- that "
                 "shouldn't happen.");
    return;
  }

  if (!GetNextFrame().get() || !GetNextFrame()->IsValid()) {
    m_frame_type = eNotAValidFrame;
    UnwindLogMsg("Could not get next frame, marking this frame as invalid.");
    return;
  }
  if (!m_thread.GetRegisterContext()) {
    m_frame_type = eNotAValidFrame;
    UnwindLogMsg("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()) {
    UnwindLogMsg("This is an async frame");
  }

  addr_t pc;
  if (!ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) {
    UnwindLogMsg("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) {
    UnwindLogMsg("pc = 0x%" PRIx64, pc);
    addr_t reg_val;
    if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
      UnwindLogMsg("fp = 0x%" PRIx64, reg_val);
    if (ReadGPRValue(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
      UnwindLogMsg("sp = 0x%" PRIx64, 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;
      UnwindLogMsg("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) {
    UnwindLogMsg("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()) {
        UnwindLogMsg("had a pc of 0x%" PRIx64 " which is not in executable "
                                              "memory but on frame 1 -- "
                                              "allowing it once.",
                     (uint64_t)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;
        UnwindLogMsg("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();
      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)) {
          UnwindLogMsg("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)) {
          UnwindLogMsg("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;
          UnwindLogMsg(
              "the CFA points to a region of memory that is not readable");
          return;
        }
      } else {
        UnwindLogMsg("could not find a row for function offset zero");
        m_frame_type = eNotAValidFrame;
        return;
      }

      if (CheckIfLoopingStack()) {
        TryFallbackUnwindPlan();
        if (CheckIfLoopingStack()) {
          UnwindLogMsg("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();

      UnwindLogMsg("initialized frame cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
                   (uint64_t)m_cfa, (uint64_t)m_afa);
      return;
    }
    m_frame_type = eNotAValidFrame;
    UnwindLogMsg("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) {
    UnwindLogMsg("with pc value of 0x%" PRIx64 ", symbol name is '%s'", pc,
                 GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
  } else if (m_sym_ctx.function) {
    UnwindLogMsg("with pc value of 0x%" PRIx64 ", function name is '%s'", pc,
                 GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
  } else {
    UnwindLogMsg("with pc value of 0x%" PRIx64
                 ", 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) {
    UnwindLogMsg("Backing up the pc value of 0x%" PRIx64
                 " by 1 and re-doing symbol lookup; old symbol was %s",
                 pc, GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
    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);

    UnwindLogMsg("Symbol is now %s",
                 GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
  }

  // 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)) {
      UnwindLogMsg("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()));
        UnwindLogMsg("async active row: %s", active_row_strm.GetData());
      }
      UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa);
      UnwindLogMsg(
          "initialized async frame current pc is 0x%" PRIx64
          " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
          (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
          (uint64_t)m_cfa, (uint64_t)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()));
      UnwindLogMsg("Using fast unwind plan '%s'",
                   m_fast_unwind_plan_sp->GetSourceName().AsCString());
      UnwindLogMsg("active row: %s", active_row_strm.GetData());
    }
  } 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()));
        UnwindLogMsg("Using full unwind plan '%s'",
                     m_full_unwind_plan_sp->GetSourceName().AsCString());
        UnwindLogMsg("active row: %s", active_row_strm.GetData());
      }
    }
  }

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

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

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

  UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa);

  if (CheckIfLoopingStack()) {
    TryFallbackUnwindPlan();
    if (CheckIfLoopingStack()) {
      UnwindLogMsg("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();

  UnwindLogMsg("initialized frame current pc is 0x%" PRIx64
               " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
               (uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
               (uint64_t)m_cfa,
               (uint64_t)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() {
  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();
  } else {
    UnwindLogMsg(
        "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;
  }

  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();
      if (auto unwind_plan_sp = platform->GetTrapHandlerUnwindPlan(
              process->GetTarget().GetArchitecture().GetTriple(),
              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)) {
      UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because the "
                          "DynamicLoader suggested we prefer it",
                          unwind_plan_sp->GetSourceName().GetCString());
      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;
        }
      }
      UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because this "
                          "is the non-call site unwind plan and this is a "
                          "zeroth frame",
                          unwind_plan_sp->GetSourceName().GetCString());
      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) {
        UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because we are at "
                            "the first instruction of a function",
                            unwind_plan_sp->GetSourceName().GetCString());
        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)) {
    UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because this "
                        "is the call-site unwind plan",
                        unwind_plan_sp->GetSourceName().GetCString());
    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)) {
    UnwindLogMsgVerbose("frame uses %s for full UnwindPlan because we "
                        "failed to find a call-site unwind plan that would work",
                        unwind_plan_sp->GetSourceName().GetCString());
    return unwind_plan_sp;
  }

  // If nothing else, use the architectural default UnwindPlan and hope that
  // does the job.
  if (arch_default_unwind_plan_sp)
    UnwindLogMsgVerbose(
        "frame uses %s for full UnwindPlan because we are falling back "
        "to the arch default plan",
        arch_default_unwind_plan_sp->GetSourceName().GetCString());
  else
    UnwindLogMsg(
        "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) {
      UnwindLogMsg("read (%d)'s location", regnum);
      value = value.GetAsUInt64(~0ull, &success) +
              regloc.location.reg_plus_offset.offset;
      UnwindLogMsg("success %s", 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) {
      UnwindLogMsg("could not convert lldb regnum %s (%d) into %d RegisterKind "
                   "reg numbering scheme",
                   regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB),
                   (int)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()) {
      UnwindLogMsg(
          "supplying caller's saved %s (%d)'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()));
      UnwindLogMsg("Using full unwind plan '%s'",
                   m_full_unwind_plan_sp->GetSourceName().AsCString());
      UnwindLogMsg("active row: %s", active_row_strm.GetData());
    }

    if (regnum.GetAsKind(kind) == LLDB_INVALID_REGNUM) {
      if (kind == eRegisterKindGeneric)
        UnwindLogMsg("could not convert lldb regnum %s (%d) into "
                     "eRegisterKindGeneric reg numbering scheme",
                     regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
      else
        UnwindLogMsg("could not convert lldb regnum %s (%d) into %d "
                     "RegisterKind reg numbering scheme",
                     regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB),
                     (int)kind);
      return {};
    }

    if (regnum.IsValid() && active_row &&
        active_row->GetRegisterInfo(regnum.GetAsKind(kind),
                                    unwindplan_regloc)) {
      UnwindLogMsg(
          "supplying caller's saved %s (%d)'s location using %s UnwindPlan",
          regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB),
          m_full_unwind_plan_sp->GetSourceName().GetCString());
      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);
        UnwindLogMsg("requested caller's saved PC but this UnwindPlan uses a "
                     "RA reg; getting %s (%d) 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)) {
          UnwindLogMsg("supplying caller's saved %s (%d)'s location using "
                       "%s UnwindPlan",
                       return_address_reg.GetName(),
                       return_address_reg.GetAsKind(eRegisterKindLLDB),
                       m_full_unwind_plan_sp->GetSourceName().GetCString());
          // 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;
          }
        }
      }
    }
  }

  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())
        UnwindLogMsg(
            "supplying caller's saved %s (%d)'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 += "'";
  }
  UnwindLogMsg("no save location for %s (%d) %s", regnum.GetName(),
               regnum.GetAsKind(eRegisterKindLLDB), unwindplan_name.c_str());

  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;
      UnwindLogMsg("supplying caller's saved %s (%d)'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()) {
    UnwindLogMsg(
        "did not supply reg location for %s (%d) 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;
    UnwindLogMsg("save location for %s (%d) 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;
      UnwindLogMsg("supplying caller's register %s (%d) 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)) {
      UnwindLogMsg("register %s (%d) 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;
    UnwindLogMsg(
        "supplying caller's register %s (%d) 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;
    UnwindLogMsg("supplying caller's register %s (%d), value is CFA plus "
                 "offset %d [value is 0x%" PRIx64 "]",
                 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;
    UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at "
                 "CFA plus offset %d [saved at 0x%" PRIx64 "]",
                 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;
    UnwindLogMsg("supplying caller's register %s (%d), value is AFA plus "
                 "offset %d [value is 0x%" PRIx64 "]",
                 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;
    UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at "
                 "AFA plus offset %d [saved at 0x%" PRIx64 "]",
                 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) {
      UnwindLogMsg("could not supply caller's %s (%d) 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;
    UnwindLogMsg(
        "supplying caller's register %s (%d), saved in register %s (%d)",
        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;
        UnwindLogMsg("supplying caller's register %s (%d) 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;
        UnwindLogMsg("supplying caller's register %s (%d) via DWARF expression "
                     "(IsAtDWARFExpression)",
                     regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
        return UnwindLLDB::RegisterSearchResult::eRegisterFound;
      }
    }
    UnwindLogMsg("tried to use IsDWARFExpression or IsAtDWARFExpression for %s "
                 "(%d) 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;
    UnwindLogMsg("supplying caller's register %s (%d) via constant value",
                 regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
  }

  UnwindLogMsg("no save location for %s (%d) 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 (GetLog(LLDBLog::Unwind)) {
      UnwindLogMsg(
          "Replacing Full Unwindplan with Architecture UnwindPlan, '%s'",
          m_full_unwind_plan_sp->GetSourceName().AsCString());
      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()));
        UnwindLogMsg("%s", active_row_strm.GetData());
      }
    }
  }

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

  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)) {
      UnwindLogMsg("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) {
      UnwindLogMsg("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) {
      UnwindLogMsg("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;
    }

    UnwindLogMsg("trying to unwind from this function with the UnwindPlan '%s' "
                 "because UnwindPlan '%s' failed.",
                 m_fallback_unwind_plan_sp->GetSourceName().GetCString(),
                 original_full_unwind_plan_sp->GetSourceName().GetCString());

    // 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)) {
      UnwindLogMsg("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);

    UnwindLogMsg("switched unconditionally to the fallback unwindplan %s",
                 m_full_unwind_plan_sp->GetSourceName().GetCString());
    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;
  UnwindLogMsg("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.
    UnwindLogMsg("Resetting current offset and re-doing symbol lookup; "
                 "old symbol was %s",
                 GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
    m_current_offset_backed_up_one = m_current_offset;

    m_sym_ctx_valid = m_current_pc.ResolveFunctionScope(m_sym_ctx);

    UnwindLogMsg("Symbol is now %s",
                 GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));

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

  switch (fa.GetValueType()) {
  case UnwindPlan::Row::FAValue::isRegisterDereferenced: {
    UnwindLogMsg("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();
          UnwindLogMsg(
              "CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64
              ", CFA value is 0x%" PRIx64,
              regnum_to_deref.GetName(),
              regnum_to_deref.GetAsKind(eRegisterKindLLDB),
              reg_to_deref_contents, address);
          return true;
        } else {
          UnwindLogMsg("Tried to deref reg %s (%d) [0x%" PRIx64
                       "] but memory read failed.",
                       regnum_to_deref.GetName(),
                       regnum_to_deref.GetAsKind(eRegisterKindLLDB),
                       reg_to_deref_contents);
        }
      }
    }
    break;
  }
  case UnwindPlan::Row::FAValue::isRegisterPlusOffset: {
    UnwindLogMsg("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)) {
        UnwindLogMsg(
            "Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64,
            cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
            cfa_reg_contents);
        return false;
      }
      address = cfa_reg_contents + fa.GetOffset();
      UnwindLogMsg(
          "CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64
          ", offset is %d",
          address, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
          cfa_reg_contents, fa.GetOffset());
      return true;
    } else
      UnwindLogMsg("unable to read CFA register %s (%d)", cfa_reg.GetName(),
                   cfa_reg.GetAsKind(eRegisterKindLLDB));
    break;
  }
  case UnwindPlan::Row::FAValue::isDWARFExpression: {
    UnwindLogMsg("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();
      UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64,
                   address);
      return true;
    }
    UnwindLogMsg("Failed to set CFA value via DWARF expression: %s",
                 llvm::toString(result.takeError()).c_str());
    break;
  }
  case UnwindPlan::Row::FAValue::isRaSearch: {
    UnwindLogMsg("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()) {
        UnwindLogMsg("Cannot read memory at 0x%" PRIx64 ": %s", candidate_addr,
                     st.AsCString());
        return false;
      }
      Address addr;
      uint32_t permissions;
      if (process.GetLoadAddressPermissions(candidate, permissions) &&
          permissions & lldb::ePermissionsExecutable) {
        address = candidate_addr;
        UnwindLogMsg("Heuristically found CFA: 0x%" PRIx64, address);
        return true;
      }
    }
    UnwindLogMsg("No suitable CFA found");
    break;
  }
  case UnwindPlan::Row::FAValue::isConstant: {
    address = fa.GetConstant();
    UnwindLogMsg("CFA value set by constant is 0x%" PRIx64, 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 {
      UnwindLogMsgVerbose("Could not retrieve parameter size: %s",
                          llvm::toString(expected_size.takeError()).c_str());
      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) {
    UnwindLogMsg(
        "Could not find RegisterInfo definition for lldb register number %d",
        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];
  UnwindLogMsgVerbose("looking for register saved location for reg %d",
                      lldb_regnum);

  // If this is the 0th frame, hand this over to the live register context
  if (IsFrameZero()) {
    UnwindLogMsgVerbose("passing along to the live register context for reg %d",
                        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];
  UnwindLogMsgVerbose("looking for register saved location for reg %d",
                      lldb_regnum);

  // If this is the 0th frame, hand this over to the live register context
  if (IsFrameZero()) {
    UnwindLogMsgVerbose("passing along to the live register context for reg %d",
                        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;
  }
}

void RegisterContextUnwind::UnwindLogMsg(const char *fmt, ...) {
  Log *log = GetLog(LLDBLog::Unwind);
  if (!log)
    return;

  va_list args;
  va_start(args, fmt);

  llvm::SmallString<0> logmsg;
  if (VASprintf(logmsg, fmt, args)) {
    LLDB_LOGF(log, "%*sth%d/fr%u %s",
              m_frame_number < 100 ? m_frame_number : 100, "",
              m_thread.GetIndexID(), m_frame_number, logmsg.c_str());
  }
  va_end(args);
}

void RegisterContextUnwind::UnwindLogMsgVerbose(const char *fmt, ...) {
  Log *log = GetLog(LLDBLog::Unwind);
  if (!log || !log->GetVerbose())
    return;

  va_list args;
  va_start(args, fmt);

  llvm::SmallString<0> logmsg;
  if (VASprintf(logmsg, fmt, args)) {
    LLDB_LOGF(log, "%*sth%d/fr%u %s",
              m_frame_number < 100 ? m_frame_number : 100, "",
              m_thread.GetIndexID(), m_frame_number, logmsg.c_str());
  }
  va_end(args);
}
