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

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Target/Thread.h"
#include "Plugins/Process/Utility/UnwindLLDB.h"
#include "Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/State.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanBase.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Target/ThreadPlanPython.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
#include "lldb/Target/ThreadPlanStepOverRange.h"
#include "lldb/Target/ThreadPlanStepThrough.h"
#include "lldb/Target/ThreadPlanStepUntil.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Target/Unwind.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/lldb-enumerations.h"

using namespace lldb;
using namespace lldb_private;

const ThreadPropertiesSP &Thread::GetGlobalProperties() {
  // NOTE: intentional leak so we don't crash if global destructor chain gets
  // called as other threads still use the result of this function
  static ThreadPropertiesSP *g_settings_sp_ptr =
      new ThreadPropertiesSP(new ThreadProperties(true));
  return *g_settings_sp_ptr;
}

static PropertyDefinition g_properties[] = {
    {"step-in-avoid-nodebug", OptionValue::eTypeBoolean, true, true, nullptr,
     nullptr,
     "If true, step-in will not stop in functions with no debug information."},
    {"step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, nullptr,
     nullptr, "If true, when step-in/step-out/step-over leave the current "
              "frame, they will continue to step out till they come to a "
              "function with "
              "debug information.  Passing a frame argument to step-out will "
              "override this option."},
    {"step-avoid-regexp", OptionValue::eTypeRegex, true, 0, "^std::", nullptr,
     "A regular expression defining functions step-in won't stop in."},
    {"step-avoid-libraries", OptionValue::eTypeFileSpecList, true, 0, nullptr,
     nullptr, "A list of libraries that source stepping won't stop in."},
    {"trace-thread", OptionValue::eTypeBoolean, false, false, nullptr, nullptr,
     "If true, this thread will single-step and log execution."},
    {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};

enum {
  ePropertyStepInAvoidsNoDebug,
  ePropertyStepOutAvoidsNoDebug,
  ePropertyStepAvoidRegex,
  ePropertyStepAvoidLibraries,
  ePropertyEnableThreadTrace
};

class ThreadOptionValueProperties : public OptionValueProperties {
public:
  ThreadOptionValueProperties(const ConstString &name)
      : OptionValueProperties(name) {}

  // This constructor is used when creating ThreadOptionValueProperties when it
  // is part of a new lldb_private::Thread instance. It will copy all current
  // global property values as needed
  ThreadOptionValueProperties(ThreadProperties *global_properties)
      : OptionValueProperties(*global_properties->GetValueProperties()) {}

  const Property *GetPropertyAtIndex(const ExecutionContext *exe_ctx,
                                     bool will_modify,
                                     uint32_t idx) const override {
    // When getting the value for a key from the thread options, we will always
    // try and grab the setting from the current thread if there is one. Else we
    // just
    // use the one from this instance.
    if (exe_ctx) {
      Thread *thread = exe_ctx->GetThreadPtr();
      if (thread) {
        ThreadOptionValueProperties *instance_properties =
            static_cast<ThreadOptionValueProperties *>(
                thread->GetValueProperties().get());
        if (this != instance_properties)
          return instance_properties->ProtectedGetPropertyAtIndex(idx);
      }
    }
    return ProtectedGetPropertyAtIndex(idx);
  }
};

ThreadProperties::ThreadProperties(bool is_global) : Properties() {
  if (is_global) {
    m_collection_sp.reset(
        new ThreadOptionValueProperties(ConstString("thread")));
    m_collection_sp->Initialize(g_properties);
  } else
    m_collection_sp.reset(
        new ThreadOptionValueProperties(Thread::GetGlobalProperties().get()));
}

ThreadProperties::~ThreadProperties() = default;

const RegularExpression *ThreadProperties::GetSymbolsToAvoidRegexp() {
  const uint32_t idx = ePropertyStepAvoidRegex;
  return m_collection_sp->GetPropertyAtIndexAsOptionValueRegex(nullptr, idx);
}

FileSpecList &ThreadProperties::GetLibrariesToAvoid() const {
  const uint32_t idx = ePropertyStepAvoidLibraries;
  OptionValueFileSpecList *option_value =
      m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr,
                                                                   false, idx);
  assert(option_value);
  return option_value->GetCurrentValue();
}

bool ThreadProperties::GetTraceEnabledState() const {
  const uint32_t idx = ePropertyEnableThreadTrace;
  return m_collection_sp->GetPropertyAtIndexAsBoolean(
      nullptr, idx, g_properties[idx].default_uint_value != 0);
}

bool ThreadProperties::GetStepInAvoidsNoDebug() const {
  const uint32_t idx = ePropertyStepInAvoidsNoDebug;
  return m_collection_sp->GetPropertyAtIndexAsBoolean(
      nullptr, idx, g_properties[idx].default_uint_value != 0);
}

bool ThreadProperties::GetStepOutAvoidsNoDebug() const {
  const uint32_t idx = ePropertyStepOutAvoidsNoDebug;
  return m_collection_sp->GetPropertyAtIndexAsBoolean(
      nullptr, idx, g_properties[idx].default_uint_value != 0);
}

//------------------------------------------------------------------
// Thread Event Data
//------------------------------------------------------------------

const ConstString &Thread::ThreadEventData::GetFlavorString() {
  static ConstString g_flavor("Thread::ThreadEventData");
  return g_flavor;
}

Thread::ThreadEventData::ThreadEventData(const lldb::ThreadSP thread_sp)
    : m_thread_sp(thread_sp), m_stack_id() {}

Thread::ThreadEventData::ThreadEventData(const lldb::ThreadSP thread_sp,
                                         const StackID &stack_id)
    : m_thread_sp(thread_sp), m_stack_id(stack_id) {}

Thread::ThreadEventData::ThreadEventData() : m_thread_sp(), m_stack_id() {}

Thread::ThreadEventData::~ThreadEventData() = default;

void Thread::ThreadEventData::Dump(Stream *s) const {}

const Thread::ThreadEventData *
Thread::ThreadEventData::GetEventDataFromEvent(const Event *event_ptr) {
  if (event_ptr) {
    const EventData *event_data = event_ptr->GetData();
    if (event_data &&
        event_data->GetFlavor() == ThreadEventData::GetFlavorString())
      return static_cast<const ThreadEventData *>(event_ptr->GetData());
  }
  return nullptr;
}

ThreadSP Thread::ThreadEventData::GetThreadFromEvent(const Event *event_ptr) {
  ThreadSP thread_sp;
  const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr);
  if (event_data)
    thread_sp = event_data->GetThread();
  return thread_sp;
}

StackID Thread::ThreadEventData::GetStackIDFromEvent(const Event *event_ptr) {
  StackID stack_id;
  const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr);
  if (event_data)
    stack_id = event_data->GetStackID();
  return stack_id;
}

StackFrameSP
Thread::ThreadEventData::GetStackFrameFromEvent(const Event *event_ptr) {
  const ThreadEventData *event_data = GetEventDataFromEvent(event_ptr);
  StackFrameSP frame_sp;
  if (event_data) {
    ThreadSP thread_sp = event_data->GetThread();
    if (thread_sp) {
      frame_sp = thread_sp->GetStackFrameList()->GetFrameWithStackID(
          event_data->GetStackID());
    }
  }
  return frame_sp;
}

//------------------------------------------------------------------
// Thread class
//------------------------------------------------------------------

ConstString &Thread::GetStaticBroadcasterClass() {
  static ConstString class_name("lldb.thread");
  return class_name;
}

Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id)
    : ThreadProperties(false), UserID(tid),
      Broadcaster(process.GetTarget().GetDebugger().GetBroadcasterManager(),
                  Thread::GetStaticBroadcasterClass().AsCString()),
      m_process_wp(process.shared_from_this()), m_stop_info_sp(),
      m_stop_info_stop_id(0), m_stop_info_override_stop_id(0),
      m_index_id(use_invalid_index_id ? LLDB_INVALID_INDEX32
                                      : process.GetNextThreadIndexID(tid)),
      m_reg_context_sp(), m_state(eStateUnloaded), m_state_mutex(),
      m_plan_stack(), m_completed_plan_stack(), m_frame_mutex(),
      m_curr_frames_sp(), m_prev_frames_sp(),
      m_resume_signal(LLDB_INVALID_SIGNAL_NUMBER),
      m_resume_state(eStateRunning), m_temporary_resume_state(eStateRunning),
      m_unwinder_ap(), m_destroy_called(false),
      m_override_should_notify(eLazyBoolCalculate),
      m_extended_info_fetched(false), m_extended_info() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
  if (log)
    log->Printf("%p Thread::Thread(tid = 0x%4.4" PRIx64 ")",
                static_cast<void *>(this), GetID());

  CheckInWithManager();
  QueueFundamentalPlan(true);
}

Thread::~Thread() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
  if (log)
    log->Printf("%p Thread::~Thread(tid = 0x%4.4" PRIx64 ")",
                static_cast<void *>(this), GetID());
  /// If you hit this assert, it means your derived class forgot to call
  /// DoDestroy in its destructor.
  assert(m_destroy_called);
}

