//===-- StopInfo.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 <string>

#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

using namespace lldb;
using namespace lldb_private;

StopInfo::StopInfo(Thread &thread, uint64_t value)
    : m_thread_wp(thread.shared_from_this()),
      m_stop_id(thread.GetProcess()->GetStopID()),
      m_resume_id(thread.GetProcess()->GetResumeID()), m_value(value),
      m_description(), m_override_should_notify(eLazyBoolCalculate),
      m_override_should_stop(eLazyBoolCalculate), m_extended_info() {}

bool StopInfo::IsValid() const {
  ThreadSP thread_sp(m_thread_wp.lock());
  if (thread_sp)
    return thread_sp->GetProcess()->GetStopID() == m_stop_id;
  return false;
}

void StopInfo::MakeStopInfoValid() {
  ThreadSP thread_sp(m_thread_wp.lock());
  if (thread_sp) {
    m_stop_id = thread_sp->GetProcess()->GetStopID();
    m_resume_id = thread_sp->GetProcess()->GetResumeID();
  }
}

bool StopInfo::HasTargetRunSinceMe() {
  ThreadSP thread_sp(m_thread_wp.lock());

  if (thread_sp) {
    lldb::StateType ret_type = thread_sp->GetProcess()->GetPrivateState();
    if (ret_type == eStateRunning) {
      return true;
    } else if (ret_type == eStateStopped) {
      // This is a little tricky.  We want to count "run and stopped again
      // before you could ask this question as a "TRUE" answer to
      // HasTargetRunSinceMe.  But we don't want to include any running of the
      // target done for expressions.  So we track both resumes, and resumes
      // caused by expressions, and check if there are any resumes
      // NOT caused
      // by expressions.

      uint32_t curr_resume_id = thread_sp->GetProcess()->GetResumeID();
      uint32_t last_user_expression_id =
          thread_sp->GetProcess()->GetLastUserExpressionResumeID();
      if (curr_resume_id == m_resume_id) {
        return false;
      } else if (curr_resume_id > last_user_expression_id) {
        return true;
      }
    }
  }
  return false;
}

// StopInfoBreakpoint

namespace lldb_private {
class StopInfoBreakpoint : public StopInfo {
public:
  StopInfoBreakpoint(Thread &thread, break_id_t break_id)
      : StopInfo(thread, break_id), m_should_stop(false),
        m_should_stop_is_valid(false), m_should_perform_action(true),
        m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),
        m_was_all_internal(false), m_was_one_shot(false) {
    StoreBPInfo();
  }

  StopInfoBreakpoint(Thread &thread, break_id_t break_id, bool should_stop)
      : StopInfo(thread, break_id), m_should_stop(should_stop),
        m_should_stop_is_valid(true), m_should_perform_action(true),
        m_address(LLDB_INVALID_ADDRESS), m_break_id(LLDB_INVALID_BREAK_ID),
        m_was_all_internal(false), m_was_one_shot(false) {
    StoreBPInfo();
  }

  ~StopInfoBreakpoint() override = default;

  void StoreBPInfo() {
    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp) {
      BreakpointSiteSP bp_site_sp(
          thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
      if (bp_site_sp) {
        uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
        if (num_owners == 1) {
          BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(0);
          if (bp_loc_sp) {
            Breakpoint & bkpt = bp_loc_sp->GetBreakpoint();
            m_break_id = bkpt.GetID();
            m_was_one_shot = bkpt.IsOneShot();
            m_was_all_internal = bkpt.IsInternal();
          }
        } else {
          m_was_all_internal = true;
          for (uint32_t i = 0; i < num_owners; i++) {
            if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) {
              m_was_all_internal = false;
              break;
            }
          }
        }
        m_address = bp_site_sp->GetLoadAddress();
      }
    }
  }

  bool IsValidForOperatingSystemThread(Thread &thread) override {
    ProcessSP process_sp(thread.GetProcess());
    if (process_sp) {
      BreakpointSiteSP bp_site_sp(
          process_sp->GetBreakpointSiteList().FindByID(m_value));
      if (bp_site_sp)
        return bp_site_sp->ValidForThisThread(thread);
    }
    return false;
  }

  StopReason GetStopReason() const override { return eStopReasonBreakpoint; }

  bool ShouldStopSynchronous(Event *event_ptr) override {
    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp) {
      if (!m_should_stop_is_valid) {
        // Only check once if we should stop at a breakpoint
        BreakpointSiteSP bp_site_sp(
            thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
        if (bp_site_sp) {
          ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
          StoppointCallbackContext context(event_ptr, exe_ctx, true);
          bp_site_sp->BumpHitCounts();
          m_should_stop = bp_site_sp->ShouldStop(&context);
        } else {
          Log *log = GetLog(LLDBLog::Process);

          LLDB_LOGF(log,
                    "Process::%s could not find breakpoint site id: %" PRId64
                    "...",
                    __FUNCTION__, m_value);

          m_should_stop = true;
        }
        m_should_stop_is_valid = true;
      }
      return m_should_stop;
    }
    return false;
  }

  bool DoShouldNotify(Event *event_ptr) override {
    return !m_was_all_internal;
  }

  const char *GetDescription() override {
    if (m_description.empty()) {
      ThreadSP thread_sp(m_thread_wp.lock());
      if (thread_sp) {
        BreakpointSiteSP bp_site_sp(
            thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
        if (bp_site_sp) {
          StreamString strm;
          // If we have just hit an internal breakpoint, and it has a kind
          // description, print that instead of the full breakpoint printing:
          if (bp_site_sp->IsInternal()) {
            size_t num_owners = bp_site_sp->GetNumberOfOwners();
            for (size_t idx = 0; idx < num_owners; idx++) {
              const char *kind = bp_site_sp->GetOwnerAtIndex(idx)
                                     ->GetBreakpoint()
                                     .GetBreakpointKind();
              if (kind != nullptr) {
                m_description.assign(kind);
                return kind;
              }
            }
          }

          strm.Printf("breakpoint ");
          bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);
          m_description = std::string(strm.GetString());
        } else {
          StreamString strm;
          if (m_break_id != LLDB_INVALID_BREAK_ID) {
            BreakpointSP break_sp =
                thread_sp->GetProcess()->GetTarget().GetBreakpointByID(
                    m_break_id);
            if (break_sp) {
              if (break_sp->IsInternal()) {
                const char *kind = break_sp->GetBreakpointKind();
                if (kind)
                  strm.Printf("internal %s breakpoint(%d).", kind, m_break_id);
                else
                  strm.Printf("internal breakpoint(%d).", m_break_id);
              } else {
                strm.Printf("breakpoint %d.", m_break_id);
              }
            } else {
              if (m_was_one_shot)
                strm.Printf("one-shot breakpoint %d", m_break_id);
              else
                strm.Printf("breakpoint %d which has been deleted.",
                            m_break_id);
            }
          } else if (m_address == LLDB_INVALID_ADDRESS)
            strm.Printf("breakpoint site %" PRIi64
                        " which has been deleted - unknown address",
                        m_value);
          else
            strm.Printf("breakpoint site %" PRIi64
                        " which has been deleted - was at 0x%" PRIx64,
                        m_value, m_address);

          m_description = std::string(strm.GetString());
        }
      }
    }
    return m_description.c_str();
  }

