//===-- Thread.cpp --------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/Thread.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/Interfaces/ScriptedFrameInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/ScriptedThreadPlan.h"
#include "lldb/Target/StackFrameRecognizer.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/ThreadPlanRunToAddress.h"
#include "lldb/Target/ThreadPlanStack.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/UnwindLLDB.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/ScriptedMetadata.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/ValueObject/ValueObjectConstResult.h"
#include "lldb/lldb-enumerations.h"

#include "llvm/Support/MathExtras.h"

#include <memory>
#include <optional>

using namespace lldb;
using namespace lldb_private;

ThreadProperties &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 ThreadProperties *g_settings_ptr = new ThreadProperties(true);
  return *g_settings_ptr;
}

#define LLDB_PROPERTIES_thread
#include "TargetProperties.inc"

enum {
#define LLDB_PROPERTIES_thread
#include "TargetPropertiesEnum.inc"
};

class ThreadOptionValueProperties
    : public Cloneable<ThreadOptionValueProperties, OptionValueProperties> {
public:
  ThreadOptionValueProperties(llvm::StringRef name) : Cloneable(name) {}

  const Property *
  GetPropertyAtIndex(size_t idx,
                     const ExecutionContext *exe_ctx) 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 = std::make_shared<ThreadOptionValueProperties>("thread");
    m_collection_sp->Initialize(g_thread_properties);
  } else
    m_collection_sp =
        OptionValueProperties::CreateLocalCopy(Thread::GetGlobalProperties());
}

ThreadProperties::~ThreadProperties() = default;

const RegularExpression *ThreadProperties::GetSymbolsToAvoidRegexp() {
  const uint32_t idx = ePropertyStepAvoidRegex;
  return GetPropertyAtIndexAs<const RegularExpression *>(idx);
}

FileSpecList ThreadProperties::GetLibrariesToAvoid() const {
  const uint32_t idx = ePropertyStepAvoidLibraries;
  return GetPropertyAtIndexAs<FileSpecList>(idx, {});
}

bool ThreadProperties::GetTraceEnabledState() const {
  const uint32_t idx = ePropertyEnableThreadTrace;
  return GetPropertyAtIndexAs<bool>(
      idx, g_thread_properties[idx].default_uint_value != 0);
}

bool ThreadProperties::GetStepInAvoidsNoDebug() const {
  const uint32_t idx = ePropertyStepInAvoidsNoDebug;
  return GetPropertyAtIndexAs<bool>(
      idx, g_thread_properties[idx].default_uint_value != 0);
}

bool ThreadProperties::GetStepOutAvoidsNoDebug() const {
  const uint32_t idx = ePropertyStepOutAvoidsNoDebug;
  return GetPropertyAtIndexAs<bool>(
      idx, g_thread_properties[idx].default_uint_value != 0);
}

uint64_t ThreadProperties::GetMaxBacktraceDepth() const {
  const uint32_t idx = ePropertyMaxBacktraceDepth;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_thread_properties[idx].default_uint_value);
}

uint64_t ThreadProperties::GetSingleThreadPlanTimeout() const {
  const uint32_t idx = ePropertySingleThreadPlanTimeout;
  return GetPropertyAtIndexAs<uint64_t>(
      idx, g_thread_properties[idx].default_uint_value);
}

// Thread Event Data

llvm::StringRef Thread::ThreadEventData::GetFlavorString() {
  return "Thread::ThreadEventData";
}

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

llvm::StringRef Thread::GetStaticBroadcasterClass() {
  static constexpr llvm::StringLiteral 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().str()),
      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_should_run_before_public_stop(false),
      m_stopped_at_unexecuted_bp(LLDB_INVALID_ADDRESS),
      m_index_id(use_invalid_index_id ? LLDB_INVALID_INDEX32
                                      : process.GetNextThreadIndexID(tid)),
      m_reg_context_sp(), m_state(eStateUnloaded), m_state_mutex(),
      m_frame_mutex(), m_curr_frames_sp(), m_prev_frames_sp(),
      m_prev_framezero_pc(), m_resume_signal(LLDB_INVALID_SIGNAL_NUMBER),
      m_resume_state(eStateRunning), m_temporary_resume_state(eStateRunning),
      m_unwinder_up(), m_destroy_called(false),
      m_override_should_notify(eLazyBoolCalculate),
      m_extended_info_fetched(false), m_extended_info() {
  Log *log = GetLog(LLDBLog::Object);
  LLDB_LOGF(log, "%p Thread::Thread(tid = 0x%4.4" PRIx64 ")",
            static_cast<void *>(this), GetID());

  CheckInWithManager();
}

