//===-- RegisterContextLLDB.cpp --------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//


#include "lldb/lldb-private.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Symbol/ArmUnwindInfo.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/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.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 "RegisterContextLLDB.h"

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

RegisterContextLLDB::RegisterContextLLDB
(
    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_start_pc (),
    m_current_pc (),
    m_current_offset (0),
    m_current_offset_backed_up_one (0),
    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
RegisterContextLLDB::IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset)
{
    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
        valid_pc_offset = m_current_offset;
        return true;
    }

    // if m_current_offset <= 0, we've got nothing else to try
    if (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))
    {
        // *valid_pc_offset = m_current_offset - 1;
        valid_pc_offset = m_current_pc.GetOffset() - 1;
        return true;
    }

    return false;
}

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

void
RegisterContextLLDB::InitializeZerothFrame()
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
    ExecutionContext exe_ctx(m_thread.shared_from_this());
    RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext();

    if (reg_ctx_sp.get() == NULL)
    {
        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.)
    ABI *abi = process->GetABI().get();
    if (abi)
        current_pc = abi->FixCodeAddress(current_pc);

    // 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");
    }

    // We require either a symbol or function in the symbols context to be successfully
    // filled in or this context is of no use to us.
    const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
    if (pc_module_sp.get()
        && (pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, resolve_scope, m_sym_ctx) & resolve_scope))
    {
        m_sym_ctx_valid = true;
    }

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

    AddressRange addr_range;
    m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range);

    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 (addr_range.GetBaseAddress().IsValid())
    {
        m_start_pc = addr_range.GetBaseAddress();
        if (m_current_pc.GetSection() == m_start_pc.GetSection())
        {
            m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset();
        }
        else if (m_current_pc.GetModule() == m_start_pc.GetModule())
        {
            // This means that whatever symbol we kicked up isn't really correct
            // --- we should not cross section boundaries ... We really should NULL out
            // the function/symbol in this case unless there is a bad assumption
            // here due to inlined functions?
            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 = -1;
        m_current_offset_backed_up_one = -1;
    }

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

    UnwindPlan::RowSP active_row;
    lldb::RegisterKind row_register_kind = eRegisterKindGeneric;
    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 ();
        if (active_row.get() && 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.GetString().c_str());
        }
    }

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


    if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))
    {
        // Try the fall back unwind plan since the
        // full unwind plan failed.
        FuncUnwindersSP func_unwinders_sp;
        UnwindPlanSP call_site_unwind_plan;
        bool cfa_status = false;

        if (m_sym_ctx_valid)
        {
            func_unwinders_sp = pc_module_sp->GetObjectFile()->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_current_offset_backed_up_one);

        if (call_site_unwind_plan.get() != 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;
        }
    }

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

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