protected:
  bool ShouldStop(Event *event_ptr) override {
    // This just reports the work done by PerformAction or the synchronous
    // stop. It should only ever get called after they have had a chance to
    // run.
    assert(m_should_stop_is_valid);
    return m_should_stop;
  }

  void PerformAction(Event *event_ptr) override {
    if (!m_should_perform_action)
      return;
    m_should_perform_action = false;
    bool all_stopping_locs_internal = true;

    ThreadSP thread_sp(m_thread_wp.lock());

    if (thread_sp) {
      Log *log = GetLog(LLDBLog::Breakpoints | LLDBLog::Step);

      if (!thread_sp->IsValid()) {
        // This shouldn't ever happen, but just in case, don't do more harm.
        if (log) {
          LLDB_LOGF(log, "PerformAction got called with an invalid thread.");
        }
        m_should_stop = true;
        m_should_stop_is_valid = true;
        return;
      }

      BreakpointSiteSP bp_site_sp(
          thread_sp->GetProcess()->GetBreakpointSiteList().FindByID(m_value));
      std::unordered_set<break_id_t> precondition_breakpoints;
      // Breakpoints that fail their condition check are not considered to
      // have been hit.  If the only locations at this site have failed their
      // conditions, we should change the stop-info to none.  Otherwise, if we
      // hit another breakpoint on a different thread which does stop, users
      // will see a breakpont hit with a failed condition, which is wrong.
      // Use this variable to tell us if that is true.
      bool actually_hit_any_locations = false;
      if (bp_site_sp) {
        // Let's copy the owners list out of the site and store them in a local
        // list.  That way if one of the breakpoint actions changes the site,
        // then we won't be operating on a bad list.
        BreakpointLocationCollection site_locations;
        size_t num_owners = bp_site_sp->CopyOwnersList(site_locations);

        if (num_owners == 0) {
          m_should_stop = true;
          actually_hit_any_locations = true;  // We're going to stop, don't 
                                              // change the stop info.
        } else {
          // We go through each location, and test first its precondition -
          // this overrides everything.  Note, we only do this once per
          // breakpoint - not once per location... Then check the condition.
          // If the condition says to stop, then we run the callback for that
          // location.  If that callback says to stop as well, then we set
          // m_should_stop to true; we are going to stop. But we still want to
          // give all the breakpoints whose conditions say we are going to stop
          // a chance to run their callbacks. Of course if any callback
          // restarts the target by putting "continue" in the callback, then
          // we're going to restart, without running the rest of the callbacks.
          // And in this case we will end up not stopping even if another
          // location said we should stop. But that's better than not running
          // all the callbacks.

          // There's one other complication here.  We may have run an async
          // breakpoint callback that said we should stop.  We only want to
          // override that if another breakpoint action says we shouldn't
          // stop.  If nobody else has an opinion, then we should stop if the
          // async callback says we should.  An example of this is the async
          // shared library load notification breakpoint and the setting
          // stop-on-sharedlibrary-events.
          // We'll keep the async value in async_should_stop, and track whether
          // anyone said we should NOT stop in actually_said_continue.
          bool async_should_stop = false;
          if (m_should_stop_is_valid)
            async_should_stop = m_should_stop;
          bool actually_said_continue = false;

          m_should_stop = false;

          // We don't select threads as we go through them testing breakpoint
          // conditions and running commands. So we need to set the thread for
          // expression evaluation here:
          ThreadList::ExpressionExecutionThreadPusher thread_pusher(thread_sp);

          ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
          Process *process = exe_ctx.GetProcessPtr();
          if (process->GetModIDRef().IsRunningExpression()) {
            // If we are in the middle of evaluating an expression, don't run
            // asynchronous breakpoint commands or expressions.  That could
            // lead to infinite recursion if the command or condition re-calls
            // the function with this breakpoint.
            // TODO: We can keep a list of the breakpoints we've seen while
            // running expressions in the nested
            // PerformAction calls that can arise when the action runs a
            // function that hits another breakpoint, and only stop running
            // commands when we see the same breakpoint hit a second time.

            m_should_stop_is_valid = true;

            // It is possible that the user has a breakpoint at the same site
            // as the completed plan had (e.g. user has a breakpoint
            // on a module entry point, and `ThreadPlanCallFunction` ends
            // also there). We can't find an internal breakpoint in the loop
            // later because it was already removed on the plan completion.
            // So check if the plan was completed, and stop if so.
            if (thread_sp->CompletedPlanOverridesBreakpoint()) {
              m_should_stop = true;
              thread_sp->ResetStopInfo();
              return;
            }

            LLDB_LOGF(log, "StopInfoBreakpoint::PerformAction - Hit a "
                           "breakpoint while running an expression,"
                           " not running commands to avoid recursion.");
            bool ignoring_breakpoints =
                process->GetIgnoreBreakpointsInExpressions();
            // Internal breakpoints should be allowed to do their job, we
            // can make sure they don't do anything that would cause recursive
            // command execution:
            if (!m_was_all_internal) {
              m_should_stop = !ignoring_breakpoints;
              LLDB_LOGF(log,
                        "StopInfoBreakpoint::PerformAction - in expression, "
                        "continuing: %s.",
                        m_should_stop ? "true" : "false");
              Debugger::ReportWarning(
                  "hit breakpoint while running function, skipping commands "
                  "and conditions to prevent recursion",
                    process->GetTarget().GetDebugger().GetID());
              return;
            }
          }

          StoppointCallbackContext context(event_ptr, exe_ctx, false);

          // For safety's sake let's also grab an extra reference to the
          // breakpoint owners of the locations we're going to examine, since
          // the locations are going to have to get back to their breakpoints,
          // and the locations don't keep their owners alive.  I'm just
          // sticking the BreakpointSP's in a vector since I'm only using it to
          // locally increment their retain counts.

          std::vector<lldb::BreakpointSP> location_owners;

          for (size_t j = 0; j < num_owners; j++) {
            BreakpointLocationSP loc(site_locations.GetByIndex(j));
            location_owners.push_back(loc->GetBreakpoint().shared_from_this());
          }

          for (size_t j = 0; j < num_owners; j++) {
            lldb::BreakpointLocationSP bp_loc_sp = site_locations.GetByIndex(j);
            StreamString loc_desc;
            if (log) {
              bp_loc_sp->GetDescription(&loc_desc, eDescriptionLevelBrief);
            }
            // If another action disabled this breakpoint or its location, then
            // don't run the actions.
            if (!bp_loc_sp->IsEnabled() ||
                !bp_loc_sp->GetBreakpoint().IsEnabled())
              continue;

            // The breakpoint site may have many locations associated with it,
            // not all of them valid for this thread.  Skip the ones that
            // aren't:
            if (!bp_loc_sp->ValidForThisThread(*thread_sp)) {
              if (log) {
                LLDB_LOGF(log,
                          "Breakpoint %s hit on thread 0x%llx but it was not "
                          "for this thread, continuing.",
                          loc_desc.GetData(),
                          static_cast<unsigned long long>(thread_sp->GetID()));
              }
              continue;
            }

            // First run the precondition, but since the precondition is per
            // breakpoint, only run it once per breakpoint.
            std::pair<std::unordered_set<break_id_t>::iterator, bool> result =
                precondition_breakpoints.insert(
                    bp_loc_sp->GetBreakpoint().GetID());
            if (!result.second)
              continue;

            bool precondition_result =
                bp_loc_sp->GetBreakpoint().EvaluatePrecondition(context);
            if (!precondition_result) {
              actually_said_continue = true;
              continue;
            }
            // Next run the condition for the breakpoint.  If that says we
            // should stop, then we'll run the callback for the breakpoint.  If
            // the callback says we shouldn't stop that will win.

            if (bp_loc_sp->GetConditionText() == nullptr)
              actually_hit_any_locations = true;
            else {
              Status condition_error;
              bool condition_says_stop =
                  bp_loc_sp->ConditionSaysStop(exe_ctx, condition_error);

              if (!condition_error.Success()) {
                // If the condition fails to evaluate, we are going to stop 
                // at it, so the location was hit.
                actually_hit_any_locations = true;
                const char *err_str =
                    condition_error.AsCString("<unknown error>");
                LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);

                StreamString strm;
                strm << "stopped due to an error evaluating condition of "
                        "breakpoint ";
                bp_loc_sp->GetDescription(&strm, eDescriptionLevelBrief);
                strm << ": \"" << bp_loc_sp->GetConditionText() << "\"\n";
                strm << err_str;

                Debugger::ReportError(
                    strm.GetString().str(),
                    exe_ctx.GetTargetRef().GetDebugger().GetID());
              } else {
                LLDB_LOGF(log,
                          "Condition evaluated for breakpoint %s on thread "
                          "0x%llx condition_says_stop: %i.",
                          loc_desc.GetData(),
                          static_cast<unsigned long long>(thread_sp->GetID()),
                          condition_says_stop);
                if (condition_says_stop) 
                  actually_hit_any_locations = true;
                else {
                  // We don't want to increment the hit count of breakpoints if
                  // the condition fails. We've already bumped it by the time
                  // we get here, so undo the bump:
                  bp_loc_sp->UndoBumpHitCount();
                  actually_said_continue = true;
                  continue;
                }
              }
            }

            // We've done all the checks whose failure means "we consider lldb
            // not to have hit the breakpoint".  Now we're going to check for
            // conditions that might continue after hitting.  Start with the
            // ignore count:
            if (!bp_loc_sp->IgnoreCountShouldStop()) {
              actually_said_continue = true;
              continue;
            }

            // Check the auto-continue bit on the location, do this before the
            // callback since it may change this, but that would be for the
            // NEXT hit.  Note, you might think you could check auto-continue
            // before the condition, and not evaluate the condition if it says
            // to continue.  But failing the condition means the breakpoint was
            // effectively NOT HIT.  So these two states are different.
            bool auto_continue_says_stop = true;
            if (bp_loc_sp->IsAutoContinue())
            {
              LLDB_LOGF(log,
                        "Continuing breakpoint %s as AutoContinue was set.",
                        loc_desc.GetData());
              // We want this stop reported, so you will know we auto-continued
              // but only for external breakpoints:
              if (!bp_loc_sp->GetBreakpoint().IsInternal())
                thread_sp->SetShouldReportStop(eVoteYes);
              auto_continue_says_stop = false;
            }

            bool callback_says_stop = true;

            // FIXME: For now the callbacks have to run in async mode - the
            // first time we restart we need
            // to get out of there.  So set it here.
            // When we figure out how to nest breakpoint hits then this will
            // change.

            // Don't run async callbacks in PerformAction.  They have already
            // been taken into account with async_should_stop.
            if (!bp_loc_sp->IsCallbackSynchronous()) {
              Debugger &debugger = thread_sp->CalculateTarget()->GetDebugger();
              bool old_async = debugger.GetAsyncExecution();
              debugger.SetAsyncExecution(true);

              callback_says_stop = bp_loc_sp->InvokeCallback(&context);

              debugger.SetAsyncExecution(old_async);

              if (callback_says_stop && auto_continue_says_stop)
                m_should_stop = true;
              else
                actually_said_continue = true;
            }

            if (m_should_stop && !bp_loc_sp->GetBreakpoint().IsInternal())
              all_stopping_locs_internal = false;

            // If we are going to stop for this breakpoint, then remove the
            // breakpoint.
            if (callback_says_stop && bp_loc_sp &&
                bp_loc_sp->GetBreakpoint().IsOneShot()) {
              thread_sp->GetProcess()->GetTarget().RemoveBreakpointByID(
                  bp_loc_sp->GetBreakpoint().GetID());
            }
            // Also make sure that the callback hasn't continued the target. If
            // it did, when we'll set m_should_start to false and get out of
            // here.
            if (HasTargetRunSinceMe()) {
              m_should_stop = false;
              actually_said_continue = true;
              break;
            }
          }
          // At this point if nobody actually told us to continue, we should
          // give the async breakpoint callback a chance to weigh in:
          if (!actually_said_continue && !m_should_stop) {
            m_should_stop = async_should_stop;
          }
        }
        // We've figured out what this stop wants to do, so mark it as valid so
        // we don't compute it again.
        m_should_stop_is_valid = true;
      } else {
        m_should_stop = true;
        m_should_stop_is_valid = true;
        actually_hit_any_locations = true;
        Log *log_process(GetLog(LLDBLog::Process));

        LLDB_LOGF(log_process,
                  "Process::%s could not find breakpoint site id: %" PRId64
                  "...",
                  __FUNCTION__, m_value);
      }

      if ((!m_should_stop || all_stopping_locs_internal) &&
          thread_sp->CompletedPlanOverridesBreakpoint()) {

        // Override should_stop decision when we have completed step plan
        // additionally to the breakpoint
        m_should_stop = true;

        // We know we're stopping for a completed plan and we don't want to
        // show the breakpoint stop, so compute the public stop info immediately
        // here.
        thread_sp->CalculatePublicStopInfo();
      } else if (!actually_hit_any_locations) {
        // In the end, we didn't actually have any locations that passed their
        // "was I hit" checks.  So say we aren't stopped.
        GetThread()->ResetStopInfo();
        LLDB_LOGF(log, "Process::%s all locations failed condition checks.",
          __FUNCTION__);
      }

      LLDB_LOGF(log,
                "Process::%s returning from action with m_should_stop: %d.",
                __FUNCTION__, m_should_stop);
    }
  }