Thread::~Thread() {
  Log *log = GetLog(LLDBLog::Object);
  LLDB_LOGF(log, "%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
  /// DestroyThread in its destructor.
  assert(m_destroy_called);
}

void Thread::DestroyThread() {
  m_destroy_called = true;
  m_stop_info_sp.reset();
  m_reg_context_sp.reset();
  m_unwinder_up.reset();
  std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
  m_curr_frames_sp.reset();
  m_prev_frames_sp.reset();
  m_unwinder_frames_sp.reset();
  m_frame_providers.clear();
  m_provider_chain_ids.clear();
  m_frame_lists_by_id.clear();
  m_prev_framezero_pc.reset();
}

void Thread::BroadcastSelectedFrameChange(StackID &new_frame_id) {
  if (EventTypeHasListeners(eBroadcastBitSelectedFrameChanged)) {
    auto data_sp =
        std::make_shared<ThreadEventData>(shared_from_this(), new_frame_id);
    BroadcastEvent(eBroadcastBitSelectedFrameChanged, data_sp);
  }
}

lldb::StackFrameSP
Thread::GetSelectedFrame(SelectMostRelevant select_most_relevant) {
  StackFrameListSP stack_frame_list_sp(GetStackFrameList());
  StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex(
      stack_frame_list_sp->GetSelectedFrameIndex(select_most_relevant));
  FrameSelectedCallback(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());
  FrameSelectedCallback(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());
    FrameSelectedCallback(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(DoNoSelectMostRelevantFrame);
    if (frame_sp) {
      bool already_shown = false;
      SymbolContext frame_sc(
          frame_sp->GetSymbolContext(eSymbolContextLineEntry));
      const Debugger &debugger = GetProcess()->GetTarget().GetDebugger();
      if (debugger.GetUseExternalEditor() && frame_sc.line_entry.GetFile() &&
          frame_sc.line_entry.line != 0) {
        if (llvm::Error e = Host::OpenFileInExternalEditor(
                debugger.GetExternalEditor(), frame_sc.line_entry.GetFile(),
                frame_sc.line_entry.line)) {
          LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e),
                         "OpenFileInExternalEditor failed: {0}");
        } else {
          already_shown = true;
        }
      }

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

void Thread::FrameSelectedCallback(StackFrame *frame) {
  if (!frame)
    return;

  if (frame->HasDebugInformation() &&
      (GetProcess()->GetWarningsOptimization() ||
       GetProcess()->GetWarningsUnsupportedLanguage())) {
    SymbolContext sc =
        frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextModule);
    GetProcess()->PrintWarningOptimization(sc);
    GetProcess()->PrintWarningUnsupportedLanguage(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_failed = 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 && !plan_failed) {
    return m_stop_info_sp;
  } else if (completed_plan_sp) {
    return StopInfo::CreateStopReasonWithPlan(
        completed_plan_sp, GetReturnValueObject(), GetExpressionVariable());
  } else {
    GetPrivateStopInfo();
    return m_stop_info_sp;
  }
}

void Thread::CalculatePublicStopInfo() {
  ResetStopInfo();
  SetStopInfo(GetStopInfo());
}

lldb::StopInfoSP Thread::GetPrivateStopInfo(bool calculate) {
  if (!calculate)
    return m_stop_info_sp;

  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) {
      // We preserve the old stop info for a variety of reasons:
      // 1) Someone has already updated it by the time we get here
      // 2) We didn't get to execute the breakpoint instruction we stopped at
      // 3) This is a virtual step so we didn't actually run
      // 4) If this thread wasn't allowed to run the last time round.
      if (m_stop_info_sp) {
        if (m_stop_info_sp->IsValid() || IsStillAtLastBreakpointHit() ||
            GetCurrentPlan()->IsVirtualStep()
            || GetTemporaryResumeState() == eStateSuspended)
          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
    // Architecture::OverrideStopInfo() 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 (const Architecture *arch =
                process_sp->GetTarget().GetArchitecturePlugin())
          arch->OverrideStopInfo(*this);
      }
    }
  }

  // If we were resuming the process and it was interrupted,
  // return no stop reason.  This thread would like to resume.
  if (m_stop_info_sp && m_stop_info_sp->WasContinueInterrupted(*this))
    return {};

  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 = GetLog(LLDBLog::Thread);
  LLDB_LOGF(log, "%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() { 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_checkpoint =
      GetPlans().CheckpointCompletedPlans();
  saved_state.stopped_at_unexecuted_bp = m_stopped_at_unexecuted_bp;

  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_up)
          m_unwinder_up->Clear();
        return ret;
      }
    }
  }
  return false;
}

void 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);
  GetPlans().RestoreCompletedPlanCheckpoint(
      saved_state.m_completed_plan_checkpoint);
  m_stopped_at_unexecuted_bp = saved_state.stopped_at_unexecuted_bp;
}

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

std::string Thread::GetStopDescription() {
  StackFrameSP frame_sp = GetStackFrameAtIndex(0);

  if (!frame_sp)
    return GetStopDescriptionRaw();

  auto recognized_frame_sp = frame_sp->GetRecognizedFrame();

  if (!recognized_frame_sp)
    return GetStopDescriptionRaw();

  std::string recognized_stop_description =
      recognized_frame_sp->GetStopDescription();

  if (!recognized_stop_description.empty())
    return recognized_stop_description;

  return GetStopDescriptionRaw();
}