void
RegisterContextLLDB::InitializeNonZerothFrame()
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_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;
    }

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

    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 == false)
        {
            m_frame_type = eNotAValidFrame;
            UnwindLogMsg ("this frame has a pc of 0x0");
            return;
        }
    }

    ExecutionContext exe_ctx(m_thread.shared_from_this());
    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.
    ABI *abi = process->GetABI().get();
    if (abi)
        pc = abi->FixCodeAddress(pc);

    m_current_pc.SetLoadAddress (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");

        // 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)
        {
            m_fast_unwind_plan_sp.reset ();
            m_full_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
            abi->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp);
            if (m_frame_type != eSkipFrame)  // don't override eSkipFrame
            {
                m_frame_type = eNormalFrame;
            }
            m_all_registers_available = false;
            m_current_offset = -1;
            m_current_offset_backed_up_one = -1;
            RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
            UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);
            if (row.get())
            {
                if (!ReadCFAValueForRow (row_register_kind, row, m_cfa))
                {
                    UnwindLogMsg ("failed to get cfa value");
                    if (m_frame_type != eSkipFrame)   // don't override eSkipFrame
                    {
                        m_frame_type = eNotAValidFrame;
                    }
                    return;
                }

                // A couple of sanity checks..
                if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1)
                {
                    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;
                }
            }

            UnwindLogMsg ("initialized frame cfa is 0x%" PRIx64, (uint64_t) m_cfa);
            return;
        }
        m_frame_type = eNotAValidFrame;
        UnwindLogMsg ("could not find any symbol for this pc, or a default unwind plan, to continue unwind.");
        return;
    }

    bool resolve_tail_call_address = false; // m_current_pc can be one past the address range of the function...
                                            // If the saved pc does not point to a function/symbol because it is
                                            // beyond the bounds of the correct function and there's no symbol there,
                                            // we do *not* want ResolveSymbolContextForAddress to back up the pc by 1,
                                            // because then we might not find the correct unwind information later.
                                            // Instead, let ResolveSymbolContextForAddress fail, and handle the case
                                            // via decr_pc_and_recompute_addr_range below.
    const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
    uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress (m_current_pc,
                                                                            resolve_scope,
                                                                            m_sym_ctx, resolve_tail_call_address);

    // We require either a symbol or function in the symbols context to be successfully
    // filled in or this context is of no use to us.
    if (resolve_scope & resolved_scope)
    {
        m_sym_ctx_valid = true;
    }

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

    AddressRange addr_range;
    if (!m_sym_ctx.GetAddressRange (resolve_scope, 0, false, addr_range))
    {
        m_sym_ctx_valid = false;
    }

    bool decr_pc_and_recompute_addr_range = false;

    // If the symbol lookup failed...
    if (m_sym_ctx_valid == false)
       decr_pc_and_recompute_addr_range = true;

    // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp),
    // and our "current" pc is the start of a function...
    if (m_sym_ctx_valid
        && GetNextFrame()->m_frame_type != eTrapHandlerFrame
        && GetNextFrame()->m_frame_type != eDebuggerFrame
        && addr_range.GetBaseAddress().IsValid()
        && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection()
        && addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset())
    {
        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 = false;
        uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
        
        ModuleSP temporary_module_sp = temporary_pc.GetModule();
        if (temporary_module_sp &&
            temporary_module_sp->ResolveSymbolContextForAddress (temporary_pc, resolve_scope, m_sym_ctx) & resolve_scope)
        {
            if (m_sym_ctx.GetAddressRange (resolve_scope, 0, false,  addr_range))
                m_sym_ctx_valid = true;
        }
        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 (addr_range.GetBaseAddress().IsValid())
    {
        m_start_pc = addr_range.GetBaseAddress();
        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 = -1;
        m_current_offset_backed_up_one = -1;
    }

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

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

    UnwindPlan::RowSP active_row;
    RegisterKind row_register_kind = eRegisterKindGeneric;

    // 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 ();
        if (active_row.get() && 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 ("active row: %s", active_row_strm.GetString().c_str());
        }
    }
    else
    {
        m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
        int valid_offset = -1;
        if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp, valid_offset))
        {
            active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (valid_offset);
            row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
            if (active_row.get() && 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 ("active row: %s", active_row_strm.GetString().c_str());
            }
        }
    }

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

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

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

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

    UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64,
            (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
}