private:
  bool m_should_stop;
  bool m_should_stop_is_valid;
  bool m_should_perform_action; // Since we are trying to preserve the "state"
                                // of the system even if we run functions
  // etc. behind the users backs, we need to make sure we only REALLY perform
  // the action once.
  lldb::addr_t m_address; // We use this to capture the breakpoint site address
                          // when we create the StopInfo,
  // in case somebody deletes it between the time the StopInfo is made and the
  // description is asked for.
  lldb::break_id_t m_break_id;
  bool m_was_all_internal;
  bool m_was_one_shot;
};

// StopInfoWatchpoint

class StopInfoWatchpoint : public StopInfo {
public:
  // Make sure watchpoint is properly disabled and subsequently enabled while
  // performing watchpoint actions.
  class WatchpointSentry {
  public:
    WatchpointSentry(ProcessSP p_sp, WatchpointSP w_sp) : process_sp(p_sp),
                     watchpoint_sp(w_sp) {
      if (process_sp && watchpoint_sp) {
        const bool notify = false;
        watchpoint_sp->TurnOnEphemeralMode();
        process_sp->DisableWatchpoint(watchpoint_sp.get(), notify);
        process_sp->AddPreResumeAction(SentryPreResumeAction, this);
      }
    }

    void DoReenable() {
      if (process_sp && watchpoint_sp) {
        bool was_disabled = watchpoint_sp->IsDisabledDuringEphemeralMode();
        watchpoint_sp->TurnOffEphemeralMode();
        const bool notify = false;
        if (was_disabled) {
          process_sp->DisableWatchpoint(watchpoint_sp.get(), notify);
        } else {
          process_sp->EnableWatchpoint(watchpoint_sp.get(), notify);
        }
      }
    }