std::string Thread::GetStopDescriptionRaw() {
  StopInfoSP stop_info_sp = GetStopInfo();
  std::string raw_stop_description;
  if (stop_info_sp && stop_info_sp->IsValid()) {
    raw_stop_description = stop_info_sp->GetDescription();
    assert((!raw_stop_description.empty() ||
            stop_info_sp->GetStopReason() == eStopReasonNone) &&
           "StopInfo returned an empty description.");
  }
  return raw_stop_description;
}

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

bool Thread::SetupToStepOverBreakpointIfNeeded(RunDirection direction) {
  if (GetResumeState() != eStateSuspended) {
    // First check whether this thread is going to "actually" resume at all.
    // For instance, if we're stepping from one level to the next of an
    // virtual inlined call stack, we just change the inlined call stack index
    // without actually running this thread.  In that case, for this thread we
    // shouldn't push a step over breakpoint plan or do that work.
    if (GetCurrentPlan()->IsVirtualStep())
      return false;

    // 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());
    ProcessSP process_sp(GetProcess());
    if (reg_ctx_sp && process_sp && direction == eRunForward) {
      const addr_t thread_pc = reg_ctx_sp->GetPC();
      BreakpointSiteSP bp_site_sp =
          process_sp->GetBreakpointSiteList().FindByAddress(thread_pc);
      // If we're at a BreakpointSite which we have either
      //   1. already triggered/hit, or
      //   2. the Breakpoint was added while stopped, or the pc was moved
      //      to this BreakpointSite
      // Step past the breakpoint before resuming.
      // If we stopped at a breakpoint instruction/BreakpointSite location
      // without hitting it, and we're still at that same address on
      // resuming, then we want to hit the BreakpointSite when we resume.
      if (bp_site_sp && m_stopped_at_unexecuted_bp != thread_pc) {
        // 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);
            return true;
          }
        }
      }
    }
  }
  return false;
}

