//===-- 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) {
        ArchSpec::StopInfoOverrideCallbackType callback =
            GetProcess()->GetStopInfoOverrideCallback();
        if (callback)
          callback(*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::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;
}