    ~WatchpointSentry() {
        DoReenable();
        if (process_sp)
            process_sp->ClearPreResumeAction(SentryPreResumeAction, this);
    }

    static bool SentryPreResumeAction(void *sentry_void) {
        WatchpointSentry *sentry = (WatchpointSentry *) sentry_void;
        sentry->DoReenable();
        return true;
    }

  private:
    ProcessSP process_sp;
    WatchpointSP watchpoint_sp;
  };

  StopInfoWatchpoint(Thread &thread, break_id_t watch_id, bool silently_skip_wp)
      : StopInfo(thread, watch_id), m_silently_skip_wp(silently_skip_wp) {}

  ~StopInfoWatchpoint() override = default;

  StopReason GetStopReason() const override { return eStopReasonWatchpoint; }

  const char *GetDescription() override {
    if (m_description.empty()) {
      StreamString strm;
      strm.Printf("watchpoint %" PRIi64, m_value);
      m_description = std::string(strm.GetString());
    }
    return m_description.c_str();
  }

protected:
  using StopInfoWatchpointSP = std::shared_ptr<StopInfoWatchpoint>;
  // This plan is used to orchestrate stepping over the watchpoint for
  // architectures (e.g. ARM) that report the watch before running the watched
  // access.  This is the sort of job you have to defer to the thread plans,
  // if you try to do it directly in the stop info and there are other threads
  // that needed to process this stop you will have yanked control away from
  // them and they won't behave correctly.
  class ThreadPlanStepOverWatchpoint : public ThreadPlanStepInstruction {
  public:
    ThreadPlanStepOverWatchpoint(Thread &thread, 
                                 StopInfoWatchpointSP stop_info_sp,
                                 WatchpointSP watch_sp)
        : ThreadPlanStepInstruction(thread, false, true, eVoteNoOpinion,
                                    eVoteNoOpinion),
          m_stop_info_sp(stop_info_sp), m_watch_sp(watch_sp) {
      assert(watch_sp);
      m_watch_index = watch_sp->GetHardwareIndex();
    }