bool Thread::ShouldResume(StateType resume_state) {
  // At this point clear the completed plan stack.
  GetPlans().WillResume();
  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())) {
    if (StopInfoSP stop_info_sp = GetPrivateStopInfo())
      stop_info_sp->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();

    // Only reset m_stopped_at_unexecuted_bp if the thread is actually being
    // resumed. Otherwise, the state of a suspended thread may not be restored
    // correctly at the next stop. For example, this could happen if the thread
    // is suspended by ThreadPlanStepOverBreakpoint in another thread, which
    // temporarily disables the breakpoint that the suspended thread has reached
    // but not yet executed.
    if (resume_state != eStateSuspended)
      m_stopped_at_unexecuted_bp = LLDB_INVALID_ADDRESS;

    // 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);
  // This will get recomputed each time when we stop.
  SetShouldRunBeforePublicStop(false);
}

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

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

  bool should_stop = true;

  Log *log = GetLog(LLDBLog::Step);

  if (GetResumeState() == eStateSuspended) {
    LLDB_LOGF(log,
              "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) {
    LLDB_LOGF(log,
              "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()) {
    LLDB_LOGF(log,
              "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;
  }

  // Clear the "must run me before stop" if it was set:
  SetShouldRunBeforePublicStop(false);

  if (log) {
    LLDB_LOGF(log,
              "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);
    LLDB_LOGF(log, "^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^");
    StreamString s;
    s.IndentMore();
    GetProcess()->DumpThreadPlansForTID(
        s, GetID(), eDescriptionLevelVerbose, true /* internal */,
        false /* condense_trivial */, true /* skip_unreported */);
    LLDB_LOGF(log, "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)) {
    LLDB_LOGF(log, "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 {
      // Leaf plan that does not explain the stop should be popped.
      // The plan should be push itself later again before resuming to stay
      // as leaf.
      if (current_plan->IsLeafPlan())
        PopPlan();

      // 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)) {
          LLDB_LOGF(log, "Plan %s explains stop.", plan_ptr->GetName());

          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->IsControllingPlan() && !plan_ptr->OkayToDiscard());
          } else {
            bool should_force_run = plan_ptr->ShouldRunBeforePublicStop();
            if (should_force_run) {
              SetShouldRunBeforePublicStop(true);
              should_stop = false;
            }
            done_processing_current_plan = true;
          }
          break;
        }
      }
    }
  }

  if (!done_processing_current_plan) {
    bool override_stop = false;

    // We're starting from the base plan, so just let it decide;
    if (current_plan->IsBasePlan()) {
      should_stop = current_plan->ShouldStop(event_ptr);
      LLDB_LOGF(log, "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 (true) {
        if (current_plan->IsBasePlan())
          break;

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

          if (current_plan->ShouldAutoContinue(event_ptr)) {
            override_stop = true;
            LLDB_LOGF(log, "Plan %s auto-continue: true.",
                      current_plan->GetName());
          }

          // If a Controlling Plan wants to stop, we let it. Otherwise, see if
          // the plan's parent wants to stop.

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

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

    if (override_stop)
      should_stop = false;
  }

  // One other potential problem is that we set up a controlling 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 (!plan_ptr->IsBasePlan()) {
      bool stale = plan_ptr->IsPlanStale();
      ThreadPlan *examined_plan = plan_ptr;
      plan_ptr = GetPreviousPlan(examined_plan);

      if (stale) {
        LLDB_LOGF(
            log,
            "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();
    GetProcess()->DumpThreadPlansForTID(
        s, GetID(), eDescriptionLevelVerbose, true /* internal */,
        false /* condense_trivial */, true /* skip_unreported */);
    LLDB_LOGF(log, "Plan stack final state:\n%s", s.GetData());
    LLDB_LOGF(log, "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 = GetLog(LLDBLog::Step);

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

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

  if (GetPlans().AnyCompletedPlans()) {
    // Pass skip_private = false to GetCompletedPlan, since we want to ask
    // the last plan, regardless of whether it is private or not.
    LLDB_LOGF(log,
              "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64
              ": returning vote for complete stack's back plan",
              GetID());
    return GetPlans().GetCompletedPlan(false)->ShouldReportStop(event_ptr);
  } else {
    Vote thread_vote = eVoteNoOpinion;
    ThreadPlan *plan_ptr = GetCurrentPlan();
    while (true) {
      if (plan_ptr->PlanExplainsStop(event_ptr)) {
        thread_vote = plan_ptr->ShouldReportStop(event_ptr);
        break;
      }
      if (plan_ptr->IsBasePlan())
        break;
      else
        plan_ptr = GetPreviousPlan(plan_ptr);
    }
    LLDB_LOGF(log,
              "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 = GetLog(LLDBLog::Step);
  if (GetPlans().AnyCompletedPlans()) {
    // Pass skip_private = false to GetCompletedPlan, since we want to ask
    // the last plan, regardless of whether it is private or not.
    LLDB_LOGF(log,
              "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()),
              GetCompletedPlan()->GetName());

    return GetPlans().GetCompletedPlan(false)->ShouldReportRun(event_ptr);
  } else {
    LLDB_LOGF(log,
              "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);
}

ThreadPlanStack &Thread::GetPlans() const {
  ThreadPlanStack *plans = GetProcess()->FindThreadPlans(GetID());
  if (plans)
    return *plans;

  // History threads don't have a thread plan, but they do ask get asked to
  // describe themselves, which usually involves pulling out the stop reason.
  // That in turn will check for a completed plan on the ThreadPlanStack.
  // Instead of special-casing at that point, we return a Stack with a
  // ThreadPlanNull as its base plan.  That will give the right answers to the
  // queries GetDescription makes, and only assert if you try to run the thread.
  if (!m_null_plan_stack_up)
    m_null_plan_stack_up = std::make_unique<ThreadPlanStack>(*this, true);
  return *m_null_plan_stack_up;
}

void Thread::PushPlan(ThreadPlanSP thread_plan_sp) {
  assert(thread_plan_sp && "Don't push an empty thread plan.");

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

  GetPlans().PushPlan(std::move(thread_plan_sp));
}

void Thread::PopPlan() {
  Log *log = GetLog(LLDBLog::Step);
  ThreadPlanSP popped_plan_sp = GetPlans().PopPlan();
  if (log) {
    LLDB_LOGF(log, "Popping plan: \"%s\", tid = 0x%4.4" PRIx64 ".",
              popped_plan_sp->GetName(), popped_plan_sp->GetThread().GetID());
  }
}

void Thread::DiscardPlan() {
  Log *log = GetLog(LLDBLog::Step);
  ThreadPlanSP discarded_plan_sp = GetPlans().DiscardPlan();

  LLDB_LOGF(log, "Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 ".",
            discarded_plan_sp->GetName(),
            discarded_plan_sp->GetThread().GetID());
}

void Thread::AutoCompleteThreadPlans(CompletionRequest &request) const {
  const ThreadPlanStack &plans = GetPlans();
  if (!plans.AnyPlans())
    return;

  // Iterate from the second plan (index: 1) to skip the base plan.
  ThreadPlanSP p;
  uint32_t i = 1;
  while ((p = plans.GetPlanByIndex(i, false))) {
    StreamString strm;
    p->GetDescription(&strm, eDescriptionLevelInitial);
    request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
    i++;
  }
}

ThreadPlan *Thread::GetCurrentPlan() const {
  return GetPlans().GetCurrentPlan().get();
}

ThreadPlanSP Thread::GetCompletedPlan() const {
  return GetPlans().GetCompletedPlan();
}

ValueObjectSP Thread::GetReturnValueObject() const {
  return GetPlans().GetReturnValueObject();
}

ExpressionVariableSP Thread::GetExpressionVariable() const {
  return GetPlans().GetExpressionVariable();
}

bool Thread::IsThreadPlanDone(ThreadPlan *plan) const {
  return GetPlans().IsPlanDone(plan);
}

bool Thread::WasThreadPlanDiscarded(ThreadPlan *plan) const {
  return GetPlans().WasPlanDiscarded(plan);
}

bool Thread::CompletedPlanOverridesBreakpoint() const {
  return GetPlans().AnyCompletedPlans();
}

ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) const{
  return GetPlans().GetPreviousPlan(current_plan);
}

Status Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp,
                               bool abort_other_plans) {
  Status status;
  StreamString s;
  if (!thread_plan_sp->ValidatePlan(&s)) {
    DiscardThreadPlansUpToPlan(thread_plan_sp);
    thread_plan_sp.reset();
    return Status(s.GetString().str());
  }

  if (abort_other_plans)
    DiscardThreadPlans(true);

  PushPlan(thread_plan_sp);

  // 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(&s)) {
    DiscardThreadPlansUpToPlan(thread_plan_sp);
    thread_plan_sp.reset();
    return Status(s.GetString().str());
  }

  return status;
}

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

  ThreadPlan *up_to_plan_ptr = GetPlans().GetPlanByIndex(plan_index).get();
  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 = GetLog(LLDBLog::Step);
  LLDB_LOGF(log,
            "Discarding thread plans for thread tid = 0x%4.4" PRIx64
            ", up to %p",
            GetID(), static_cast<void *>(up_to_plan_ptr));
  GetPlans().DiscardPlansUpToPlan(up_to_plan_ptr);
}

void Thread::DiscardThreadPlans(bool force) {
  Log *log = GetLog(LLDBLog::Step);
  if (log) {
    LLDB_LOGF(log,
              "Discarding thread plans for thread (tid = 0x%4.4" PRIx64
              ", force %d)",
              GetID(), force);
  }

  if (force) {
    GetPlans().DiscardAllPlans();
    return;
  }
  GetPlans().DiscardConsultingControllingPlans();
}

Status Thread::UnwindInnermostExpression() {
  Status error;
  ThreadPlan *innermost_expr_plan = GetPlans().GetInnermostExpression();
  if (!innermost_expr_plan) {
    error = Status::FromErrorString(
        "No expressions currently active on this thread");
    return error;
  }
  DiscardThreadPlansUpToPlan(innermost_expr_plan);
  return error;
}

ThreadPlanSP Thread::QueueBasePlan(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,
    Status &status) {
  ThreadPlanSP thread_plan_sp(new ThreadPlanStepInstruction(
      *this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
  status = 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,
    Status &status, LazyBool step_out_avoids_code_withoug_debug_info) {
  ThreadPlanSP thread_plan_sp;
  thread_plan_sp = std::make_shared<ThreadPlanStepOverRange>(
      *this, range, addr_context, stop_other_threads,
      step_out_avoids_code_withoug_debug_info);

  status = 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,
    Status &status, LazyBool step_out_avoids_code_withoug_debug_info) {
  const bool include_inlined_functions = true;
  auto address_range =
      line_entry.GetSameLineContiguousAddressRange(include_inlined_functions);
  return QueueThreadPlanForStepOverRange(
      abort_other_plans, address_range, addr_context, stop_other_threads,
      status, 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, Status &status,
    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, step_in_target, stop_other_threads,
      step_in_avoids_code_without_debug_info,
      step_out_avoids_code_without_debug_info));
  status = 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, Status &status,
    LazyBool step_in_avoids_code_without_debug_info,
    LazyBool step_out_avoids_code_without_debug_info) {
  const bool include_inlined_functions = false;
  return QueueThreadPlanForStepInRange(
      abort_other_plans,
      line_entry.GetSameLineContiguousAddressRange(include_inlined_functions),
      addr_context, step_in_target, stop_other_threads, status,
      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 report_stop_vote, Vote report_run_vote,
    uint32_t frame_idx, Status &status,
    LazyBool step_out_avoids_code_without_debug_info) {
  ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
      *this, addr_context, first_insn, stop_other_threads, report_stop_vote,
      report_run_vote, frame_idx, step_out_avoids_code_without_debug_info));

  status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
  return thread_plan_sp;
}

ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop(
    bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
    bool stop_other_threads, Vote report_stop_vote, Vote report_run_vote,
    uint32_t frame_idx, Status &status, 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, stop_other_threads, report_stop_vote, report_run_vote, frame_idx,
      continue_to_next_branch, calculate_return_value));

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

  status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
  return thread_plan_sp;
}

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

  status = 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,
                                                    Status &status) {
  ThreadPlanSP thread_plan_sp(
      new ThreadPlanRunToAddress(*this, target_addr, stop_other_threads));

  status = 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, Status &status) {
  ThreadPlanSP thread_plan_sp(new ThreadPlanStepUntil(
      *this, address_list, num_addresses, stop_other_threads, frame_idx));

  status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
  return thread_plan_sp;
}

lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
    bool abort_other_plans, const char *class_name,
    StructuredData::ObjectSP extra_args_sp, bool stop_other_threads,
    Status &status) {

  ThreadPlanSP thread_plan_sp(new ScriptedThreadPlan(
      *this, class_name, StructuredDataImpl(extra_args_sp)));
  thread_plan_sp->SetStopOthers(stop_other_threads);
  status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
  return thread_plan_sp;
}

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

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() {
  std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);

  if (m_curr_frames_sp)
    return m_curr_frames_sp;

  // First, try to load frame providers if we don't have any yet.
  if (m_frame_providers.empty()) {
    ProcessSP process_sp = GetProcess();
    if (process_sp) {
      Target &target = process_sp->GetTarget();
      const auto &descriptors = target.GetScriptedFrameProviderDescriptors();

      // Collect all descriptors that apply to this thread.
      std::vector<const ScriptedFrameProviderDescriptor *> thread_descriptors;
      for (const auto &entry : descriptors) {
        const ScriptedFrameProviderDescriptor &descriptor = entry.second;
        if (descriptor.IsValid() && descriptor.AppliesToThread(*this))
          thread_descriptors.push_back(&descriptor);
      }

      // Sort by priority (lower number = higher priority).
      llvm::sort(thread_descriptors,
                 [](const ScriptedFrameProviderDescriptor *a,
                    const ScriptedFrameProviderDescriptor *b) {
                   // nullopt (no priority) sorts last (UINT32_MAX).
                   uint32_t priority_a = a->GetPriority().value_or(UINT32_MAX);
                   uint32_t priority_b = b->GetPriority().value_or(UINT32_MAX);
                   return priority_a < priority_b;
                 });

      // Load ALL matching providers in priority order.
      for (const auto *descriptor : thread_descriptors) {
        if (llvm::Error error = LoadScriptedFrameProvider(*descriptor)) {
          LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(error),
                         "Failed to load scripted frame provider: {0}");
          continue; // Try next provider if this one fails.
        }
      }
    }
  }

  // Create the frame list based on whether we have providers.
  if (!m_provider_chain_ids.empty()) {
    // We have providers - use the last one in the chain.
    // The last provider has already been chained with all previous providers.
    auto [last_desc, last_id] = m_provider_chain_ids.back();
    auto it = m_frame_providers.find(last_id);
    if (it != m_frame_providers.end()) {
      SyntheticFrameProviderSP last_provider = it->second;
      StackFrameListSP input_frames = last_provider->GetInputFrames();
      m_curr_frames_sp = std::make_shared<SyntheticStackFrameList>(
          *this, input_frames, m_prev_frames_sp, true, last_provider, last_id);
    } else {
      LLDB_LOG(GetLog(LLDBLog::Thread),
               "Missing frame provider (id = {0}) in Thread #{1:x}}", last_id,
               GetID());
    }
  }

  if (!m_curr_frames_sp) {
    // No provider - use normal unwinder frames with stable ID = 0.
    m_unwinder_frames_sp = std::make_shared<StackFrameList>(
        *this, m_prev_frames_sp, true, /*provider_id=*/0);
    m_curr_frames_sp = m_unwinder_frames_sp;
  } else {
    // Register this frame list by its identifier for later lookup.
    m_frame_lists_by_id.insert(
        {m_curr_frames_sp->GetIdentifier(), m_curr_frames_sp});
  }

  return m_curr_frames_sp;
}