void Thread::DestroyThread() {
  // Tell any plans on the plan stacks that the thread is being destroyed since
  // any plans that have a thread go away in the middle of might need
  // to do cleanup, or in some cases NOT do cleanup...
  for (auto plan : m_plan_stack)
    plan->ThreadDestroyed();

  for (auto plan : m_discarded_plan_stack)
    plan->ThreadDestroyed();

  for (auto plan : m_completed_plan_stack)
    plan->ThreadDestroyed();

  m_destroy_called = true;
  m_plan_stack.clear();
  m_discarded_plan_stack.clear();
  m_completed_plan_stack.clear();

  // Push a ThreadPlanNull on the plan stack.  That way we can continue assuming
  // that the
  // plan stack is never empty, but if somebody errantly asks questions of a
  // destroyed thread
  // without checking first whether it is destroyed, they won't crash.
  ThreadPlanSP null_plan_sp(new ThreadPlanNull(*this));
  m_plan_stack.push_back(null_plan_sp);

  m_stop_info_sp.reset();
  m_reg_context_sp.reset();
  m_unwinder_ap.reset();
  std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
  m_curr_frames_sp.reset();
  m_prev_frames_sp.reset();
}

void Thread::BroadcastSelectedFrameChange(StackID &new_frame_id) {
  if (EventTypeHasListeners(eBroadcastBitSelectedFrameChanged))
    BroadcastEvent(eBroadcastBitSelectedFrameChanged,
                   new ThreadEventData(this->shared_from_this(), new_frame_id));
}

lldb::StackFrameSP Thread::GetSelectedFrame() {
  StackFrameListSP stack_frame_list_sp(GetStackFrameList());
  StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex(
      stack_frame_list_sp->GetSelectedFrameIndex());
  FunctionOptimizationWarning(frame_sp.get());
  return frame_sp;
}

uint32_t Thread::SetSelectedFrame(lldb_private::StackFrame *frame,
                                  bool broadcast) {
  uint32_t ret_value = GetStackFrameList()->SetSelectedFrame(frame);
  if (broadcast)
    BroadcastSelectedFrameChange(frame->GetStackID());
  FunctionOptimizationWarning(frame);
  return ret_value;
}

bool Thread::SetSelectedFrameByIndex(uint32_t frame_idx, bool broadcast) {
  StackFrameSP frame_sp(GetStackFrameList()->GetFrameAtIndex(frame_idx));
  if (frame_sp) {
    GetStackFrameList()->SetSelectedFrame(frame_sp.get());
    if (broadcast)
      BroadcastSelectedFrameChange(frame_sp->GetStackID());
    FunctionOptimizationWarning(frame_sp.get());
    return true;
  } else
    return false;
}

bool Thread::SetSelectedFrameByIndexNoisily(uint32_t frame_idx,
                                            Stream &output_stream) {
  const bool broadcast = true;
  bool success = SetSelectedFrameByIndex(frame_idx, broadcast);
  if (success) {
    StackFrameSP frame_sp = GetSelectedFrame();
    if (frame_sp) {
      bool already_shown = false;
      SymbolContext frame_sc(
          frame_sp->GetSymbolContext(eSymbolContextLineEntry));
      if (GetProcess()->GetTarget().GetDebugger().GetUseExternalEditor() &&
          frame_sc.line_entry.file && frame_sc.line_entry.line != 0) {
        already_shown = Host::OpenFileInExternalEditor(
            frame_sc.line_entry.file, frame_sc.line_entry.line);
      }

      bool show_frame_info = true;
      bool show_source = !already_shown;
      FunctionOptimizationWarning(frame_sp.get());
      return frame_sp->GetStatus(output_stream, show_frame_info, show_source);
    }
    return false;
  } else
    return false;
}

void Thread::FunctionOptimizationWarning(StackFrame *frame) {
  if (frame && frame->HasDebugInformation() &&
      GetProcess()->GetWarningsOptimization()) {
    SymbolContext sc =
        frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextModule);
    GetProcess()->PrintWarningOptimization(sc);
  }
}

lldb::StopInfoSP Thread::GetStopInfo() {
  if (m_destroy_called)
    return m_stop_info_sp;

  ThreadPlanSP completed_plan_sp(GetCompletedPlan());
  ProcessSP process_sp(GetProcess());
  const uint32_t stop_id = process_sp ? process_sp->GetStopID() : UINT32_MAX;

  // Here we select the stop info according to priorirty:
  // - m_stop_info_sp (if not trace) - preset value
  // - completed plan stop info - new value with plan from completed plan stack
  // - m_stop_info_sp (trace stop reason is OK now)
  // - ask GetPrivateStopInfo to set stop info

  bool have_valid_stop_info = m_stop_info_sp &&
      m_stop_info_sp ->IsValid() &&
      m_stop_info_stop_id == stop_id;
  bool have_valid_completed_plan = completed_plan_sp && completed_plan_sp->PlanSucceeded();
  bool plan_overrides_trace =
    have_valid_stop_info && have_valid_completed_plan
    && (m_stop_info_sp->GetStopReason() == eStopReasonTrace);

  if (have_valid_stop_info && !plan_overrides_trace) {
    return m_stop_info_sp;
  } else if (have_valid_completed_plan) {
    return StopInfo::CreateStopReasonWithPlan(
        completed_plan_sp, GetReturnValueObject(), GetExpressionVariable());
  } else {
    GetPrivateStopInfo();
    return m_stop_info_sp;
  }
}

lldb::StopInfoSP Thread::GetPrivateStopInfo() {
  if (m_destroy_called)
    return m_stop_info_sp;

  ProcessSP process_sp(GetProcess());
  if (process_sp) {
    const uint32_t process_stop_id = process_sp->GetStopID();
    if (m_stop_info_stop_id != process_stop_id) {
      if (m_stop_info_sp) {
        if (m_stop_info_sp->IsValid() || IsStillAtLastBreakpointHit() ||
            GetCurrentPlan()->IsVirtualStep())
          SetStopInfo(m_stop_info_sp);
        else
          m_stop_info_sp.reset();
      }

      if (!m_stop_info_sp) {
        if (!CalculateStopInfo())
          SetStopInfo(StopInfoSP());
      }
    }

    // The stop info can be manually set by calling Thread::SetStopInfo()
    // prior to this function ever getting called, so we can't rely on
    // "m_stop_info_stop_id != process_stop_id" as the condition for
    // the if statement below, we must also check the stop info to see
    // if we need to override it. See the header documentation in
    // Process::GetStopInfoOverrideCallback() for more information on
    // the stop info override callback.
    if (m_stop_info_override_stop_id != process_stop_id) {
      m_stop_info_override_stop_id = process_stop_id;
      if (m_stop_info_sp) {
        if (Architecture *arch =
                process_sp->GetTarget().GetArchitecturePlugin())
          arch->OverrideStopInfo(*this);
      }
    }
  }
  return m_stop_info_sp;
}

lldb::StopReason Thread::GetStopReason() {
  lldb::StopInfoSP stop_info_sp(GetStopInfo());
  if (stop_info_sp)
    return stop_info_sp->GetStopReason();
  return eStopReasonNone;
}

bool Thread::StopInfoIsUpToDate() const {
  ProcessSP process_sp(GetProcess());
  if (process_sp)
    return m_stop_info_stop_id == process_sp->GetStopID();
  else
    return true; // Process is no longer around so stop info is always up to
                 // date...
}

void Thread::ResetStopInfo() {
  if (m_stop_info_sp) {
    m_stop_info_sp.reset();
  }
}

void Thread::SetStopInfo(const lldb::StopInfoSP &stop_info_sp) {
  m_stop_info_sp = stop_info_sp;
  if (m_stop_info_sp) {
    m_stop_info_sp->MakeStopInfoValid();
    // If we are overriding the ShouldReportStop, do that here:
    if (m_override_should_notify != eLazyBoolCalculate)
      m_stop_info_sp->OverrideShouldNotify(m_override_should_notify ==
                                           eLazyBoolYes);
  }

  ProcessSP process_sp(GetProcess());
  if (process_sp)
    m_stop_info_stop_id = process_sp->GetStopID();
  else
    m_stop_info_stop_id = UINT32_MAX;
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
  if (log)
    log->Printf("%p: tid = 0x%" PRIx64 ": stop info = %s (stop_id = %u)",
                static_cast<void *>(this), GetID(),
                stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>",
                m_stop_info_stop_id);
}

void Thread::SetShouldReportStop(Vote vote) {
  if (vote == eVoteNoOpinion)
    return;
  else {
    m_override_should_notify = (vote == eVoteYes ? eLazyBoolYes : eLazyBoolNo);
    if (m_stop_info_sp)
      m_stop_info_sp->OverrideShouldNotify(m_override_should_notify ==
                                           eLazyBoolYes);
  }
}

void Thread::SetStopInfoToNothing() {
  // Note, we can't just NULL out the private reason, or the native thread
  // implementation will try to
  // go calculate it again.  For now, just set it to a Unix Signal with an
  // invalid signal number.
  SetStopInfo(
      StopInfo::CreateStopReasonWithSignal(*this, LLDB_INVALID_SIGNAL_NUMBER));
}

bool Thread::ThreadStoppedForAReason(void) {
  return (bool)GetPrivateStopInfo();
}

bool Thread::CheckpointThreadState(ThreadStateCheckpoint &saved_state) {
  saved_state.register_backup_sp.reset();
  lldb::StackFrameSP frame_sp(GetStackFrameAtIndex(0));
  if (frame_sp) {
    lldb::RegisterCheckpointSP reg_checkpoint_sp(
        new RegisterCheckpoint(RegisterCheckpoint::Reason::eExpression));
    if (reg_checkpoint_sp) {
      lldb::RegisterContextSP reg_ctx_sp(frame_sp->GetRegisterContext());
      if (reg_ctx_sp && reg_ctx_sp->ReadAllRegisterValues(*reg_checkpoint_sp))
        saved_state.register_backup_sp = reg_checkpoint_sp;
    }
  }
  if (!saved_state.register_backup_sp)
    return false;

  saved_state.stop_info_sp = GetStopInfo();
  ProcessSP process_sp(GetProcess());
  if (process_sp)
    saved_state.orig_stop_id = process_sp->GetStopID();
  saved_state.current_inlined_depth = GetCurrentInlinedDepth();
  saved_state.m_completed_plan_stack = m_completed_plan_stack;

  return true;
}