    bool DoWillResume(lldb::StateType resume_state,
                      bool current_plan) override {
      if (resume_state == eStateSuspended)
        return true;

      if (!m_did_disable_wp) {
        GetThread().GetProcess()->DisableWatchpoint(m_watch_sp.get(), false);
        m_did_disable_wp = true;
      }
      return true;
    }
    
    bool DoPlanExplainsStop(Event *event_ptr) override {
      if (ThreadPlanStepInstruction::DoPlanExplainsStop(event_ptr))
        return true;
      StopInfoSP stop_info_sp = GetThread().GetPrivateStopInfo();
      // lldb-server resets the stop info for threads that didn't get to run,
      // so we might have not gotten to run, but still have a watchpoint stop
      // reason, in which case this will indeed be for us.
      if (stop_info_sp 
          && stop_info_sp->GetStopReason() == eStopReasonWatchpoint)
        return true;
      return false;
    }

    void DidPop() override {
      // Don't artifically keep the watchpoint alive.
      m_watch_sp.reset();
    }
    
    bool ShouldStop(Event *event_ptr) override {
      bool should_stop = ThreadPlanStepInstruction::ShouldStop(event_ptr);
      bool plan_done = MischiefManaged();
      if (plan_done) {
        m_stop_info_sp->SetStepOverPlanComplete();
        GetThread().SetStopInfo(m_stop_info_sp);
        ResetWatchpoint();
      }
      return should_stop;
    }
    
    bool ShouldRunBeforePublicStop() override {
        return true;
    }

  protected:
    void ResetWatchpoint() {
      if (!m_did_disable_wp)
        return;
      m_did_disable_wp = true;
      GetThread().GetProcess()->EnableWatchpoint(m_watch_sp.get(), true);
      m_watch_sp->SetHardwareIndex(m_watch_index);
    }

  private:
    StopInfoWatchpointSP m_stop_info_sp;
    WatchpointSP m_watch_sp;
    uint32_t m_watch_index = LLDB_INVALID_INDEX32;
    bool m_did_disable_wp = false;
  };

  bool ShouldStopSynchronous(Event *event_ptr) override {
    // If we are running our step-over the watchpoint plan, stop if it's done
    // and continue if it's not:
    if (m_should_stop_is_valid)
      return m_should_stop;

    // If we are running our step over plan, then stop here and let the regular
    // ShouldStop figure out what we should do:  Otherwise, give our plan
    // more time to get run:
    if (m_using_step_over_plan)
      return m_step_over_plan_complete;

    Log *log = GetLog(LLDBLog::Process);
    ThreadSP thread_sp(m_thread_wp.lock());
    assert(thread_sp);
    
    if (thread_sp->GetTemporaryResumeState() == eStateSuspended) {
      // This is the second firing of a watchpoint so don't process it again.
      LLDB_LOG(log, "We didn't run but stopped with a StopInfoWatchpoint, we "
               "have already handled this one, don't do it again.");
      m_should_stop = false;
      m_should_stop_is_valid = true;
      return m_should_stop;
    }
    
    WatchpointSP wp_sp(
        thread_sp->CalculateTarget()->GetWatchpointList().FindByID(GetValue()));
    // If we can no longer find the watchpoint, we just have to stop:
    if (!wp_sp) {

      LLDB_LOGF(log,
                "Process::%s could not find watchpoint location id: %" PRId64
                "...",
                __FUNCTION__, GetValue());

      m_should_stop = true;
      m_should_stop_is_valid = true;
      return true;
    }

    ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
    StoppointCallbackContext context(event_ptr, exe_ctx, true);
    m_should_stop = wp_sp->ShouldStop(&context);
    if (!m_should_stop) {
      // This won't happen at present because we only allow one watchpoint per
      // watched range.  So we won't stop at a watched address with a disabled
      // watchpoint.  If we start allowing overlapping watchpoints, then we
      // will have to make watchpoints be real "WatchpointSite" and delegate to
      // all the watchpoints sharing the site.  In that case, the code below
      // would be the right thing to do.
      m_should_stop_is_valid = true;
      return m_should_stop;
    }
    // If this is a system where we need to execute the watchpoint by hand
    // after the hit, queue a thread plan to do that, and then say not to stop.
    // Otherwise, let the async action figure out whether the watchpoint should
    // stop

    ProcessSP process_sp = exe_ctx.GetProcessSP();
    bool wp_triggers_after = process_sp->GetWatchpointReportedAfter();

    if (!wp_triggers_after) {
      // We have to step over the watchpoint before we know what to do:   
      StopInfoWatchpointSP me_as_siwp_sp 
          = std::static_pointer_cast<StopInfoWatchpoint>(shared_from_this());
      ThreadPlanSP step_over_wp_sp(new ThreadPlanStepOverWatchpoint(
          *(thread_sp.get()), me_as_siwp_sp, wp_sp));
      // When this plan is done we want to stop, so set this as a Controlling
      // plan.    
      step_over_wp_sp->SetIsControllingPlan(true);
      step_over_wp_sp->SetOkayToDiscard(false);

      Status error;
      error = thread_sp->QueueThreadPlan(step_over_wp_sp, false);
      // If we couldn't push the thread plan, just stop here:
      if (!error.Success()) {
        LLDB_LOGF(log, "Could not push our step over watchpoint plan: %s", 
            error.AsCString());

        m_should_stop = true;
        m_should_stop_is_valid = true;
        return true;
      } else {
      // Otherwise, don't set m_should_stop, we don't know that yet.  Just 
      // say we should continue, and tell the thread we really should do so:
        thread_sp->SetShouldRunBeforePublicStop(true);
        m_using_step_over_plan = true;
        return false;
      }
    } else {
      // We didn't have to do anything special
      m_should_stop_is_valid = true;
      return m_should_stop;
    }
    
    return m_should_stop;
  }