lldb::StackFrameListSP
Thread::GetFrameListByIdentifier(lldb::frame_list_id_t id) {
  std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);

  // ID 0 is reserved for the unwinder frame list. Always return the unwinder
  // frame list for ID 0.
  if (id == 0) {
    return m_unwinder_frames_sp;
  }

  auto it = m_frame_lists_by_id.find(id);
  if (it != m_frame_lists_by_id.end()) {
    return it->second.lock();
  }
  return nullptr;
}

llvm::Error Thread::LoadScriptedFrameProvider(
    const ScriptedFrameProviderDescriptor &descriptor) {
  std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);

  StackFrameListSP input_frames;
  if (m_frame_providers.empty()) {
    // First provider gets real unwinder frames with stable ID = 0.
    m_unwinder_frames_sp =
        std::make_shared<StackFrameList>(*this, m_prev_frames_sp, true,
                                         /*provider_id=*/0);
    input_frames = m_unwinder_frames_sp;
  } else {
    // Subsequent providers wrap the previous provider.
    auto [last_desc, last_id] = m_provider_chain_ids.back();
    auto it = m_frame_providers.find(last_id);
    if (it == m_frame_providers.end())
      return llvm::createStringError("Previous frame provider not found");
    SyntheticFrameProviderSP last_provider = it->second;
    StackFrameListSP last_provider_frames = last_provider->GetInputFrames();
    input_frames = std::make_shared<SyntheticStackFrameList>(
        *this, last_provider_frames, m_prev_frames_sp, true, last_provider,
        last_id);
  }

  auto provider_or_err =
      SyntheticFrameProvider::CreateInstance(input_frames, descriptor);
  if (!provider_or_err)
    return provider_or_err.takeError();

  if (m_next_provider_id == std::numeric_limits<lldb::frame_list_id_t>::max())
    m_next_provider_id = 1;
  else
    m_next_provider_id++;

  lldb::frame_list_id_t provider_id = m_next_provider_id;
  m_frame_providers.insert({provider_id, *provider_or_err});

  // Add to the provider chain.
  m_provider_chain_ids.push_back({descriptor, provider_id});

  return llvm::Error::success();
}