bool
RegisterContextLLDB::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 compiance) 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 very unlikely)

    RegisterContextLLDB::SharedPtr next_frame = GetNextFrame();
    if (next_frame)
    {
        RegisterContextLLDB::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
RegisterContextLLDB::IsFrameZero () const
{
    return m_frame_number == 0;
}


// 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, -1 if unknown

UnwindPlanSP
RegisterContextLLDB::GetFastUnwindPlanForFrame ()
{
    UnwindPlanSP unwind_plan_sp;
    ModuleSP pc_module_sp (m_current_pc.GetModule());

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

    if (IsFrameZero ())
        return unwind_plan_sp;

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

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

    unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind (*m_thread.CalculateTarget(), m_thread);
    if (unwind_plan_sp)
    {
        if (unwind_plan_sp->PlanValidAtAddress (m_current_pc))
        {
            Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
            if (log && log->GetVerbose())
            {
                if (m_fast_unwind_plan_sp)
                    UnwindLogMsgVerbose ("frame, and has a fast UnwindPlan");
                else
                    UnwindLogMsgVerbose ("frame");
            }
            m_frame_type = eNormalFrame;
            return unwind_plan_sp;
        }
        else
        {
            unwind_plan_sp.reset();
        }
    }
    return unwind_plan_sp;
}

// 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, -1 if unknown

UnwindPlanSP
RegisterContextLLDB::GetFullUnwindPlanForFrame ()
{
    UnwindPlanSP unwind_plan_sp;
    UnwindPlanSP arch_default_unwind_plan_sp;
    ExecutionContext exe_ctx(m_thread.shared_from_this());
    Process *process = exe_ctx.GetProcessPtr();
    ABI *abi = process ? process->GetABI().get() : NULL;
    if (abi)
    {
        arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
        abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp);
    }
    else
    {
        UnwindLogMsg ("unable to get architectural default UnwindPlan from ABI plugin");
    }

    bool behaves_like_zeroth_frame = false;
    if (IsFrameZero ()
        || GetNextFrame()->m_frame_type == eTrapHandlerFrame
        || GetNextFrame()->m_frame_type == eDebuggerFrame)
    {
        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 == NULL && m_sym_ctx.symbol == NULL)) && 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)
            {
                unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
                abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp);
                m_frame_type = eNormalFrame;
                return unwind_plan_sp;
            }
        }
    }

    // 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() == NULL)
    {
        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->GetObjectFile()->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.
        DWARFCallFrameInfo *eh_frame = pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo();
        if (eh_frame)
        {
            unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
            if (eh_frame->GetUnwindPlan (m_current_pc, *unwind_plan_sp))
                return unwind_plan_sp;
            else
                unwind_plan_sp.reset();
        }

        ArmUnwindInfo *arm_exidx = pc_module_sp->GetObjectFile()->GetUnwindTable().GetArmUnwindInfo();
        if (arm_exidx)
        {
            unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
            if (arm_exidx->GetUnwindPlan (exe_ctx.GetTargetRef(), m_current_pc, *unwind_plan_sp))
                return unwind_plan_sp;
            else
                unwind_plan_sp.reset();
        }

        return arch_default_unwind_plan_sp;
    }

    // If we're in _sigtramp(), unwinding past this frame requires special knowledge.  On Mac OS X this knowledge
    // is properly encoded in the eh_frame section, so prefer that if available.
    // On other platforms we may need to provide a platform-specific UnwindPlan which encodes the details of
    // how to unwind out of sigtramp.
    if (m_frame_type == eTrapHandlerFrame && process)
    {
        m_fast_unwind_plan_sp.reset();
        unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one);
        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)
        unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one);
        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 (behaves_like_zeroth_frame && process)
    {
        unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (process->GetTarget(), m_thread, m_current_offset_backed_up_one);
        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.
                UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one);
                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", unwind_plan_sp->GetSourceName().GetCString());
            return 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_current_offset_backed_up_one);
    }
    int valid_offset = -1;
    if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset))
    {
        UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", 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, m_current_offset_backed_up_one);
    }
    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.
        UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one);
        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, valid_offset))
    {
        UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", 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_backed_up_one == 0)
    {
        unwind_plan_sp = func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry (m_thread);
        if (unwind_plan_sp)
        {
            UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", 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", 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
RegisterContextLLDB::InvalidateAllRegisters ()
{
    m_frame_type = eNotAValidFrame;
}

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

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

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

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

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

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

    switch (regloc.type)
    {
    case UnwindLLDB::RegisterLocation::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::RegisterLocation::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::RegisterLocation::eRegisterValueInferred:
        success = value.SetUInt (regloc.location.inferred_value, reg_info->byte_size);
        break;

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

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

    bool success = false;

    switch (regloc.type)
    {
        case UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext:
            {
                const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
                success = m_thread.GetRegisterContext()->WriteRegister (other_reg_info, value);
            }
            break;
        case UnwindLLDB::RegisterLocation::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::RegisterLocation::eRegisterValueInferred:
        case UnwindLLDB::RegisterLocation::eRegisterNotSaved:
            break;
        case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation:
            assert ("FIXME debugger inferior function call unwind");
            break;
        case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation:
            {
                Error error (WriteRegisterValueToMemory (reg_info,
                                                         regloc.location.target_memory_location,
                                                         reg_info->byte_size,
                                                         value));
                success = error.Success();
            }
            break;
        default:
            assert ("Unknown RegisterLocation type.");
            break;
    }
    return success;
}


bool
RegisterContextLLDB::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 differnece between
// "the unwind plan below this frame failed" versus "we successfully completed the stack walk" so
// this method helps to disambiguate that.

bool
RegisterContextLLDB::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
RegisterContextLLDB::IsSkipFrame () const
{
    return m_frame_type == eSkipFrame;
}

bool
RegisterContextLLDB::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;
}

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

enum UnwindLLDB::RegisterSearchResult
RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc)
{
    RegisterNumber regnum (m_thread, eRegisterKindLLDB, lldb_regnum);

    // Have we already found this register location?
    if (!m_registers.empty())
    {
        std::map<uint32_t, lldb_private::UnwindLLDB::RegisterLocation>::const_iterator iterator;
        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;
        }
    }

    // Look through the available UnwindPlans for the register location.

    UnwindPlan::Row::RegisterLocation unwindplan_regloc;
    bool have_unwindplan_regloc = false;
    RegisterKind unwindplan_registerkind = kNumRegisterKinds;

    if (m_fast_unwind_plan_sp)
    {
        UnwindPlan::RowSP active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
        unwindplan_registerkind = m_fast_unwind_plan_sp->GetRegisterKind ();
        if (regnum.GetAsKind (unwindplan_registerkind) == LLDB_INVALID_REGNUM)
        {
            UnwindLogMsg ("could not convert lldb regnum %s (%d) into %d RegisterKind reg numbering scheme",
                    regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), (int) unwindplan_registerkind);
            return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
        }
        if (active_row->GetRegisterInfo (regnum.GetAsKind (unwindplan_registerkind), unwindplan_regloc))
        {
            UnwindLogMsg ("supplying caller's saved %s (%d)'s location using FastUnwindPlan", 
                          regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
            have_unwindplan_regloc = true;
        }
    }

    if (!have_unwindplan_regloc)
    {
        // m_full_unwind_plan_sp being NULL means that we haven't tried to find a full UnwindPlan yet
        if (!m_full_unwind_plan_sp)
            m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();

        if (m_full_unwind_plan_sp)
        {
            RegisterNumber pc_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);

            UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
            unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind ();

            RegisterNumber return_address_reg;

            // If we're fetching the saved pc and this UnwindPlan defines a ReturnAddress register (e.g. lr on arm),
            // look for the return address register number in the UnwindPlan's row.
            if (pc_regnum.IsValid()
                && pc_regnum == regnum
                && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM)
            {
                
                return_address_reg.init (m_thread, m_full_unwind_plan_sp->GetRegisterKind(), m_full_unwind_plan_sp->GetReturnAddressRegister());
                regnum = return_address_reg;
                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));
            }
            else
            {
                if (regnum.GetAsKind (unwindplan_registerkind) == LLDB_INVALID_REGNUM)
                {
                    if (unwindplan_registerkind == 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) unwindplan_registerkind);
                    }
                    return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
                }
            }

            if (regnum.IsValid() 
                && active_row->GetRegisterInfo (regnum.GetAsKind (unwindplan_registerkind), unwindplan_regloc))
            {
                have_unwindplan_regloc = true;
                UnwindLogMsg ("supplying caller's saved %s (%d)'s location using %s UnwindPlan", 
                              regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB),
                              m_full_unwind_plan_sp->GetSourceName().GetCString());
            }

            // This is frame 0 and we're retrieving the PC and it's saved in a Return Address register and
            // it hasn't been saved anywhere yet -- that is, it's still live in the actual register.
            // Handle this specially.

            if (have_unwindplan_regloc == false 
                && return_address_reg.IsValid()
                && IsFrameZero())
            {
                if (return_address_reg.GetAsKind (eRegisterKindLLDB) != LLDB_INVALID_REGNUM)
                {
                    lldb_private::UnwindLLDB::RegisterLocation new_regloc;
                    new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext;
                    new_regloc.location.register_number = return_address_reg.GetAsKind (eRegisterKindLLDB);
                    m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = new_regloc;
                    regloc = new_regloc;
                    UnwindLogMsg ("supplying caller's register %s (%d) from the live RegisterContext at frame 0, saved in %d", 
                                  return_address_reg.GetName(), return_address_reg.GetAsKind (eRegisterKindLLDB), 
                                  return_address_reg.GetAsKind (eRegisterKindLLDB));
                    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
                }
            }

            // If this architecture stores the return address in a register (it defines a Return Address register)
            // and we're on a non-zero stack frame and the Full UnwindPlan says that the pc is stored in the
            // RA registers (e.g. lr on arm), then we know that the full unwindplan is not trustworthy -- this
            // is an impossible situation and the instruction emulation code has likely been misled.  
            // If this stack frame meets those criteria, we need to throw away the Full UnwindPlan that the 
            // instruction emulation came up with and fall back to the architecture's Default UnwindPlan so
            // the stack walk can get past this point.

            // Special note:  If the Full UnwindPlan was generated from the compiler, don't second-guess it 
            // when we're at a call site location.

            // arch_default_ra_regnum is the return address register # in the Full UnwindPlan register numbering
            RegisterNumber arch_default_ra_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);

            if (arch_default_ra_regnum.GetAsKind (unwindplan_registerkind) != LLDB_INVALID_REGNUM
                && pc_regnum == regnum
                && unwindplan_regloc.IsInOtherRegister()
                && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum.GetAsKind (unwindplan_registerkind)
                && m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes
                && !m_all_registers_available)
            {
                UnwindLogMsg ("%s UnwindPlan tried to restore the pc from the link register but this is a non-zero frame",
                              m_full_unwind_plan_sp->GetSourceName().GetCString());

                // Throw away the full unwindplan; install the arch default unwindplan
                if (ForceSwitchToFallbackUnwindPlan())
                {
                    // Update for the possibly new unwind plan
                    unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind ();
                    UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);

                    // Sanity check: Verify that we can fetch a pc value and CFA value with this unwind plan

                    RegisterNumber arch_default_pc_reg (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
                    bool can_fetch_pc_value = false;
                    bool can_fetch_cfa = false;
                    addr_t cfa_value;
                    if (active_row)
                    {
                        if (arch_default_pc_reg.GetAsKind (unwindplan_registerkind) != LLDB_INVALID_REGNUM
                            && active_row->GetRegisterInfo (arch_default_pc_reg.GetAsKind (unwindplan_registerkind), unwindplan_regloc))
                        {
                            can_fetch_pc_value = true;
                        }
                        if (ReadCFAValueForRow (unwindplan_registerkind, active_row, cfa_value))
                        {
                            can_fetch_cfa = true;
                        }
                    }

                    if (can_fetch_pc_value && can_fetch_cfa)
                    {
                        have_unwindplan_regloc = true;
                    }
                    else
                    {
                        have_unwindplan_regloc = false;
                    }
                }
                else
                {
                    // We were unable to fall back to another unwind plan
                    have_unwindplan_regloc = false;
                }
            }
        }
    }

    ExecutionContext exe_ctx(m_thread.shared_from_this());
    Process *process = exe_ctx.GetProcessPtr();
    if (have_unwindplan_regloc == false)
    {
        // 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 may set volatile registers to the undefined state.
        ABI *abi = process ? process->GetABI().get() : NULL;
        if (abi)
        {
            const RegisterInfo *reg_info = GetRegisterInfoAtIndex(regnum.GetAsKind (eRegisterKindLLDB));
            if (reg_info && abi->GetFallbackRegisterLocation (reg_info, unwindplan_regloc))
            {
                UnwindLogMsg ("supplying caller's saved %s (%d)'s location using ABI default",
                              regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
                have_unwindplan_regloc = true;
            }
        }
    }

    if (have_unwindplan_regloc == false)
    {
        if (IsFrameZero ())
        {
            // This is frame 0 - we should return the actual live register context value
            lldb_private::UnwindLLDB::RegisterLocation new_regloc;
            new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext;
            new_regloc.location.register_number = regnum.GetAsKind (eRegisterKindLLDB);
            m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = new_regloc;
            regloc = new_regloc;
            UnwindLogMsg ("supplying caller's register %s (%d) from the live RegisterContext at frame 0", 
                           regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
            return UnwindLLDB::RegisterSearchResult::eRegisterFound;
        }
        else
        {
            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());
        }
        return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
    }

    // unwindplan_regloc has valid contents about where to retrieve the register
    if (unwindplan_regloc.IsUnspecified())
    {
        lldb_private::UnwindLLDB::RegisterLocation new_regloc;
        new_regloc.type = UnwindLLDB::RegisterLocation::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 (unwindplan_regloc.IsUndefined())
    {
         UnwindLogMsg ("did not supply reg location for %s (%d) because it is volatile",
                       regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
         return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
    }

    if (unwindplan_regloc.IsSame())
    {
        if (IsFrameZero() == false 
            && (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 non-zero frame -- treat as if we have no information", 
                        regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
            return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
        }
        else
        {
            regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
            regloc.location.register_number = 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), 
                        regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB));
            return UnwindLLDB::RegisterSearchResult::eRegisterFound;
        }
    }

    if (unwindplan_regloc.IsCFAPlusOffset())
    {
        int offset = unwindplan_regloc.GetOffset();
        regloc.type = UnwindLLDB::RegisterLocation::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 (unwindplan_regloc.IsAtCFAPlusOffset())
    {
        int offset = unwindplan_regloc.GetOffset();
        regloc.type = UnwindLLDB::RegisterLocation::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 (unwindplan_regloc.IsInOtherRegister())
    {
        uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber();
        RegisterNumber row_regnum (m_thread, unwindplan_registerkind, unwindplan_regnum);
        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::RegisterLocation::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 (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression())
    {
        DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
                                 unwindplan_regloc.GetDWARFExpressionLength(),
                                 process->GetByteOrder(), process->GetAddressByteSize());
        ModuleSP opcode_ctx;
        DWARFExpression dwarfexpr (opcode_ctx,
                                   dwarfdata,
                                   nullptr,
                                   0,
                                   unwindplan_regloc.GetDWARFExpressionLength());
        dwarfexpr.SetRegisterKind (unwindplan_registerkind);
        Value result;
        Error error;
        if (dwarfexpr.Evaluate (&exe_ctx, nullptr, nullptr, this, 0, nullptr, nullptr, result, &error))
        {
            addr_t val;
            val = result.GetScalar().ULongLong();
            if (unwindplan_regloc.IsDWARFExpression())
             {
                regloc.type = UnwindLLDB::RegisterLocation::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::RegisterLocation::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;
    }

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

// 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
RegisterContextLLDB::TryFallbackUnwindPlan ()
{
    if (m_fallback_unwind_plan_sp.get() == nullptr)
        return false;

    if (m_full_unwind_plan_sp.get() == 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;
    addr_t old_this_frame_cfa_value = m_cfa;
    UnwindLLDB::RegisterLocation 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();
            }
        }
    }

    // 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.get() == 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'.
    UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
    addr_t old_cfa = m_cfa;

    m_registers.clear();

    m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;

    UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
    
    if (active_row && active_row->GetCFAValue().GetValueType() != UnwindPlan::Row::CFAValue::unspecified)
    {
        addr_t new_cfa;
        if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa)
            || new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS)
        {
            UnwindLogMsg ("failed to get cfa with fallback unwindplan");
            m_fallback_unwind_plan_sp.reset();
            m_full_unwind_plan_sp = original_full_unwind_plan_sp;
            m_cfa = old_cfa;
            return false;
        }
        m_cfa = new_cfa;

        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 (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;
            return false;
        }

        if (old_caller_pc_value != LLDB_INVALID_ADDRESS)
        {
            if (old_caller_pc_value == new_caller_pc_value && new_cfa == old_this_frame_cfa_value)
            {
                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;
                m_cfa = old_cfa;
                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();
    }

    return true;
}

bool
RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan ()
{
    if (m_fallback_unwind_plan_sp.get() == NULL)
        return false;

    if (m_full_unwind_plan_sp.get() == NULL)
        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;
    }

    UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
    
    if (active_row && active_row->GetCFAValue().GetValueType() != UnwindPlan::Row::CFAValue::unspecified)
    {
        addr_t new_cfa;
        if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa)
            || new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS)
        {
            UnwindLogMsg ("failed to get cfa with fallback unwindplan");
            m_fallback_unwind_plan_sp.reset();
            return false;
        }

        m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
        m_fallback_unwind_plan_sp.reset();

        m_registers.clear();

        m_cfa = new_cfa;

        UnwindLogMsg ("switched unconditionally to the fallback unwindplan %s", m_full_unwind_plan_sp->GetSourceName().GetCString());
        return true;
    }
    return false;
}