  bool ShouldStop(Event *event_ptr) override {
    // This just reports the work done by PerformAction or the synchronous
    // stop. It should only ever get called after they have had a chance to
    // run.
    assert(m_should_stop_is_valid);
    return m_should_stop;
  }

  void PerformAction(Event *event_ptr) override {
    Log *log = GetLog(LLDBLog::Watchpoints);
    // We're going to calculate if we should stop or not in some way during the
    // course of this code.  Also by default we're going to stop, so set that
    // here.
    m_should_stop = true;


    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp) {

      WatchpointSP wp_sp(
          thread_sp->CalculateTarget()->GetWatchpointList().FindByID(
              GetValue()));
      if (wp_sp) {
        // This sentry object makes sure the current watchpoint is disabled
        // while performing watchpoint actions, and it is then enabled after we
        // are finished.
        ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
        ProcessSP process_sp = exe_ctx.GetProcessSP();

        WatchpointSentry sentry(process_sp, wp_sp);

        if (m_silently_skip_wp) {
          m_should_stop = false;
          wp_sp->IncrementFalseAlarmsAndReviseHitCount();
        }

        if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount()) {
          m_should_stop = false;
          m_should_stop_is_valid = true;
        }

        Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();

        if (m_should_stop && wp_sp->GetConditionText() != nullptr) {
          // We need to make sure the user sees any parse errors in their
          // condition, so we'll hook the constructor errors up to the
          // debugger's Async I/O.
          ExpressionResults result_code;
          EvaluateExpressionOptions expr_options;
          expr_options.SetUnwindOnError(true);
          expr_options.SetIgnoreBreakpoints(true);
          ValueObjectSP result_value_sp;
          Status error;
          result_code = UserExpression::Evaluate(
              exe_ctx, expr_options, wp_sp->GetConditionText(),
              llvm::StringRef(), result_value_sp, error);

          if (result_code == eExpressionCompleted) {
            if (result_value_sp) {
              Scalar scalar_value;
              if (result_value_sp->ResolveValue(scalar_value)) {
                if (scalar_value.ULongLong(1) == 0) {
                  // The condition failed, which we consider "not having hit
                  // the watchpoint" so undo the hit count here.
                  wp_sp->UndoHitCount();
                  m_should_stop = false;
                } else
                  m_should_stop = true;
                LLDB_LOGF(log,
                          "Condition successfully evaluated, result is %s.\n",
                          m_should_stop ? "true" : "false");
              } else {
                m_should_stop = true;
                LLDB_LOGF(
                    log,
                    "Failed to get an integer result from the expression.");
              }
            }
          } else {
            const char *err_str = error.AsCString("<unknown error>");
            LLDB_LOGF(log, "Error evaluating condition: \"%s\"\n", err_str);

            StreamString strm;
            strm << "stopped due to an error evaluating condition of "
                    "watchpoint ";
            wp_sp->GetDescription(&strm, eDescriptionLevelBrief);
            strm << ": \"" << wp_sp->GetConditionText() << "\"\n";
            strm << err_str;

            Debugger::ReportError(strm.GetString().str(),
                                  exe_ctx.GetTargetRef().GetDebugger().GetID());
          }
        }

        // If the condition says to stop, we run the callback to further decide
        // whether to stop.
        if (m_should_stop) {
            // FIXME: For now the callbacks have to run in async mode - the
            // first time we restart we need
            // to get out of there.  So set it here.
            // When we figure out how to nest watchpoint hits then this will
            // change.

          bool old_async = debugger.GetAsyncExecution();
          debugger.SetAsyncExecution(true);

          StoppointCallbackContext context(event_ptr, exe_ctx, false);
          bool stop_requested = wp_sp->InvokeCallback(&context);

          debugger.SetAsyncExecution(old_async);

          // Also make sure that the callback hasn't continued the target. If
          // it did, when we'll set m_should_stop to false and get out of here.
          if (HasTargetRunSinceMe())
            m_should_stop = false;

          if (m_should_stop && !stop_requested) {
            // We have been vetoed by the callback mechanism.
            m_should_stop = false;
          }
        }
        // Finally, if we are going to stop, print out the new & old values:
        if (m_should_stop) {
          wp_sp->CaptureWatchedValue(exe_ctx);

          Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
          StreamSP output_sp = debugger.GetAsyncOutputStream();
          wp_sp->DumpSnapshots(output_sp.get());
          output_sp->EOL();
          output_sp->Flush();
        }

      } else {
        Log *log_process(GetLog(LLDBLog::Process));

        LLDB_LOGF(log_process,
                  "Process::%s could not find watchpoint id: %" PRId64 "...",
                  __FUNCTION__, m_value);
      }
      LLDB_LOGF(log,
                "Process::%s returning from action with m_should_stop: %d.",
                __FUNCTION__, m_should_stop);

      m_should_stop_is_valid = true;
    }
  }

private:
  void SetStepOverPlanComplete() {
    assert(m_using_step_over_plan);
    m_step_over_plan_complete = true;
  }
  
  bool m_should_stop = false;
  bool m_should_stop_is_valid = false;
  // A false watchpoint hit has happened -
  // the thread stopped with a watchpoint
  // hit notification, but the watched region
  // was not actually accessed (as determined
  // by the gdb stub we're talking to).
  // Continue past this watchpoint without
  // notifying the user; on some targets this
  // may mean disable wp, instruction step,
  // re-enable wp, continue.
  // On others, just continue.
  bool m_silently_skip_wp = false;
  bool m_step_over_plan_complete = false;
  bool m_using_step_over_plan = false;
};

// StopInfoUnixSignal

class StopInfoUnixSignal : public StopInfo {
public:
  StopInfoUnixSignal(Thread &thread, int signo, const char *description,
                     std::optional<int> code)
      : StopInfo(thread, signo), m_code(code) {
    SetDescription(description);
  }

  ~StopInfoUnixSignal() override = default;

  StopReason GetStopReason() const override { return eStopReasonSignal; }