bool Thread::RestoreRegisterStateFromCheckpoint(
    ThreadStateCheckpoint &saved_state) {
  if (saved_state.register_backup_sp) {
    lldb::StackFrameSP frame_sp(GetStackFrameAtIndex(0));
    if (frame_sp) {
      lldb::RegisterContextSP reg_ctx_sp(frame_sp->GetRegisterContext());
      if (reg_ctx_sp) {
        bool ret =
            reg_ctx_sp->WriteAllRegisterValues(*saved_state.register_backup_sp);

        // Clear out all stack frames as our world just changed.
        ClearStackFrames();
        reg_ctx_sp->InvalidateIfNeeded(true);
        if (m_unwinder_ap.get())
          m_unwinder_ap->Clear();
        return ret;
      }
    }
  }
  return false;
}

bool Thread::RestoreThreadStateFromCheckpoint(
    ThreadStateCheckpoint &saved_state) {
  if (saved_state.stop_info_sp)
    saved_state.stop_info_sp->MakeStopInfoValid();
  SetStopInfo(saved_state.stop_info_sp);
  GetStackFrameList()->SetCurrentInlinedDepth(
      saved_state.current_inlined_depth);
  m_completed_plan_stack = saved_state.m_completed_plan_stack;
  return true;
}

StateType Thread::GetState() const {
  // If any other threads access this we will need a mutex for it
  std::lock_guard<std::recursive_mutex> guard(m_state_mutex);
  return m_state;
}

void Thread::SetState(StateType state) {
  std::lock_guard<std::recursive_mutex> guard(m_state_mutex);
  m_state = state;
}

void Thread::WillStop() {
  ThreadPlan *current_plan = GetCurrentPlan();

  // FIXME: I may decide to disallow threads with no plans.  In which
  // case this should go to an assert.

  if (!current_plan)
    return;

  current_plan->WillStop();
}

void Thread::SetupForResume() {
  if (GetResumeState() != eStateSuspended) {
    // If we're at a breakpoint push the step-over breakpoint plan.  Do this
    // before
    // telling the current plan it will resume, since we might change what the
    // current
    // plan is.

    lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());
    if (reg_ctx_sp) {
      const addr_t thread_pc = reg_ctx_sp->GetPC();
      BreakpointSiteSP bp_site_sp =
          GetProcess()->GetBreakpointSiteList().FindByAddress(thread_pc);
      if (bp_site_sp) {
        // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the target
        // may not require anything
        // special to step over a breakpoint.

        ThreadPlan *cur_plan = GetCurrentPlan();

        bool push_step_over_bp_plan = false;
        if (cur_plan->GetKind() == ThreadPlan::eKindStepOverBreakpoint) {
          ThreadPlanStepOverBreakpoint *bp_plan =
              (ThreadPlanStepOverBreakpoint *)cur_plan;
          if (bp_plan->GetBreakpointLoadAddress() != thread_pc)
            push_step_over_bp_plan = true;
        } else
          push_step_over_bp_plan = true;

        if (push_step_over_bp_plan) {
          ThreadPlanSP step_bp_plan_sp(new ThreadPlanStepOverBreakpoint(*this));
          if (step_bp_plan_sp) {
            step_bp_plan_sp->SetPrivate(true);

            if (GetCurrentPlan()->RunState() != eStateStepping) {
              ThreadPlanStepOverBreakpoint *step_bp_plan =
                  static_cast<ThreadPlanStepOverBreakpoint *>(
                      step_bp_plan_sp.get());
              step_bp_plan->SetAutoContinue(true);
            }
            QueueThreadPlan(step_bp_plan_sp, false);
          }
        }
      }
    }
  }
}

bool Thread::ShouldResume(StateType resume_state) {
  // At this point clear the completed plan stack.
  m_completed_plan_stack.clear();
  m_discarded_plan_stack.clear();
  m_override_should_notify = eLazyBoolCalculate;

  StateType prev_resume_state = GetTemporaryResumeState();

  SetTemporaryResumeState(resume_state);

  lldb::ThreadSP backing_thread_sp(GetBackingThread());
  if (backing_thread_sp)
    backing_thread_sp->SetTemporaryResumeState(resume_state);

  // Make sure m_stop_info_sp is valid.  Don't do this for threads we suspended
  // in the previous run.
  if (prev_resume_state != eStateSuspended)
    GetPrivateStopInfo();

  // This is a little dubious, but we are trying to limit how often we actually
  // fetch stop info from
  // the target, 'cause that slows down single stepping.  So assume that if we
  // got to the point where
  // we're about to resume, and we haven't yet had to fetch the stop reason,
  // then it doesn't need to know
  // about the fact that we are resuming...
  const uint32_t process_stop_id = GetProcess()->GetStopID();
  if (m_stop_info_stop_id == process_stop_id &&
      (m_stop_info_sp && m_stop_info_sp->IsValid())) {
    StopInfo *stop_info = GetPrivateStopInfo().get();
    if (stop_info)
      stop_info->WillResume(resume_state);
  }

  // Tell all the plans that we are about to resume in case they need to clear
  // any state.
  // We distinguish between the plan on the top of the stack and the lower
  // plans in case a plan needs to do any special business before it runs.

  bool need_to_resume = false;
  ThreadPlan *plan_ptr = GetCurrentPlan();
  if (plan_ptr) {
    need_to_resume = plan_ptr->WillResume(resume_state, true);

    while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) {
      plan_ptr->WillResume(resume_state, false);
    }

    // If the WillResume for the plan says we are faking a resume, then it will
    // have set an appropriate stop info.
    // In that case, don't reset it here.

    if (need_to_resume && resume_state != eStateSuspended) {
      m_stop_info_sp.reset();
    }
  }

  if (need_to_resume) {
    ClearStackFrames();
    // Let Thread subclasses do any special work they need to prior to resuming
    WillResume(resume_state);
  }

  return need_to_resume;
}

void Thread::DidResume() { SetResumeSignal(LLDB_INVALID_SIGNAL_NUMBER); }

void Thread::DidStop() { SetState(eStateStopped); }