llvm::Expected<ScriptedFrameProviderDescriptor>
Thread::GetScriptedFrameProviderDescriptorForID(
    lldb::frame_list_id_t id) const {
  if (id == LLDB_UNWINDER_FRAME_LIST_ID)
    return ScriptedFrameProviderDescriptor();

  auto it = llvm::find_if(
      m_provider_chain_ids,
      [id](const std::pair<ScriptedFrameProviderDescriptor,
                           lldb::frame_list_id_t> &provider_id_pair) {
        return provider_id_pair.second == id;
      });

  if (it == m_provider_chain_ids.end())
    return llvm::createStringError(
        "Couldn't find ScriptedFrameProviderDescriptor for id = %u.", id);

  return it->first;
}

void Thread::ClearScriptedFrameProvider() {
  std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
  m_frame_providers.clear();
  m_provider_chain_ids.clear();
  m_next_provider_id = 1; // Reset counter.
  m_unwinder_frames_sp.reset();
  m_curr_frames_sp.reset();
  m_prev_frames_sp.reset();
}

std::optional<addr_t> Thread::GetPreviousFrameZeroPC() {
  return m_prev_framezero_pc;
}

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

  GetUnwinder().Clear();
  m_prev_framezero_pc.reset();
  if (RegisterContextSP reg_ctx_sp = GetRegisterContext())
    m_prev_framezero_pc = reg_ctx_sp->GetPC();

  // 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->WereAllFramesFetched())
    m_prev_frames_sp.swap(m_curr_frames_sp);
  m_curr_frames_sp.reset();
  m_unwinder_frames_sp.reset();

  // Clear the provider instances, but keep the chain configuration
  // (m_provider_chain_ids and m_next_provider_id) so provider IDs
  // remain stable across ClearStackFrames() calls.
  m_frame_providers.clear();
  m_frame_lists_by_id.clear();
  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 = Status::FromErrorStringWithFormat(
        "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 = Status::FromErrorString("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 = Status::FromErrorString("No older frame to return to.");
    return return_error;
  }

  if (return_value_sp) {
    lldb::ABISP abi = thread->GetProcess()->GetABI();
    if (!abi) {
      return_error =
          Status::FromErrorString("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 */ (false) && 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)) {
          auto data_sp = std::make_shared<ThreadEventData>(shared_from_this());
          BroadcastEvent(eBroadcastBitStackChanged, data_sp);
        }
      } else {
        return_error =
            Status::FromErrorString("Could not reset register values.");
      }
    } else {
      return_error = Status::FromErrorString("Frame has no register context.");
    }
  } else {
    return_error = Status::FromErrorString("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::FromErrorStringWithFormat(
          "Cannot locate an address for %s:%i.", file.GetFilename().AsCString(),
          line);
    } else if (outside_function.size() == 1) {
      return Status::FromErrorStringWithFormat(
          "%s:%i is outside the current function.",
          file.GetFilename().AsCString(), line);
    } else {
      StreamString sstr;
      DumpAddressList(sstr, outside_function, target);
      return Status::FromErrorStringWithFormat(
          "%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 = std::string(sstr.GetString());
  }

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

  return Status();
}