bool
RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind,
                                         const UnwindPlan::RowSP &row,
                                         addr_t &cfa_value)
{
    RegisterValue reg_value;

    cfa_value = LLDB_INVALID_ADDRESS;
    addr_t cfa_reg_contents;

    switch (row->GetCFAValue().GetValueType())
    {
    case UnwindPlan::Row::CFAValue::isRegisterDereferenced:
        {
            RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFAValue().GetRegisterNumber());
            if (ReadGPRValue (cfa_reg, cfa_reg_contents))
            {
                const RegisterInfo *reg_info = GetRegisterInfoAtIndex (cfa_reg.GetAsKind (eRegisterKindLLDB));
                RegisterValue reg_value;
                if (reg_info)
                {
                    Error error = ReadRegisterValueFromMemory(reg_info,
                                                              cfa_reg_contents,
                                                              reg_info->byte_size,
                                                              reg_value);
                    if (error.Success ())
                    {
                        cfa_value = reg_value.GetAsUInt64();
                        UnwindLogMsg ("CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64 ", CFA value is 0x%" PRIx64,
                                      cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
                                      cfa_reg_contents, cfa_value);
                        return true;
                    }
                    else
                    {
                        UnwindLogMsg ("Tried to deref reg %s (%d) [0x%" PRIx64 "] but memory read failed.",
                                      cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
                                      cfa_reg_contents);
                    }
                }
            }
            break;
        }
    case UnwindPlan::Row::CFAValue::isRegisterPlusOffset:
        {
            RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFAValue().GetRegisterNumber());
            if (ReadGPRValue (cfa_reg, cfa_reg_contents))
            {
                if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || cfa_reg_contents == 1)
                {
                    UnwindLogMsg ("Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64,
                                  cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
                                  cfa_reg_contents);
                    cfa_reg_contents = LLDB_INVALID_ADDRESS;
                    return false;
                }
                cfa_value = cfa_reg_contents + row->GetCFAValue().GetOffset();
                UnwindLogMsg ("CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64 ", offset is %d",
                              cfa_value,
                              cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
                              cfa_reg_contents, row->GetCFAValue().GetOffset());
                return true;
            }
            break;
        }
    case UnwindPlan::Row::CFAValue::isDWARFExpression:
        {
            ExecutionContext exe_ctx(m_thread.shared_from_this());
            Process *process = exe_ctx.GetProcessPtr();
            DataExtractor dwarfdata (row->GetCFAValue().GetDWARFExpressionBytes(),
                                     row->GetCFAValue().GetDWARFExpressionLength(),
                                     process->GetByteOrder(), process->GetAddressByteSize());
            ModuleSP opcode_ctx;
            DWARFExpression dwarfexpr (opcode_ctx,
                                       dwarfdata,
                                       nullptr,
                                       0,
                                       row->GetCFAValue().GetDWARFExpressionLength());
            dwarfexpr.SetRegisterKind (row_register_kind);
            Value result;
            Error error;
            if (dwarfexpr.Evaluate (&exe_ctx, nullptr, nullptr, this, 0, nullptr, nullptr, result, &error))
            {
                cfa_value = result.GetScalar().ULongLong();

                UnwindLogMsg ("CFA value set by DWARF expression is 0x%" PRIx64, cfa_value);
                return true;
            }
            UnwindLogMsg ("Failed to set CFA value via DWARF expression: %s", error.AsCString());
            break;
        }
    default:
        return false;
    }
    return false;
}