bool Thread::ShouldStop(Event *event_ptr) {
  ThreadPlan *current_plan = GetCurrentPlan();

  bool should_stop = true;

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));

  if (GetResumeState() == eStateSuspended) {
    if (log)
      log->Printf("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
                  ", should_stop = 0 (ignore since thread was suspended)",
                  __FUNCTION__, GetID(), GetProtocolID());
    return false;
  }

  if (GetTemporaryResumeState() == eStateSuspended) {
    if (log)
      log->Printf("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
                  ", should_stop = 0 (ignore since thread was suspended)",
                  __FUNCTION__, GetID(), GetProtocolID());
    return false;
  }

  // Based on the current thread plan and process stop info, check if this
  // thread caused the process to stop. NOTE: this must take place before
  // the plan is moved from the current plan stack to the completed plan
  // stack.
  if (!ThreadStoppedForAReason()) {
    if (log)
      log->Printf("Thread::%s for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
                  ", pc = 0x%16.16" PRIx64
                  ", should_stop = 0 (ignore since no stop reason)",
                  __FUNCTION__, GetID(), GetProtocolID(),
                  GetRegisterContext() ? GetRegisterContext()->GetPC()
                                       : LLDB_INVALID_ADDRESS);
    return false;
  }

  if (log) {
    log->Printf("Thread::%s(%p) for tid = 0x%4.4" PRIx64 " 0x%4.4" PRIx64
                ", pc = 0x%16.16" PRIx64,
                __FUNCTION__, static_cast<void *>(this), GetID(),
                GetProtocolID(),
                GetRegisterContext() ? GetRegisterContext()->GetPC()
                                     : LLDB_INVALID_ADDRESS);
    log->Printf("^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^");
    StreamString s;
    s.IndentMore();
    DumpThreadPlans(&s);
    log->Printf("Plan stack initial state:\n%s", s.GetData());
  }

  // The top most plan always gets to do the trace log...
  current_plan->DoTraceLog();

  // First query the stop info's ShouldStopSynchronous.  This handles
  // "synchronous" stop reasons, for example the breakpoint
  // command on internal breakpoints.  If a synchronous stop reason says we
  // should not stop, then we don't have to
  // do any more work on this stop.
  StopInfoSP private_stop_info(GetPrivateStopInfo());
  if (private_stop_info &&
      !private_stop_info->ShouldStopSynchronous(event_ptr)) {
    if (log)
      log->Printf("StopInfo::ShouldStop async callback says we should not "
                  "stop, returning ShouldStop of false.");
    return false;
  }

  // If we've already been restarted, don't query the plans since the state they
  // would examine is not current.
  if (Process::ProcessEventData::GetRestartedFromEvent(event_ptr))
    return false;

  // Before the plans see the state of the world, calculate the current inlined
  // depth.
  GetStackFrameList()->CalculateCurrentInlinedDepth();

  // If the base plan doesn't understand why we stopped, then we have to find a
  // plan that does.
  // If that plan is still working, then we don't need to do any more work.  If
  // the plan that explains
  // the stop is done, then we should pop all the plans below it, and pop it,
  // and then let the plans above it decide
  // whether they still need to do more work.

  bool done_processing_current_plan = false;

  if (!current_plan->PlanExplainsStop(event_ptr)) {
    if (current_plan->TracerExplainsStop()) {
      done_processing_current_plan = true;
      should_stop = false;
    } else {
      // If the current plan doesn't explain the stop, then find one that
      // does and let it handle the situation.
      ThreadPlan *plan_ptr = current_plan;
      while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) {
        if (plan_ptr->PlanExplainsStop(event_ptr)) {
          should_stop = plan_ptr->ShouldStop(event_ptr);

          // plan_ptr explains the stop, next check whether plan_ptr is done, if
          // so, then we should take it
          // and all the plans below it off the stack.

          if (plan_ptr->MischiefManaged()) {
            // We're going to pop the plans up to and including the plan that
            // explains the stop.
            ThreadPlan *prev_plan_ptr = GetPreviousPlan(plan_ptr);

            do {
              if (should_stop)
                current_plan->WillStop();
              PopPlan();
            } while ((current_plan = GetCurrentPlan()) != prev_plan_ptr);
            // Now, if the responsible plan was not "Okay to discard" then we're
            // done,
            // otherwise we forward this to the next plan in the stack below.
            done_processing_current_plan =
                (plan_ptr->IsMasterPlan() && !plan_ptr->OkayToDiscard());
          } else
            done_processing_current_plan = true;

          break;
        }
      }
    }
  }

  if (!done_processing_current_plan) {
    bool over_ride_stop = current_plan->ShouldAutoContinue(event_ptr);

    if (log)
      log->Printf("Plan %s explains stop, auto-continue %i.",
                  current_plan->GetName(), over_ride_stop);

    // We're starting from the base plan, so just let it decide;
    if (PlanIsBasePlan(current_plan)) {
      should_stop = current_plan->ShouldStop(event_ptr);
      if (log)
        log->Printf("Base plan says should stop: %i.", should_stop);
    } else {
      // Otherwise, don't let the base plan override what the other plans say to
      // do, since
      // presumably if there were other plans they would know what to do...
      while (1) {
        if (PlanIsBasePlan(current_plan))
          break;

        should_stop = current_plan->ShouldStop(event_ptr);
        if (log)
          log->Printf("Plan %s should stop: %d.", current_plan->GetName(),
                      should_stop);
        if (current_plan->MischiefManaged()) {
          if (should_stop)
            current_plan->WillStop();

          // If a Master Plan wants to stop, and wants to stick on the stack, we
          // let it.
          // Otherwise, see if the plan's parent wants to stop.

          if (should_stop && current_plan->IsMasterPlan() &&
              !current_plan->OkayToDiscard()) {
            PopPlan();
            break;
          } else {
            PopPlan();

            current_plan = GetCurrentPlan();
            if (current_plan == nullptr) {
              break;
            }
          }
        } else {
          break;
        }
      }
    }

    if (over_ride_stop)
      should_stop = false;
  }

  // One other potential problem is that we set up a master plan, then stop in
  // before it is complete - for instance
  // by hitting a breakpoint during a step-over - then do some step/finish/etc
  // operations that wind up
  // past the end point condition of the initial plan.  We don't want to strand
  // the original plan on the stack,
  // This code clears stale plans off the stack.

  if (should_stop) {
    ThreadPlan *plan_ptr = GetCurrentPlan();

    // Discard the stale plans and all plans below them in the stack,
    // plus move the completed plans to the completed plan stack
    while (!PlanIsBasePlan(plan_ptr)) {
      bool stale = plan_ptr->IsPlanStale();
      ThreadPlan *examined_plan = plan_ptr;
      plan_ptr = GetPreviousPlan(examined_plan);

      if (stale) {
        if (log)
          log->Printf(
              "Plan %s being discarded in cleanup, it says it is already done.",
              examined_plan->GetName());
        while (GetCurrentPlan() != examined_plan) {
          DiscardPlan();
        }
        if (examined_plan->IsPlanComplete()) {
          // plan is complete but does not explain the stop (example: step to a line
          // with breakpoint), let us move the plan to completed_plan_stack anyway
          PopPlan();
        } else
          DiscardPlan();
      }
    }
  }

  if (log) {
    StreamString s;
    s.IndentMore();
    DumpThreadPlans(&s);
    log->Printf("Plan stack final state:\n%s", s.GetData());
    log->Printf("vvvvvvvv Thread::ShouldStop End (returning %i) vvvvvvvv",
                should_stop);
  }
  return should_stop;
}

Vote Thread::ShouldReportStop(Event *event_ptr) {
  StateType thread_state = GetResumeState();
  StateType temp_thread_state = GetTemporaryResumeState();

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));

  if (thread_state == eStateSuspended || thread_state == eStateInvalid) {
    if (log)
      log->Printf("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
                  ": returning vote %i (state was suspended or invalid)",
                  GetID(), eVoteNoOpinion);
    return eVoteNoOpinion;
  }

  if (temp_thread_state == eStateSuspended ||
      temp_thread_state == eStateInvalid) {
    if (log)
      log->Printf(
          "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
          ": returning vote %i (temporary state was suspended or invalid)",
          GetID(), eVoteNoOpinion);
    return eVoteNoOpinion;
  }

  if (!ThreadStoppedForAReason()) {
    if (log)
      log->Printf("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
                  ": returning vote %i (thread didn't stop for a reason.)",
                  GetID(), eVoteNoOpinion);
    return eVoteNoOpinion;
  }

  if (m_completed_plan_stack.size() > 0) {
    // Don't use GetCompletedPlan here, since that suppresses private plans.
    if (log)
      log->Printf("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
                  ": returning vote  for complete stack's back plan",
                  GetID());
    return m_completed_plan_stack.back()->ShouldReportStop(event_ptr);
  } else {
    Vote thread_vote = eVoteNoOpinion;
    ThreadPlan *plan_ptr = GetCurrentPlan();
    while (1) {
      if (plan_ptr->PlanExplainsStop(event_ptr)) {
        thread_vote = plan_ptr->ShouldReportStop(event_ptr);
        break;
      }
      if (PlanIsBasePlan(plan_ptr))
        break;
      else
        plan_ptr = GetPreviousPlan(plan_ptr);
    }
    if (log)
      log->Printf("Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
                  ": returning vote %i for current plan",
                  GetID(), thread_vote);

    return thread_vote;
  }
}

Vote Thread::ShouldReportRun(Event *event_ptr) {
  StateType thread_state = GetResumeState();

  if (thread_state == eStateSuspended || thread_state == eStateInvalid) {
    return eVoteNoOpinion;
  }

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  if (m_completed_plan_stack.size() > 0) {
    // Don't use GetCompletedPlan here, since that suppresses private plans.
    if (log)
      log->Printf("Current Plan for thread %d(%p) (0x%4.4" PRIx64
                  ", %s): %s being asked whether we should report run.",
                  GetIndexID(), static_cast<void *>(this), GetID(),
                  StateAsCString(GetTemporaryResumeState()),
                  m_completed_plan_stack.back()->GetName());

    return m_completed_plan_stack.back()->ShouldReportRun(event_ptr);
  } else {
    if (log)
      log->Printf("Current Plan for thread %d(%p) (0x%4.4" PRIx64
                  ", %s): %s being asked whether we should report run.",
                  GetIndexID(), static_cast<void *>(this), GetID(),
                  StateAsCString(GetTemporaryResumeState()),
                  GetCurrentPlan()->GetName());

    return GetCurrentPlan()->ShouldReportRun(event_ptr);
  }
}

bool Thread::MatchesSpec(const ThreadSpec *spec) {
  return (spec == nullptr) ? true : spec->ThreadPassesBasicTests(*this);
}

void Thread::PushPlan(ThreadPlanSP &thread_plan_sp) {
  if (thread_plan_sp) {
    // If the thread plan doesn't already have a tracer, give it its parent's
    // tracer:
    if (!thread_plan_sp->GetThreadPlanTracer())
      thread_plan_sp->SetThreadPlanTracer(
          m_plan_stack.back()->GetThreadPlanTracer());
    m_plan_stack.push_back(thread_plan_sp);

    thread_plan_sp->DidPush();

    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
    if (log) {
      StreamString s;
      thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull);
      log->Printf("Thread::PushPlan(0x%p): \"%s\", tid = 0x%4.4" PRIx64 ".",
                  static_cast<void *>(this), s.GetData(),
                  thread_plan_sp->GetThread().GetID());
    }
  }
}

void Thread::PopPlan() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));

  if (m_plan_stack.size() <= 1)
    return;
  else {
    ThreadPlanSP &plan = m_plan_stack.back();
    if (log) {
      log->Printf("Popping plan: \"%s\", tid = 0x%4.4" PRIx64 ".",
                  plan->GetName(), plan->GetThread().GetID());
    }
    m_completed_plan_stack.push_back(plan);
    plan->WillPop();
    m_plan_stack.pop_back();
  }
}

void Thread::DiscardPlan() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  if (m_plan_stack.size() > 1) {
    ThreadPlanSP &plan = m_plan_stack.back();
    if (log)
      log->Printf("Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 ".",
                  plan->GetName(), plan->GetThread().GetID());

    m_discarded_plan_stack.push_back(plan);
    plan->WillPop();
    m_plan_stack.pop_back();
  }
}

ThreadPlan *Thread::GetCurrentPlan() {
  // There will always be at least the base plan.  If somebody is mucking with a
  // thread with an empty plan stack, we should assert right away.
  return m_plan_stack.empty() ? nullptr : m_plan_stack.back().get();
}