bool Thread::DumpUsingFormat(Stream &strm, uint32_t frame_idx,
                             const FormatEntity::Entry *format) {
  ExecutionContext exe_ctx(shared_from_this());
  Process *process = exe_ctx.GetProcessPtr();
  if (!process || !format)
    return false;

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

  return FormatEntity::Formatter(frame_sp ? &frame_sc : nullptr, &exe_ctx,
                                 nullptr, false, false)
      .Format(*format, strm);
}

void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx,
                                     bool stop_format) {
  ExecutionContext exe_ctx(shared_from_this());

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

  assert(thread_format);

  DumpUsingFormat(strm, frame_idx, thread_format);
}

void Thread::SettingsInitialize() {}

void Thread::SettingsTerminate() {}

lldb::addr_t Thread::GetThreadPointer() {
  if (m_reg_context_sp)
    return m_reg_context_sp->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) {
    DynamicLoader *loader = GetProcess()->GetDynamicLoader();
    if (loader && loader->IsFullyInitialized() == false)
      return false;

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

std::string Thread::StopReasonAsString(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 eStopReasonFork:
    return "fork";
  case eStopReasonVFork:
    return "vfork";
  case eStopReasonVForkDone:
    return "vfork done";
  case eStopReasonPlanComplete:
    return "plan complete";
  case eStopReasonThreadExiting:
    return "thread exiting";
  case eStopReasonInstrumentation:
    return "instrumentation break";
  case eStopReasonProcessorTrace:
    return "processor trace";
  case eStopReasonInterrupt:
    return "async interrupt";
  case eStopReasonHistoryBoundary:
    return "history boundary";
  }

  return "StopReason = " + std::to_string(reason);
}