  bool ShouldStopSynchronous(Event *event_ptr) override {
    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp)
      return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);
    return false;
  }

  bool ShouldStop(Event *event_ptr) override {
    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp)
      return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value);
    return false;
  }

  // If should stop returns false, check if we should notify of this event
  bool DoShouldNotify(Event *event_ptr) override {
    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp) {
      bool should_notify =
          thread_sp->GetProcess()->GetUnixSignals()->GetShouldNotify(m_value);
      if (should_notify) {
        StreamString strm;
        strm.Printf(
            "thread %d received signal: %s", thread_sp->GetIndexID(),
            thread_sp->GetProcess()->GetUnixSignals()->GetSignalAsCString(
                m_value));
        Process::ProcessEventData::AddRestartedReason(event_ptr,
                                                      strm.GetData());
      }
      return should_notify;
    }
    return true;
  }

  void WillResume(lldb::StateType resume_state) override {
    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp) {
      if (!thread_sp->GetProcess()->GetUnixSignals()->GetShouldSuppress(
              m_value))
        thread_sp->SetResumeSignal(m_value);
    }
  }

  const char *GetDescription() override {
    if (m_description.empty()) {
      ThreadSP thread_sp(m_thread_wp.lock());
      if (thread_sp) {
        UnixSignalsSP unix_signals = thread_sp->GetProcess()->GetUnixSignals();
        StreamString strm;
        strm << "signal ";

        std::string signal_name =
            unix_signals->GetSignalDescription(m_value, m_code);
        if (signal_name.size())
          strm << signal_name;
        else
          strm.Printf("%" PRIi64, m_value);

        m_description = std::string(strm.GetString());
      }
    }
    return m_description.c_str();
  }

private:
  // In siginfo_t terms, if m_value is si_signo, m_code is si_code.
  std::optional<int> m_code;
};

// StopInfoTrace

class StopInfoTrace : public StopInfo {
public:
  StopInfoTrace(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {}

  ~StopInfoTrace() override = default;

  StopReason GetStopReason() const override { return eStopReasonTrace; }

  const char *GetDescription() override {
    if (m_description.empty())
      return "trace";
    else
      return m_description.c_str();
  }
};

// StopInfoException

class StopInfoException : public StopInfo {
public:
  StopInfoException(Thread &thread, const char *description)
      : StopInfo(thread, LLDB_INVALID_UID) {
    if (description)
      SetDescription(description);
  }

  ~StopInfoException() override = default;

  StopReason GetStopReason() const override { return eStopReasonException; }

  const char *GetDescription() override {
    if (m_description.empty())
      return "exception";
    else
      return m_description.c_str();
  }
};

// StopInfoProcessorTrace

class StopInfoProcessorTrace : public StopInfo {
public:
  StopInfoProcessorTrace(Thread &thread, const char *description)
      : StopInfo(thread, LLDB_INVALID_UID) {
    if (description)
      SetDescription(description);
  }

  ~StopInfoProcessorTrace() override = default;

  StopReason GetStopReason() const override {
    return eStopReasonProcessorTrace;
  }

  const char *GetDescription() override {
    if (m_description.empty())
      return "processor trace event";
    else
      return m_description.c_str();
  }
};

// StopInfoThreadPlan

class StopInfoThreadPlan : public StopInfo {
public:
  StopInfoThreadPlan(ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp,
                     ExpressionVariableSP &expression_variable_sp)
      : StopInfo(plan_sp->GetThread(), LLDB_INVALID_UID), m_plan_sp(plan_sp),
        m_return_valobj_sp(return_valobj_sp),
        m_expression_variable_sp(expression_variable_sp) {}

  ~StopInfoThreadPlan() override = default;

  StopReason GetStopReason() const override { return eStopReasonPlanComplete; }

  const char *GetDescription() override {
    if (m_description.empty()) {
      StreamString strm;
      m_plan_sp->GetDescription(&strm, eDescriptionLevelBrief);
      m_description = std::string(strm.GetString());
    }
    return m_description.c_str();
  }

  ValueObjectSP GetReturnValueObject() { return m_return_valobj_sp; }

  ExpressionVariableSP GetExpressionVariable() {
    return m_expression_variable_sp;
  }

protected:
  bool ShouldStop(Event *event_ptr) override {
    if (m_plan_sp)
      return m_plan_sp->ShouldStop(event_ptr);
    else
      return StopInfo::ShouldStop(event_ptr);
  }

private:
  ThreadPlanSP m_plan_sp;
  ValueObjectSP m_return_valobj_sp;
  ExpressionVariableSP m_expression_variable_sp;
};

// StopInfoExec

class StopInfoExec : public StopInfo {
public:
  StopInfoExec(Thread &thread) : StopInfo(thread, LLDB_INVALID_UID) {}

  ~StopInfoExec() override = default;

  bool ShouldStop(Event *event_ptr) override {
    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp)
      return thread_sp->GetProcess()->GetStopOnExec();
    return false;
  }

  StopReason GetStopReason() const override { return eStopReasonExec; }

  const char *GetDescription() override { return "exec"; }

protected:
  void PerformAction(Event *event_ptr) override {
    // Only perform the action once
    if (m_performed_action)
      return;
    m_performed_action = true;
    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp)
      thread_sp->GetProcess()->DidExec();
  }

  bool m_performed_action = false;
};

// StopInfoFork

class StopInfoFork : public StopInfo {
public:
  StopInfoFork(Thread &thread, lldb::pid_t child_pid, lldb::tid_t child_tid)
      : StopInfo(thread, child_pid), m_child_pid(child_pid),
        m_child_tid(child_tid) {}

  ~StopInfoFork() override = default;

  bool ShouldStop(Event *event_ptr) override { return false; }

  StopReason GetStopReason() const override { return eStopReasonFork; }

  const char *GetDescription() override { return "fork"; }

protected:
  void PerformAction(Event *event_ptr) override {
    // Only perform the action once
    if (m_performed_action)
      return;
    m_performed_action = true;
    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp)
      thread_sp->GetProcess()->DidFork(m_child_pid, m_child_tid);
  }

  bool m_performed_action = false;