ThreadPlanSP Thread::GetCompletedPlan() {
  ThreadPlanSP empty_plan_sp;
  if (!m_completed_plan_stack.empty()) {
    for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--) {
      ThreadPlanSP completed_plan_sp;
      completed_plan_sp = m_completed_plan_stack[i];
      if (!completed_plan_sp->GetPrivate())
        return completed_plan_sp;
    }
  }
  return empty_plan_sp;
}

ValueObjectSP Thread::GetReturnValueObject() {
  if (!m_completed_plan_stack.empty()) {
    for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--) {
      ValueObjectSP return_valobj_sp;
      return_valobj_sp = m_completed_plan_stack[i]->GetReturnValueObject();
      if (return_valobj_sp)
        return return_valobj_sp;
    }
  }
  return ValueObjectSP();
}

ExpressionVariableSP Thread::GetExpressionVariable() {
  if (!m_completed_plan_stack.empty()) {
    for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--) {
      ExpressionVariableSP expression_variable_sp;
      expression_variable_sp =
          m_completed_plan_stack[i]->GetExpressionVariable();
      if (expression_variable_sp)
        return expression_variable_sp;
    }
  }
  return ExpressionVariableSP();
}

bool Thread::IsThreadPlanDone(ThreadPlan *plan) {
  if (!m_completed_plan_stack.empty()) {
    for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--) {
      if (m_completed_plan_stack[i].get() == plan)
        return true;
    }
  }
  return false;
}

bool Thread::WasThreadPlanDiscarded(ThreadPlan *plan) {
  if (!m_discarded_plan_stack.empty()) {
    for (int i = m_discarded_plan_stack.size() - 1; i >= 0; i--) {
      if (m_discarded_plan_stack[i].get() == plan)
        return true;
    }
  }
  return false;
}

bool Thread::CompletedPlanOverridesBreakpoint() {
  return (!m_completed_plan_stack.empty()) ;
}

ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) {
  if (current_plan == nullptr)
    return nullptr;

  int stack_size = m_completed_plan_stack.size();
  for (int i = stack_size - 1; i > 0; i--) {
    if (current_plan == m_completed_plan_stack[i].get())
      return m_completed_plan_stack[i - 1].get();
  }

  if (stack_size > 0 && m_completed_plan_stack[0].get() == current_plan) {
    return GetCurrentPlan();
  }

  stack_size = m_plan_stack.size();
  for (int i = stack_size - 1; i > 0; i--) {
    if (current_plan == m_plan_stack[i].get())
      return m_plan_stack[i - 1].get();
  }
  return nullptr;
}

void Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp,
                             bool abort_other_plans) {
  if (abort_other_plans)
    DiscardThreadPlans(true);

  PushPlan(thread_plan_sp);
}

void Thread::EnableTracer(bool value, bool single_stepping) {
  int stack_size = m_plan_stack.size();
  for (int i = 0; i < stack_size; i++) {
    if (m_plan_stack[i]->GetThreadPlanTracer()) {
      m_plan_stack[i]->GetThreadPlanTracer()->EnableTracing(value);
      m_plan_stack[i]->GetThreadPlanTracer()->EnableSingleStep(single_stepping);
    }
  }
}

void Thread::SetTracer(lldb::ThreadPlanTracerSP &tracer_sp) {
  int stack_size = m_plan_stack.size();
  for (int i = 0; i < stack_size; i++)
    m_plan_stack[i]->SetThreadPlanTracer(tracer_sp);
}

bool Thread::DiscardUserThreadPlansUpToIndex(uint32_t thread_index) {
  // Count the user thread plans from the back end to get the number of the one
  // we want
  // to discard:

  uint32_t idx = 0;
  ThreadPlan *up_to_plan_ptr = nullptr;

  for (ThreadPlanSP plan_sp : m_plan_stack) {
    if (plan_sp->GetPrivate())
      continue;
    if (idx == thread_index) {
      up_to_plan_ptr = plan_sp.get();
      break;
    } else
      idx++;
  }

  if (up_to_plan_ptr == nullptr)
    return false;

  DiscardThreadPlansUpToPlan(up_to_plan_ptr);
  return true;
}

void Thread::DiscardThreadPlansUpToPlan(lldb::ThreadPlanSP &up_to_plan_sp) {
  DiscardThreadPlansUpToPlan(up_to_plan_sp.get());
}

void Thread::DiscardThreadPlansUpToPlan(ThreadPlan *up_to_plan_ptr) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  if (log)
    log->Printf("Discarding thread plans for thread tid = 0x%4.4" PRIx64
                ", up to %p",
                GetID(), static_cast<void *>(up_to_plan_ptr));

  int stack_size = m_plan_stack.size();

  // If the input plan is nullptr, discard all plans.  Otherwise make sure this
  // plan is in the
  // stack, and if so discard up to and including it.

  if (up_to_plan_ptr == nullptr) {
    for (int i = stack_size - 1; i > 0; i--)
      DiscardPlan();
  } else {
    bool found_it = false;
    for (int i = stack_size - 1; i > 0; i--) {
      if (m_plan_stack[i].get() == up_to_plan_ptr)
        found_it = true;
    }
    if (found_it) {
      bool last_one = false;
      for (int i = stack_size - 1; i > 0 && !last_one; i--) {
        if (GetCurrentPlan() == up_to_plan_ptr)
          last_one = true;
        DiscardPlan();
      }
    }
  }
}

void Thread::DiscardThreadPlans(bool force) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  if (log) {
    log->Printf("Discarding thread plans for thread (tid = 0x%4.4" PRIx64
                ", force %d)",
                GetID(), force);
  }

  if (force) {
    int stack_size = m_plan_stack.size();
    for (int i = stack_size - 1; i > 0; i--) {
      DiscardPlan();
    }
    return;
  }

  while (1) {
    int master_plan_idx;
    bool discard = true;

    // Find the first master plan, see if it wants discarding, and if yes
    // discard up to it.
    for (master_plan_idx = m_plan_stack.size() - 1; master_plan_idx >= 0;
         master_plan_idx--) {
      if (m_plan_stack[master_plan_idx]->IsMasterPlan()) {
        discard = m_plan_stack[master_plan_idx]->OkayToDiscard();
        break;
      }
    }

    if (discard) {
      // First pop all the dependent plans:
      for (int i = m_plan_stack.size() - 1; i > master_plan_idx; i--) {
        // FIXME: Do we need a finalize here, or is the rule that
        // "PrepareForStop"
        // for the plan leaves it in a state that it is safe to pop the plan
        // with no more notice?
        DiscardPlan();
      }

      // Now discard the master plan itself.
      // The bottom-most plan never gets discarded.  "OkayToDiscard" for it
      // means
      // discard it's dependent plans, but not it...
      if (master_plan_idx > 0) {
        DiscardPlan();
      }
    } else {
      // If the master plan doesn't want to get discarded, then we're done.
      break;
    }
  }
}

bool Thread::PlanIsBasePlan(ThreadPlan *plan_ptr) {
  if (plan_ptr->IsBasePlan())
    return true;
  else if (m_plan_stack.size() == 0)
    return false;
  else
    return m_plan_stack[0].get() == plan_ptr;
}

Status Thread::UnwindInnermostExpression() {
  Status error;
  int stack_size = m_plan_stack.size();

  // If the input plan is nullptr, discard all plans.  Otherwise make sure this
  // plan is in the
  // stack, and if so discard up to and including it.

  for (int i = stack_size - 1; i > 0; i--) {
    if (m_plan_stack[i]->GetKind() == ThreadPlan::eKindCallFunction) {
      DiscardThreadPlansUpToPlan(m_plan_stack[i].get());
      return error;
    }
  }
  error.SetErrorString("No expressions currently active on this thread");
  return error;
}

ThreadPlanSP Thread::QueueFundamentalPlan(bool abort_other_plans) {
  ThreadPlanSP thread_plan_sp(new ThreadPlanBase(*this));
  QueueThreadPlan(thread_plan_sp, abort_other_plans);
  return thread_plan_sp;
}

ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction(
    bool step_over, bool abort_other_plans, bool stop_other_threads) {
  ThreadPlanSP thread_plan_sp(new ThreadPlanStepInstruction(
      *this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
  QueueThreadPlan(thread_plan_sp, abort_other_plans);
  return thread_plan_sp;
}

ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
    bool abort_other_plans, const AddressRange &range,
    const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
    LazyBool step_out_avoids_code_withoug_debug_info) {
  ThreadPlanSP thread_plan_sp;
  thread_plan_sp.reset(new ThreadPlanStepOverRange(
      *this, range, addr_context, stop_other_threads,
      step_out_avoids_code_withoug_debug_info));

  QueueThreadPlan(thread_plan_sp, abort_other_plans);
  return thread_plan_sp;
}

// Call the QueueThreadPlanForStepOverRange method which takes an address range.
ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
    bool abort_other_plans, const LineEntry &line_entry,
    const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
    LazyBool step_out_avoids_code_withoug_debug_info) {
  return QueueThreadPlanForStepOverRange(
      abort_other_plans, line_entry.GetSameLineContiguousAddressRange(),
      addr_context, stop_other_threads,
      step_out_avoids_code_withoug_debug_info);
}

ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
    bool abort_other_plans, const AddressRange &range,
    const SymbolContext &addr_context, const char *step_in_target,
    lldb::RunMode stop_other_threads,
    LazyBool step_in_avoids_code_without_debug_info,
    LazyBool step_out_avoids_code_without_debug_info) {
  ThreadPlanSP thread_plan_sp(
      new ThreadPlanStepInRange(*this, range, addr_context, stop_other_threads,
                                step_in_avoids_code_without_debug_info,
                                step_out_avoids_code_without_debug_info));
  ThreadPlanStepInRange *plan =
      static_cast<ThreadPlanStepInRange *>(thread_plan_sp.get());

  if (step_in_target)
    plan->SetStepInTarget(step_in_target);

  QueueThreadPlan(thread_plan_sp, abort_other_plans);
  return thread_plan_sp;
}