std::string Thread::RunModeAsString(lldb::RunMode mode) {
  switch (mode) {
  case eOnlyThisThread:
    return "only this thread";
  case eAllThreads:
    return "all threads";
  case eOnlyDuringStepping:
    return "only during stepping";
  }

  return "RunMode = " + std::to_string(mode);
}

size_t Thread::GetStatus(Stream &strm, uint32_t start_frame,
                         uint32_t num_frames, uint32_t num_frames_with_source,
                         bool stop_format, bool show_hidden, 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.GetFile()) {
          if (llvm::Error e = Host::OpenFileInExternalEditor(
                  target->GetDebugger().GetExternalEditor(),
                  frame_sc.line_entry.GetFile(), frame_sc.line_entry.line)) {
            LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e),
                           "OpenFileInExternalEditor failed: {0}");
          }
        }
      }
    }

    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, show_hidden, 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->GetUnsignedIntegerValue());
      }
      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,
                                   bool show_hidden) {
  return GetStackFrameList()->GetStatus(strm, first_frame, num_frames,
                                        show_frame_info, num_frames_with_source,
                                        /*show_unique*/ false, show_hidden);
}

Unwind &Thread::GetUnwinder() {
  if (!m_unwinder_up)
    m_unwinder_up = std::make_unique<UnwindLLDB>(*this);
  return *m_unwinder_up;
}

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

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

    new_plan_sp->SetIsControllingPlan(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 = Status::FromErrorString("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, error,
          step_out_avoids_code_without_debug_info);
    } else {
      new_plan_sp = QueueThreadPlanForStepSingleInstruction(
          true, abort_other_plans, run_mode, error);
    }

    new_plan_sp->SetIsControllingPlan(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 = Status::FromErrorString("process not stopped");
  }
  return error;
}

Status Thread::StepOut(uint32_t frame_idx) {
  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, frame_idx, error));

    new_plan_sp->SetIsControllingPlan(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 = Status::FromErrorString("process not stopped");
  }
  return error;
}

ValueObjectSP Thread::GetCurrentException() {
  if (auto frame_sp = GetStackFrameAtIndex(0))
    if (auto recognized_frame = frame_sp->GetRecognizedFrame())
      if (auto e = recognized_frame->GetExceptionObject())
        return e;

  // NOTE: Even though this behavior is generalized, only ObjC is actually
  // supported at the moment.
  for (LanguageRuntime *runtime : GetProcess()->GetLanguageRuntimes()) {
    if (auto e = runtime->GetExceptionObjectForThread(shared_from_this()))
      return e;
  }

  return ValueObjectSP();
}

ThreadSP Thread::GetCurrentExceptionBacktrace() {
  ValueObjectSP exception = GetCurrentException();
  if (!exception)
    return ThreadSP();

  // NOTE: Even though this behavior is generalized, only ObjC is actually
  // supported at the moment.
  for (LanguageRuntime *runtime : GetProcess()->GetLanguageRuntimes()) {
    if (auto bt = runtime->GetBacktraceThreadFromException(exception))
      return bt;
  }

  return ThreadSP();
}

lldb::ValueObjectSP Thread::GetSiginfoValue() {
  ProcessSP process_sp = GetProcess();
  assert(process_sp);
  Target &target = process_sp->GetTarget();
  PlatformSP platform_sp = target.GetPlatform();
  assert(platform_sp);
  ArchSpec arch = target.GetArchitecture();

  CompilerType type = platform_sp->GetSiginfoType(arch.GetTriple());
  if (!type.IsValid())
    return ValueObjectConstResult::Create(
        &target, Status::FromErrorString("no siginfo_t for the platform"));

  auto type_size_or_err = type.GetByteSize(nullptr);
  if (!type_size_or_err)
    return ValueObjectConstResult::Create(
        &target, Status::FromError(type_size_or_err.takeError()));

  llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> data =
      GetSiginfo(*type_size_or_err);
  if (!data)
    return ValueObjectConstResult::Create(&target,
                                          Status::FromError(data.takeError()));

  DataExtractor data_extractor{data.get()->getBufferStart(), data.get()->getBufferSize(),
    process_sp->GetByteOrder(), arch.GetAddressByteSize()};
  return ValueObjectConstResult::Create(&target, type, ConstString("__lldb_siginfo"), data_extractor);
}