private:
  lldb::pid_t m_child_pid;
  lldb::tid_t m_child_tid;
};

// StopInfoVFork

class StopInfoVFork : public StopInfo {
public:
  StopInfoVFork(Thread &thread, lldb::pid_t child_pid, lldb::tid_t child_tid)
      : StopInfo(thread, child_pid), m_child_pid(child_pid),
        m_child_tid(child_tid) {}

  ~StopInfoVFork() override = default;

  bool ShouldStop(Event *event_ptr) override { return false; }

  StopReason GetStopReason() const override { return eStopReasonVFork; }

  const char *GetDescription() override { return "vfork"; }

protected:
  void PerformAction(Event *event_ptr) override {
    // Only perform the action once
    if (m_performed_action)
      return;
    m_performed_action = true;
    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp)
      thread_sp->GetProcess()->DidVFork(m_child_pid, m_child_tid);
  }

  bool m_performed_action = false;

private:
  lldb::pid_t m_child_pid;
  lldb::tid_t m_child_tid;
};

// StopInfoVForkDone

class StopInfoVForkDone : public StopInfo {
public:
  StopInfoVForkDone(Thread &thread) : StopInfo(thread, 0) {}

  ~StopInfoVForkDone() override = default;

  bool ShouldStop(Event *event_ptr) override { return false; }

  StopReason GetStopReason() const override { return eStopReasonVForkDone; }

  const char *GetDescription() override { return "vforkdone"; }

protected:
  void PerformAction(Event *event_ptr) override {
    // Only perform the action once
    if (m_performed_action)
      return;
    m_performed_action = true;
    ThreadSP thread_sp(m_thread_wp.lock());
    if (thread_sp)
      thread_sp->GetProcess()->DidVForkDone();
  }

  bool m_performed_action = false;
};

} // namespace lldb_private

StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,
                                                          break_id_t break_id) {
  return StopInfoSP(new StopInfoBreakpoint(thread, break_id));
}

StopInfoSP StopInfo::CreateStopReasonWithBreakpointSiteID(Thread &thread,
                                                          break_id_t break_id,
                                                          bool should_stop) {
  return StopInfoSP(new StopInfoBreakpoint(thread, break_id, should_stop));
}

StopInfoSP StopInfo::CreateStopReasonWithWatchpointID(Thread &thread,
                                                      break_id_t watch_id,
                                                      bool silently_continue) {
  return StopInfoSP(
      new StopInfoWatchpoint(thread, watch_id, silently_continue));
}

StopInfoSP StopInfo::CreateStopReasonWithSignal(Thread &thread, int signo,
                                                const char *description,
                                                std::optional<int> code) {
  thread.GetProcess()->GetUnixSignals()->IncrementSignalHitCount(signo);
  return StopInfoSP(new StopInfoUnixSignal(thread, signo, description, code));
}

StopInfoSP StopInfo::CreateStopReasonToTrace(Thread &thread) {
  return StopInfoSP(new StopInfoTrace(thread));
}

StopInfoSP StopInfo::CreateStopReasonWithPlan(
    ThreadPlanSP &plan_sp, ValueObjectSP return_valobj_sp,
    ExpressionVariableSP expression_variable_sp) {
  return StopInfoSP(new StopInfoThreadPlan(plan_sp, return_valobj_sp,
                                           expression_variable_sp));
}

StopInfoSP StopInfo::CreateStopReasonWithException(Thread &thread,
                                                   const char *description) {
  return StopInfoSP(new StopInfoException(thread, description));
}

StopInfoSP StopInfo::CreateStopReasonProcessorTrace(Thread &thread,
                                                    const char *description) {
  return StopInfoSP(new StopInfoProcessorTrace(thread, description));
}

StopInfoSP StopInfo::CreateStopReasonWithExec(Thread &thread) {
  return StopInfoSP(new StopInfoExec(thread));
}

StopInfoSP StopInfo::CreateStopReasonFork(Thread &thread,
                                          lldb::pid_t child_pid,
                                          lldb::tid_t child_tid) {
  return StopInfoSP(new StopInfoFork(thread, child_pid, child_tid));
}


StopInfoSP StopInfo::CreateStopReasonVFork(Thread &thread,
                                           lldb::pid_t child_pid,
                                           lldb::tid_t child_tid) {
  return StopInfoSP(new StopInfoVFork(thread, child_pid, child_tid));
}

StopInfoSP StopInfo::CreateStopReasonVForkDone(Thread &thread) {
  return StopInfoSP(new StopInfoVForkDone(thread));
}

ValueObjectSP StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp) {
  if (stop_info_sp &&
      stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {
    StopInfoThreadPlan *plan_stop_info =
        static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
    return plan_stop_info->GetReturnValueObject();
  } else
    return ValueObjectSP();
}

ExpressionVariableSP StopInfo::GetExpressionVariable(StopInfoSP &stop_info_sp) {
  if (stop_info_sp &&
      stop_info_sp->GetStopReason() == eStopReasonPlanComplete) {
    StopInfoThreadPlan *plan_stop_info =
        static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
    return plan_stop_info->GetExpressionVariable();
  } else
    return ExpressionVariableSP();
}

lldb::ValueObjectSP
StopInfo::GetCrashingDereference(StopInfoSP &stop_info_sp,
                                 lldb::addr_t *crashing_address) {
  if (!stop_info_sp) {
    return ValueObjectSP();
  }

  const char *description = stop_info_sp->GetDescription();
  if (!description) {
    return ValueObjectSP();
  }

  ThreadSP thread_sp = stop_info_sp->GetThread();
  if (!thread_sp) {
    return ValueObjectSP();
  }

  StackFrameSP frame_sp =
      thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);

  if (!frame_sp) {
    return ValueObjectSP();
  }

  const char address_string[] = "address=";

  const char *address_loc = strstr(description, address_string);
  if (!address_loc) {
    return ValueObjectSP();
  }

  address_loc += (sizeof(address_string) - 1);

  uint64_t address = strtoull(address_loc, nullptr, 0);
  if (crashing_address) {
    *crashing_address = address;
  }

  return frame_sp->GuessValueForAddress(address);
}