// Call the QueueThreadPlanForStepInRange method which takes an address range.
ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
    bool abort_other_plans, const LineEntry &line_entry,
    const SymbolContext &addr_context, const char *step_in_target,
    lldb::RunMode stop_other_threads,
    LazyBool step_in_avoids_code_without_debug_info,
    LazyBool step_out_avoids_code_without_debug_info) {
  return QueueThreadPlanForStepInRange(
      abort_other_plans, line_entry.GetSameLineContiguousAddressRange(),
      addr_context, step_in_target, stop_other_threads,
      step_in_avoids_code_without_debug_info,
      step_out_avoids_code_without_debug_info);
}

ThreadPlanSP Thread::QueueThreadPlanForStepOut(
    bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
    bool stop_other_threads, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
    LazyBool step_out_avoids_code_without_debug_info) {
  ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
      *this, addr_context, first_insn, stop_other_threads, stop_vote, run_vote,
      frame_idx, step_out_avoids_code_without_debug_info));

  if (thread_plan_sp->ValidatePlan(nullptr)) {
    QueueThreadPlan(thread_plan_sp, abort_other_plans);
    return thread_plan_sp;
  } else {
    return ThreadPlanSP();
  }
}

ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop(
    bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
    bool stop_other_threads, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
    bool continue_to_next_branch) {
  const bool calculate_return_value =
      false; // No need to calculate the return value here.
  ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
      *this, addr_context, first_insn, stop_other_threads, stop_vote, run_vote,
      frame_idx, eLazyBoolNo, continue_to_next_branch, calculate_return_value));

  ThreadPlanStepOut *new_plan =
      static_cast<ThreadPlanStepOut *>(thread_plan_sp.get());
  new_plan->ClearShouldStopHereCallbacks();

  if (thread_plan_sp->ValidatePlan(nullptr)) {
    QueueThreadPlan(thread_plan_sp, abort_other_plans);
    return thread_plan_sp;
  } else {
    return ThreadPlanSP();
  }
}

ThreadPlanSP Thread::QueueThreadPlanForStepThrough(StackID &return_stack_id,
                                                   bool abort_other_plans,
                                                   bool stop_other_threads) {
  ThreadPlanSP thread_plan_sp(
      new ThreadPlanStepThrough(*this, return_stack_id, stop_other_threads));
  if (!thread_plan_sp || !thread_plan_sp->ValidatePlan(nullptr))
    return ThreadPlanSP();

  QueueThreadPlan(thread_plan_sp, abort_other_plans);
  return thread_plan_sp;
}

ThreadPlanSP Thread::QueueThreadPlanForRunToAddress(bool abort_other_plans,
                                                    Address &target_addr,
                                                    bool stop_other_threads) {
  ThreadPlanSP thread_plan_sp(
      new ThreadPlanRunToAddress(*this, target_addr, stop_other_threads));
  QueueThreadPlan(thread_plan_sp, abort_other_plans);
  return thread_plan_sp;
}

ThreadPlanSP Thread::QueueThreadPlanForStepUntil(bool abort_other_plans,
                                                 lldb::addr_t *address_list,
                                                 size_t num_addresses,
                                                 bool stop_other_threads,
                                                 uint32_t frame_idx) {
  ThreadPlanSP thread_plan_sp(new ThreadPlanStepUntil(
      *this, address_list, num_addresses, stop_other_threads, frame_idx));
  QueueThreadPlan(thread_plan_sp, abort_other_plans);
  return thread_plan_sp;
}

lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
    bool abort_other_plans, const char *class_name, bool stop_other_threads) {
  ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name));
  QueueThreadPlan(thread_plan_sp, abort_other_plans);
  // This seems a little funny, but I don't want to have to split up the
  // constructor and the
  // DidPush in the scripted plan, that seems annoying.
  // That means the constructor has to be in DidPush.
  // So I have to validate the plan AFTER pushing it, and then take it off
  // again...
  if (!thread_plan_sp->ValidatePlan(nullptr)) {
    DiscardThreadPlansUpToPlan(thread_plan_sp);
    return ThreadPlanSP();
  } else
    return thread_plan_sp;
}

uint32_t Thread::GetIndexID() const { return m_index_id; }

static void PrintPlanElement(Stream *s, const ThreadPlanSP &plan,
                             lldb::DescriptionLevel desc_level,
                             int32_t elem_idx) {
  s->IndentMore();
  s->Indent();
  s->Printf("Element %d: ", elem_idx);
  plan->GetDescription(s, desc_level);
  s->EOL();
  s->IndentLess();
}

static void PrintPlanStack(Stream *s,
                           const std::vector<lldb::ThreadPlanSP> &plan_stack,
                           lldb::DescriptionLevel desc_level,
                           bool include_internal) {
  int32_t print_idx = 0;
  for (ThreadPlanSP plan_sp : plan_stack) {
    if (include_internal || !plan_sp->GetPrivate()) {
      PrintPlanElement(s, plan_sp, desc_level, print_idx++);
    }
  }
}

void Thread::DumpThreadPlans(Stream *s, lldb::DescriptionLevel desc_level,
                             bool include_internal,
                             bool ignore_boring_threads) const {
  uint32_t stack_size;

  if (ignore_boring_threads) {
    uint32_t stack_size = m_plan_stack.size();
    uint32_t completed_stack_size = m_completed_plan_stack.size();
    uint32_t discarded_stack_size = m_discarded_plan_stack.size();
    if (stack_size == 1 && completed_stack_size == 0 &&
        discarded_stack_size == 0) {
      s->Printf("thread #%u: tid = 0x%4.4" PRIx64 "\n", GetIndexID(), GetID());
      s->IndentMore();
      s->Indent();
      s->Printf("No active thread plans\n");
      s->IndentLess();
      return;
    }
  }

  s->Indent();
  s->Printf("thread #%u: tid = 0x%4.4" PRIx64 ":\n", GetIndexID(), GetID());
  s->IndentMore();
  s->Indent();
  s->Printf("Active plan stack:\n");
  PrintPlanStack(s, m_plan_stack, desc_level, include_internal);

  stack_size = m_completed_plan_stack.size();
  if (stack_size > 0) {
    s->Indent();
    s->Printf("Completed Plan Stack:\n");
    PrintPlanStack(s, m_completed_plan_stack, desc_level, include_internal);
  }

  stack_size = m_discarded_plan_stack.size();
  if (stack_size > 0) {
    s->Indent();
    s->Printf("Discarded Plan Stack:\n");
    PrintPlanStack(s, m_discarded_plan_stack, desc_level, include_internal);
  }

  s->IndentLess();
}

TargetSP Thread::CalculateTarget() {
  TargetSP target_sp;
  ProcessSP process_sp(GetProcess());
  if (process_sp)
    target_sp = process_sp->CalculateTarget();
  return target_sp;
}

ProcessSP Thread::CalculateProcess() { return GetProcess(); }

ThreadSP Thread::CalculateThread() { return shared_from_this(); }

StackFrameSP Thread::CalculateStackFrame() { return StackFrameSP(); }

void Thread::CalculateExecutionContext(ExecutionContext &exe_ctx) {
  exe_ctx.SetContext(shared_from_this());
}

StackFrameListSP Thread::GetStackFrameList() {
  StackFrameListSP frame_list_sp;
  std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
  if (m_curr_frames_sp) {
    frame_list_sp = m_curr_frames_sp;
  } else {
    frame_list_sp.reset(new StackFrameList(*this, m_prev_frames_sp, true));
    m_curr_frames_sp = frame_list_sp;
  }
  return frame_list_sp;
}

void Thread::ClearStackFrames() {
  std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);

  Unwind *unwinder = GetUnwinder();
  if (unwinder)
    unwinder->Clear();

  // Only store away the old "reference" StackFrameList if we got all its
  // frames:
  // FIXME: At some point we can try to splice in the frames we have fetched
  // into
  // the new frame as we make it, but let's not try that now.
  if (m_curr_frames_sp && m_curr_frames_sp->GetAllFramesFetched())
    m_prev_frames_sp.swap(m_curr_frames_sp);
  m_curr_frames_sp.reset();

  m_extended_info.reset();
  m_extended_info_fetched = false;
}

lldb::StackFrameSP Thread::GetFrameWithConcreteFrameIndex(uint32_t unwind_idx) {
  return GetStackFrameList()->GetFrameWithConcreteFrameIndex(unwind_idx);
}

Status Thread::ReturnFromFrameWithIndex(uint32_t frame_idx,
                                        lldb::ValueObjectSP return_value_sp,
                                        bool broadcast) {
  StackFrameSP frame_sp = GetStackFrameAtIndex(frame_idx);
  Status return_error;

  if (!frame_sp) {
    return_error.SetErrorStringWithFormat(
        "Could not find frame with index %d in thread 0x%" PRIx64 ".",
        frame_idx, GetID());
  }

  return ReturnFromFrame(frame_sp, return_value_sp, broadcast);
}