// 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
RegisterContextLLDB::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);
    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();
            return true;
        }
        return false;
    }

    bool pc_register = false;
    uint32_t generic_regnum;
    if (register_kind == eRegisterKindGeneric 
        && (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA))
    {
        pc_register = true;
    }
    else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindGeneric, generic_regnum)
             && (generic_regnum == LLDB_REGNUM_GENERIC_PC || generic_regnum == LLDB_REGNUM_GENERIC_RA))
    {
        pc_register = true;
    }

    lldb_private::UnwindLLDB::RegisterLocation 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();
        return true;
    }
    return false;
}

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

// Find the value of a register in THIS frame

bool
RegisterContextLLDB::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::RegisterLocation 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;

    return ReadRegisterValueFromRegisterLocation (regloc, reg_info, value);
}

bool
RegisterContextLLDB::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::RegisterLocation 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
RegisterContextLLDB::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
{
    return false;
}

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

// Retrieve the pc value for THIS from

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


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

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

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

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

    if (!m_start_pc.IsValid())
    {
        return ReadPC (start_pc);
    }
    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
RegisterContextLLDB::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 (m_all_registers_available == false
            && above_trap_handler == false
            && (pc == 0 || pc == 1))
        {
            return false;
        }
        else
        {
            return true;
        }
    }
    else
    {
        return false;
    }
}


void
RegisterContextLLDB::UnwindLogMsg (const char *fmt, ...)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
    if (log)
    {
        va_list args;
        va_start (args, fmt);

        char *logmsg;
        if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
        {
            if (logmsg)
                free (logmsg);
            va_end (args);
            return;
        }
        va_end (args);

        log->Printf ("%*sth%d/fr%u %s",
                      m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
                      logmsg);
        free (logmsg);
    }
}

void
RegisterContextLLDB::UnwindLogMsgVerbose (const char *fmt, ...)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
    if (log && log->GetVerbose())
    {
        va_list args;
        va_start (args, fmt);

        char *logmsg;
        if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
        {
            if (logmsg)
                free (logmsg);
            va_end (args);
            return;
        }
        va_end (args);

        log->Printf ("%*sth%d/fr%u %s",
                      m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
                      logmsg);
        free (logmsg);
    }
}