Status Thread::ReturnFromFrame(lldb::StackFrameSP frame_sp,
                               lldb::ValueObjectSP return_value_sp,
                               bool broadcast) {
  Status return_error;

  if (!frame_sp) {
    return_error.SetErrorString("Can't return to a null frame.");
    return return_error;
  }

  Thread *thread = frame_sp->GetThread().get();
  uint32_t older_frame_idx = frame_sp->GetFrameIndex() + 1;
  StackFrameSP older_frame_sp = thread->GetStackFrameAtIndex(older_frame_idx);
  if (!older_frame_sp) {
    return_error.SetErrorString("No older frame to return to.");
    return return_error;
  }

  if (return_value_sp) {
    lldb::ABISP abi = thread->GetProcess()->GetABI();
    if (!abi) {
      return_error.SetErrorString("Could not find ABI to set return value.");
      return return_error;
    }
    SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextFunction);

    // FIXME: ValueObject::Cast doesn't currently work correctly, at least not
    // for scalars.
    // Turn that back on when that works.
    if (/* DISABLES CODE */ (0) && sc.function != nullptr) {
      Type *function_type = sc.function->GetType();
      if (function_type) {
        CompilerType return_type =
            sc.function->GetCompilerType().GetFunctionReturnType();
        if (return_type) {
          StreamString s;
          return_type.DumpTypeDescription(&s);
          ValueObjectSP cast_value_sp = return_value_sp->Cast(return_type);
          if (cast_value_sp) {
            cast_value_sp->SetFormat(eFormatHex);
            return_value_sp = cast_value_sp;
          }
        }
      }
    }

    return_error = abi->SetReturnValueObject(older_frame_sp, return_value_sp);
    if (!return_error.Success())
      return return_error;
  }

  // Now write the return registers for the chosen frame:
  // Note, we can't use ReadAllRegisterValues->WriteAllRegisterValues, since the
  // read & write
  // cook their data

  StackFrameSP youngest_frame_sp = thread->GetStackFrameAtIndex(0);
  if (youngest_frame_sp) {
    lldb::RegisterContextSP reg_ctx_sp(youngest_frame_sp->GetRegisterContext());
    if (reg_ctx_sp) {
      bool copy_success = reg_ctx_sp->CopyFromRegisterContext(
          older_frame_sp->GetRegisterContext());
      if (copy_success) {
        thread->DiscardThreadPlans(true);
        thread->ClearStackFrames();
        if (broadcast && EventTypeHasListeners(eBroadcastBitStackChanged))
          BroadcastEvent(eBroadcastBitStackChanged,
                         new ThreadEventData(this->shared_from_this()));
      } else {
        return_error.SetErrorString("Could not reset register values.");
      }
    } else {
      return_error.SetErrorString("Frame has no register context.");
    }
  } else {
    return_error.SetErrorString("Returned past top frame.");
  }
  return return_error;
}

static void DumpAddressList(Stream &s, const std::vector<Address> &list,
                            ExecutionContextScope *exe_scope) {
  for (size_t n = 0; n < list.size(); n++) {
    s << "\t";
    list[n].Dump(&s, exe_scope, Address::DumpStyleResolvedDescription,
                 Address::DumpStyleSectionNameOffset);
    s << "\n";
  }
}

Status Thread::JumpToLine(const FileSpec &file, uint32_t line,
                          bool can_leave_function, std::string *warnings) {
  ExecutionContext exe_ctx(GetStackFrameAtIndex(0));
  Target *target = exe_ctx.GetTargetPtr();
  TargetSP target_sp = exe_ctx.GetTargetSP();
  RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
  StackFrame *frame = exe_ctx.GetFramePtr();
  const SymbolContext &sc = frame->GetSymbolContext(eSymbolContextFunction);

  // Find candidate locations.
  std::vector<Address> candidates, within_function, outside_function;
  target->GetImages().FindAddressesForLine(target_sp, file, line, sc.function,
                                           within_function, outside_function);

  // If possible, we try and stay within the current function.
  // Within a function, we accept multiple locations (optimized code may do
  // this,
  // there's no solution here so we do the best we can).
  // However if we're trying to leave the function, we don't know how to pick
  // the
  // right location, so if there's more than one then we bail.
  if (!within_function.empty())
    candidates = within_function;
  else if (outside_function.size() == 1 && can_leave_function)
    candidates = outside_function;

  // Check if we got anything.
  if (candidates.empty()) {
    if (outside_function.empty()) {
      return Status("Cannot locate an address for %s:%i.",
                    file.GetFilename().AsCString(), line);
    } else if (outside_function.size() == 1) {
      return Status("%s:%i is outside the current function.",
                    file.GetFilename().AsCString(), line);
    } else {
      StreamString sstr;
      DumpAddressList(sstr, outside_function, target);
      return Status("%s:%i has multiple candidate locations:\n%s",
                    file.GetFilename().AsCString(), line, sstr.GetData());
    }
  }

  // Accept the first location, warn about any others.
  Address dest = candidates[0];
  if (warnings && candidates.size() > 1) {
    StreamString sstr;
    sstr.Printf("%s:%i appears multiple times in this function, selecting the "
                "first location:\n",
                file.GetFilename().AsCString(), line);
    DumpAddressList(sstr, candidates, target);
    *warnings = sstr.GetString();
  }

  if (!reg_ctx->SetPC(dest))
    return Status("Cannot change PC to target address.");

  return Status();
}

void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx,
                                     bool stop_format) {
  ExecutionContext exe_ctx(shared_from_this());
  Process *process = exe_ctx.GetProcessPtr();
  if (process == nullptr)
    return;

  StackFrameSP frame_sp;
  SymbolContext frame_sc;
  if (frame_idx != LLDB_INVALID_FRAME_ID) {
    frame_sp = GetStackFrameAtIndex(frame_idx);
    if (frame_sp) {
      exe_ctx.SetFrameSP(frame_sp);
      frame_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
    }
  }

  const FormatEntity::Entry *thread_format;
  if (stop_format)
    thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadStopFormat();
  else
    thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat();

  assert(thread_format);

  FormatEntity::Format(*thread_format, strm, frame_sp ? &frame_sc : nullptr,
                       &exe_ctx, nullptr, nullptr, false, false);
}

void Thread::SettingsInitialize() {}

void Thread::SettingsTerminate() {}

lldb::addr_t Thread::GetThreadPointer() { return LLDB_INVALID_ADDRESS; }

addr_t Thread::GetThreadLocalData(const ModuleSP module,
                                  lldb::addr_t tls_file_addr) {
  // The default implementation is to ask the dynamic loader for it.
  // This can be overridden for specific platforms.
  DynamicLoader *loader = GetProcess()->GetDynamicLoader();
  if (loader)
    return loader->GetThreadLocalData(module, shared_from_this(),
                                      tls_file_addr);
  else
    return LLDB_INVALID_ADDRESS;
}

bool Thread::SafeToCallFunctions() {
  Process *process = GetProcess().get();
  if (process) {
    SystemRuntime *runtime = process->GetSystemRuntime();
    if (runtime) {
      return runtime->SafeToCallFunctionsOnThisThread(shared_from_this());
    }
  }
  return true;
}

lldb::StackFrameSP
Thread::GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr) {
  return GetStackFrameList()->GetStackFrameSPForStackFramePtr(stack_frame_ptr);
}

const char *Thread::StopReasonAsCString(lldb::StopReason reason) {
  switch (reason) {
  case eStopReasonInvalid:
    return "invalid";
  case eStopReasonNone:
    return "none";
  case eStopReasonTrace:
    return "trace";
  case eStopReasonBreakpoint:
    return "breakpoint";
  case eStopReasonWatchpoint:
    return "watchpoint";
  case eStopReasonSignal:
    return "signal";
  case eStopReasonException:
    return "exception";
  case eStopReasonExec:
    return "exec";
  case eStopReasonPlanComplete:
    return "plan complete";
  case eStopReasonThreadExiting:
    return "thread exiting";
  case eStopReasonInstrumentation:
    return "instrumentation break";
  }

  static char unknown_state_string[64];
  snprintf(unknown_state_string, sizeof(unknown_state_string),
           "StopReason = %i", reason);
  return unknown_state_string;
}

const char *Thread::RunModeAsCString(lldb::RunMode mode) {
  switch (mode) {
  case eOnlyThisThread:
    return "only this thread";
  case eAllThreads:
    return "all threads";
  case eOnlyDuringStepping:
    return "only during stepping";
  }

  static char unknown_state_string[64];
  snprintf(unknown_state_string, sizeof(unknown_state_string), "RunMode = %i",
           mode);
  return unknown_state_string;
}

size_t Thread::GetStatus(Stream &strm, uint32_t start_frame,
                         uint32_t num_frames, uint32_t num_frames_with_source,
                         bool stop_format, bool only_stacks) {

  if (!only_stacks) {
    ExecutionContext exe_ctx(shared_from_this());
    Target *target = exe_ctx.GetTargetPtr();
    Process *process = exe_ctx.GetProcessPtr();
    strm.Indent();
    bool is_selected = false;
    if (process) {
      if (process->GetThreadList().GetSelectedThread().get() == this)
        is_selected = true;
    }
    strm.Printf("%c ", is_selected ? '*' : ' ');
    if (target && target->GetDebugger().GetUseExternalEditor()) {
      StackFrameSP frame_sp = GetStackFrameAtIndex(start_frame);
      if (frame_sp) {
        SymbolContext frame_sc(
            frame_sp->GetSymbolContext(eSymbolContextLineEntry));
        if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.file) {
          Host::OpenFileInExternalEditor(frame_sc.line_entry.file,
                                         frame_sc.line_entry.line);
        }
      }
    }

    DumpUsingSettingsFormat(strm, start_frame, stop_format);
  }

  size_t num_frames_shown = 0;
  if (num_frames > 0) {
    strm.IndentMore();

    const bool show_frame_info = true;
    const bool show_frame_unique = only_stacks;
    const char *selected_frame_marker = nullptr;
    if (num_frames == 1 || only_stacks ||
        (GetID() != GetProcess()->GetThreadList().GetSelectedThread()->GetID()))
      strm.IndentMore();
    else
      selected_frame_marker = "* ";

    num_frames_shown = GetStackFrameList()->GetStatus(
        strm, start_frame, num_frames, show_frame_info, num_frames_with_source,
        show_frame_unique, selected_frame_marker);
    if (num_frames == 1)
      strm.IndentLess();
    strm.IndentLess();
  }
  return num_frames_shown;
}

bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level,
                            bool print_json_thread, bool print_json_stopinfo) {
  const bool stop_format = false;
  DumpUsingSettingsFormat(strm, 0, stop_format);
  strm.Printf("\n");

  StructuredData::ObjectSP thread_info = GetExtendedInfo();

  if (print_json_thread || print_json_stopinfo) {
    if (thread_info && print_json_thread) {
      thread_info->Dump(strm);
      strm.Printf("\n");
    }

    if (print_json_stopinfo && m_stop_info_sp) {
      StructuredData::ObjectSP stop_info = m_stop_info_sp->GetExtendedInfo();
      if (stop_info) {
        stop_info->Dump(strm);
        strm.Printf("\n");
      }
    }

    return true;
  }

  if (thread_info) {
    StructuredData::ObjectSP activity =
        thread_info->GetObjectForDotSeparatedPath("activity");
    StructuredData::ObjectSP breadcrumb =
        thread_info->GetObjectForDotSeparatedPath("breadcrumb");
    StructuredData::ObjectSP messages =
        thread_info->GetObjectForDotSeparatedPath("trace_messages");

    bool printed_activity = false;
    if (activity && activity->GetType() == eStructuredDataTypeDictionary) {
      StructuredData::Dictionary *activity_dict = activity->GetAsDictionary();
      StructuredData::ObjectSP id = activity_dict->GetValueForKey("id");
      StructuredData::ObjectSP name = activity_dict->GetValueForKey("name");
      if (name && name->GetType() == eStructuredDataTypeString && id &&
          id->GetType() == eStructuredDataTypeInteger) {
        strm.Format("  Activity '{0}', {1:x}\n",
                    name->GetAsString()->GetValue(),
                    id->GetAsInteger()->GetValue());
      }
      printed_activity = true;
    }
    bool printed_breadcrumb = false;
    if (breadcrumb && breadcrumb->GetType() == eStructuredDataTypeDictionary) {
      if (printed_activity)
        strm.Printf("\n");
      StructuredData::Dictionary *breadcrumb_dict =
          breadcrumb->GetAsDictionary();
      StructuredData::ObjectSP breadcrumb_text =
          breadcrumb_dict->GetValueForKey("name");
      if (breadcrumb_text &&
          breadcrumb_text->GetType() == eStructuredDataTypeString) {
        strm.Format("  Current Breadcrumb: {0}\n",
                    breadcrumb_text->GetAsString()->GetValue());
      }
      printed_breadcrumb = true;
    }
    if (messages && messages->GetType() == eStructuredDataTypeArray) {
      if (printed_breadcrumb)
        strm.Printf("\n");
      StructuredData::Array *messages_array = messages->GetAsArray();
      const size_t msg_count = messages_array->GetSize();
      if (msg_count > 0) {
        strm.Printf("  %zu trace messages:\n", msg_count);
        for (size_t i = 0; i < msg_count; i++) {
          StructuredData::ObjectSP message = messages_array->GetItemAtIndex(i);
          if (message && message->GetType() == eStructuredDataTypeDictionary) {
            StructuredData::Dictionary *message_dict =
                message->GetAsDictionary();
            StructuredData::ObjectSP message_text =
                message_dict->GetValueForKey("message");
            if (message_text &&
                message_text->GetType() == eStructuredDataTypeString) {
              strm.Format("    {0}\n", message_text->GetAsString()->GetValue());
            }
          }
        }
      }
    }
  }

  return true;
}

size_t Thread::GetStackFrameStatus(Stream &strm, uint32_t first_frame,
                                   uint32_t num_frames, bool show_frame_info,
                                   uint32_t num_frames_with_source) {
  return GetStackFrameList()->GetStatus(
      strm, first_frame, num_frames, show_frame_info, num_frames_with_source);
}

Unwind *Thread::GetUnwinder() {
  if (!m_unwinder_ap) {
    const ArchSpec target_arch(CalculateTarget()->GetArchitecture());
    const llvm::Triple::ArchType machine = target_arch.GetMachine();
    switch (machine) {
    case llvm::Triple::x86_64:
    case llvm::Triple::x86:
    case llvm::Triple::arm:
    case llvm::Triple::aarch64:
    case llvm::Triple::thumb:
    case llvm::Triple::mips:
    case llvm::Triple::mipsel:
    case llvm::Triple::mips64:
    case llvm::Triple::mips64el:
    case llvm::Triple::ppc:
    case llvm::Triple::ppc64:
    case llvm::Triple::ppc64le:
    case llvm::Triple::systemz:
    case llvm::Triple::hexagon:
      m_unwinder_ap.reset(new UnwindLLDB(*this));
      break;

    default:
      if (target_arch.GetTriple().getVendor() == llvm::Triple::Apple)
        m_unwinder_ap.reset(new UnwindMacOSXFrameBackchain(*this));
      break;
    }
  }
  return m_unwinder_ap.get();
}

void Thread::Flush() {
  ClearStackFrames();
  m_reg_context_sp.reset();
}

bool Thread::IsStillAtLastBreakpointHit() {
  // If we are currently stopped at a breakpoint, always return that stopinfo
  // and don't reset it.
  // This allows threads to maintain their breakpoint stopinfo, such as when
  // thread-stepping in
  // multithreaded programs.
  if (m_stop_info_sp) {
    StopReason stop_reason = m_stop_info_sp->GetStopReason();
    if (stop_reason == lldb::eStopReasonBreakpoint) {
      uint64_t value = m_stop_info_sp->GetValue();
      lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());
      if (reg_ctx_sp) {
        lldb::addr_t pc = reg_ctx_sp->GetPC();
        BreakpointSiteSP bp_site_sp =
            GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
        if (bp_site_sp && static_cast<break_id_t>(value) == bp_site_sp->GetID())
          return true;
      }
    }
  }
  return false;
}

Status Thread::StepIn(bool source_step,
                      LazyBool step_in_avoids_code_without_debug_info,
                      LazyBool step_out_avoids_code_without_debug_info)

{
  Status error;
  Process *process = GetProcess().get();
  if (StateIsStoppedState(process->GetState(), true)) {
    StackFrameSP frame_sp = GetStackFrameAtIndex(0);
    ThreadPlanSP new_plan_sp;
    const lldb::RunMode run_mode = eOnlyThisThread;
    const bool abort_other_plans = false;

    if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
      SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
      new_plan_sp = QueueThreadPlanForStepInRange(
          abort_other_plans, sc.line_entry, sc, nullptr, run_mode,
          step_in_avoids_code_without_debug_info,
          step_out_avoids_code_without_debug_info);
    } else {
      new_plan_sp = QueueThreadPlanForStepSingleInstruction(
          false, abort_other_plans, run_mode);
    }

    new_plan_sp->SetIsMasterPlan(true);
    new_plan_sp->SetOkayToDiscard(false);

    // Why do we need to set the current thread by ID here???
    process->GetThreadList().SetSelectedThreadByID(GetID());
    error = process->Resume();
  } else {
    error.SetErrorString("process not stopped");
  }
  return error;
}

Status Thread::StepOver(bool source_step,
                        LazyBool step_out_avoids_code_without_debug_info) {
  Status error;
  Process *process = GetProcess().get();
  if (StateIsStoppedState(process->GetState(), true)) {
    StackFrameSP frame_sp = GetStackFrameAtIndex(0);
    ThreadPlanSP new_plan_sp;

    const lldb::RunMode run_mode = eOnlyThisThread;
    const bool abort_other_plans = false;

    if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
      SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
      new_plan_sp = QueueThreadPlanForStepOverRange(
          abort_other_plans, sc.line_entry, sc, run_mode,
          step_out_avoids_code_without_debug_info);
    } else {
      new_plan_sp = QueueThreadPlanForStepSingleInstruction(
          true, abort_other_plans, run_mode);
    }

    new_plan_sp->SetIsMasterPlan(true);
    new_plan_sp->SetOkayToDiscard(false);

    // Why do we need to set the current thread by ID here???
    process->GetThreadList().SetSelectedThreadByID(GetID());
    error = process->Resume();
  } else {
    error.SetErrorString("process not stopped");
  }
  return error;
}

Status Thread::StepOut() {
  Status error;
  Process *process = GetProcess().get();
  if (StateIsStoppedState(process->GetState(), true)) {
    const bool first_instruction = false;
    const bool stop_other_threads = false;
    const bool abort_other_plans = false;

    ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut(
        abort_other_plans, nullptr, first_instruction, stop_other_threads,
        eVoteYes, eVoteNoOpinion, 0));

    new_plan_sp->SetIsMasterPlan(true);
    new_plan_sp->SetOkayToDiscard(false);

    // Why do we need to set the current thread by ID here???
    process->GetThreadList().SetSelectedThreadByID(GetID());
    error = process->Resume();
  } else {
    error.SetErrorString("process not stopped");
  }
  return error;
}
