//===-- ThreadPlanStepUntil.cpp ---------------------------------*- C++ -*-===//
//
// 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/ThreadPlanStepUntil.h"

#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Symbol/SymbolContextScope.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// ThreadPlanStepUntil: Run until we reach a given line number or step out of
// the current frame
//----------------------------------------------------------------------

ThreadPlanStepUntil::ThreadPlanStepUntil(Thread &thread,
                                         lldb::addr_t *address_list,
                                         size_t num_addresses, bool stop_others,
                                         uint32_t frame_idx)
    : ThreadPlan(ThreadPlan::eKindStepUntil, "Step until", thread,
                 eVoteNoOpinion, eVoteNoOpinion),
      m_step_from_insn(LLDB_INVALID_ADDRESS),
      m_return_bp_id(LLDB_INVALID_BREAK_ID),
      m_return_addr(LLDB_INVALID_ADDRESS), m_stepped_out(false),
      m_should_stop(false), m_ran_analyze(false), m_explains_stop(false),
      m_until_points(), m_stop_others(stop_others) {
  // Stash away our "until" addresses:
  TargetSP target_sp(m_thread.CalculateTarget());

  StackFrameSP frame_sp(m_thread.GetStackFrameAtIndex(frame_idx));
  if (frame_sp) {
    m_step_from_insn = frame_sp->GetStackID().GetPC();
    lldb::user_id_t thread_id = m_thread.GetID();

    // Find the return address and set a breakpoint there:
    // FIXME - can we do this more securely if we know first_insn?

    StackFrameSP return_frame_sp(m_thread.GetStackFrameAtIndex(frame_idx + 1));
    if (return_frame_sp) {
      // TODO: add inline functionality
      m_return_addr = return_frame_sp->GetStackID().GetPC();
      Breakpoint *return_bp =
          target_sp->CreateBreakpoint(m_return_addr, true, false).get();

      if (return_bp != nullptr) {
        if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
          m_could_not_resolve_hw_bp = true;
        return_bp->SetThreadID(thread_id);
        m_return_bp_id = return_bp->GetID();
        return_bp->SetBreakpointKind("until-return-backstop");
      }
    }

    m_stack_id = frame_sp->GetStackID();

    // Now set breakpoints on all our return addresses:
    for (size_t i = 0; i < num_addresses; i++) {
      Breakpoint *until_bp =
          target_sp->CreateBreakpoint(address_list[i], true, false).get();
      if (until_bp != nullptr) {
        until_bp->SetThreadID(thread_id);
        m_until_points[address_list[i]] = until_bp->GetID();
        until_bp->SetBreakpointKind("until-target");
      } else {
        m_until_points[address_list[i]] = LLDB_INVALID_BREAK_ID;
      }
    }
  }
}

ThreadPlanStepUntil::~ThreadPlanStepUntil() { Clear(); }

void ThreadPlanStepUntil::Clear() {
  TargetSP target_sp(m_thread.CalculateTarget());
  if (target_sp) {
    if (m_return_bp_id != LLDB_INVALID_BREAK_ID) {
      target_sp->RemoveBreakpointByID(m_return_bp_id);
      m_return_bp_id = LLDB_INVALID_BREAK_ID;
    }

    until_collection::iterator pos, end = m_until_points.end();
    for (pos = m_until_points.begin(); pos != end; pos++) {
      target_sp->RemoveBreakpointByID((*pos).second);
    }
  }
  m_until_points.clear();
  m_could_not_resolve_hw_bp = false;
}

void ThreadPlanStepUntil::GetDescription(Stream *s,
                                         lldb::DescriptionLevel level) {
  if (level == lldb::eDescriptionLevelBrief) {
    s->Printf("step until");
    if (m_stepped_out)
      s->Printf(" - stepped out");
  } else {
    if (m_until_points.size() == 1)
      s->Printf("Stepping from address 0x%" PRIx64 " until we reach 0x%" PRIx64
                " using breakpoint %d",
                (uint64_t)m_step_from_insn,
                (uint64_t)(*m_until_points.begin()).first,
                (*m_until_points.begin()).second);
    else {
      until_collection::iterator pos, end = m_until_points.end();
      s->Printf("Stepping from address 0x%" PRIx64 " until we reach one of:",
                (uint64_t)m_step_from_insn);
      for (pos = m_until_points.begin(); pos != end; pos++) {
        s->Printf("\n\t0x%" PRIx64 " (bp: %d)", (uint64_t)(*pos).first,
                  (*pos).second);
      }
    }
    s->Printf(" stepped out address is 0x%" PRIx64 ".",
              (uint64_t)m_return_addr);
  }
}

bool ThreadPlanStepUntil::ValidatePlan(Stream *error) {
  if (m_could_not_resolve_hw_bp) {
    if (error)
      error->PutCString(
          "Could not create hardware breakpoint for thread plan.");
    return false;
  } else if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
    if (error)
      error->PutCString("Could not create return breakpoint.");
    return false;
  } else {
    until_collection::iterator pos, end = m_until_points.end();
    for (pos = m_until_points.begin(); pos != end; pos++) {
      if (!LLDB_BREAK_ID_IS_VALID((*pos).second))
        return false;
    }
    return true;
  }
}

void ThreadPlanStepUntil::AnalyzeStop() {
  if (m_ran_analyze)
    return;

  StopInfoSP stop_info_sp = GetPrivateStopInfo();
  m_should_stop = true;
  m_explains_stop = false;

  if (stop_info_sp) {
    StopReason reason = stop_info_sp->GetStopReason();

    if (reason == eStopReasonBreakpoint) {
      // If this is OUR breakpoint, we're fine, otherwise we don't know why
      // this happened...
      BreakpointSiteSP this_site =
          m_thread.GetProcess()->GetBreakpointSiteList().FindByID(
              stop_info_sp->GetValue());
      if (!this_site) {
        m_explains_stop = false;
        return;
      }

      if (this_site->IsBreakpointAtThisSite(m_return_bp_id)) {
        // If we are at our "step out" breakpoint, and the stack depth has
        // shrunk, then this is indeed our stop. If the stack depth has grown,
        // then we've hit our step out breakpoint recursively. If we are the
        // only breakpoint at that location, then we do explain the stop, and
        // we'll just continue. If there was another breakpoint here, then we
        // don't explain the stop, but we won't mark ourselves Completed,
        // because maybe that breakpoint will continue, and then we'll finish
        // the "until".
        bool done;
        StackID cur_frame_zero_id;

        done = (m_stack_id < cur_frame_zero_id);

        if (done) {
          m_stepped_out = true;
          SetPlanComplete();
        } else
          m_should_stop = false;

        if (this_site->GetNumberOfOwners() == 1)
          m_explains_stop = true;
        else
          m_explains_stop = false;
        return;
      } else {
        // Check if we've hit one of our "until" breakpoints.
        until_collection::iterator pos, end = m_until_points.end();
        for (pos = m_until_points.begin(); pos != end; pos++) {
          if (this_site->IsBreakpointAtThisSite((*pos).second)) {
            // If we're at the right stack depth, then we're done.

            bool done;
            StackID frame_zero_id =
                m_thread.GetStackFrameAtIndex(0)->GetStackID();

            if (frame_zero_id == m_stack_id)
              done = true;
            else if (frame_zero_id < m_stack_id)
              done = false;
            else {
              StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1);

              // But if we can't even unwind one frame we should just get out
              // of here & stop...
              if (older_frame_sp) {
                const SymbolContext &older_context =
                    older_frame_sp->GetSymbolContext(eSymbolContextEverything);
                SymbolContext stack_context;
                m_stack_id.GetSymbolContextScope()->CalculateSymbolContext(
                    &stack_context);

                done = (older_context == stack_context);
              } else
                done = false;
            }

            if (done)
              SetPlanComplete();
            else
              m_should_stop = false;

            // Otherwise we've hit this breakpoint recursively.  If we're the
            // only breakpoint here, then we do explain the stop, and we'll
            // continue. If not then we should let higher plans handle this
            // stop.
            if (this_site->GetNumberOfOwners() == 1)
              m_explains_stop = true;
            else {
              m_should_stop = true;
              m_explains_stop = false;
            }
            return;
          }
        }
      }
      // If we get here we haven't hit any of our breakpoints, so let the
      // higher plans take care of the stop.
      m_explains_stop = false;
      return;
    } else if (IsUsuallyUnexplainedStopReason(reason)) {
      m_explains_stop = false;
    } else {
      m_explains_stop = true;
    }
  }
}

bool ThreadPlanStepUntil::DoPlanExplainsStop(Event *event_ptr) {
  // We don't explain signals or breakpoints (breakpoints that handle stepping
  // in or out will be handled by a child plan.
  AnalyzeStop();
  return m_explains_stop;
}

bool ThreadPlanStepUntil::ShouldStop(Event *event_ptr) {
  // If we've told our self in ExplainsStop that we plan to continue, then do
  // so here.  Otherwise, as long as this thread has stopped for a reason, we
  // will stop.

  StopInfoSP stop_info_sp = GetPrivateStopInfo();
  if (!stop_info_sp || stop_info_sp->GetStopReason() == eStopReasonNone)
    return false;

  AnalyzeStop();
  return m_should_stop;
}

bool ThreadPlanStepUntil::StopOthers() { return m_stop_others; }

StateType ThreadPlanStepUntil::GetPlanRunState() { return eStateRunning; }

bool ThreadPlanStepUntil::DoWillResume(StateType resume_state,
                                       bool current_plan) {
  if (current_plan) {
    TargetSP target_sp(m_thread.CalculateTarget());
    if (target_sp) {
      Breakpoint *return_bp =
          target_sp->GetBreakpointByID(m_return_bp_id).get();
      if (return_bp != nullptr)
        return_bp->SetEnabled(true);

      until_collection::iterator pos, end = m_until_points.end();
      for (pos = m_until_points.begin(); pos != end; pos++) {
        Breakpoint *until_bp =
            target_sp->GetBreakpointByID((*pos).second).get();
        if (until_bp != nullptr)
          until_bp->SetEnabled(true);
      }
    }
  }

  m_should_stop = true;
  m_ran_analyze = false;
  m_explains_stop = false;
  return true;
}

bool ThreadPlanStepUntil::WillStop() {
  TargetSP target_sp(m_thread.CalculateTarget());
  if (target_sp) {
    Breakpoint *return_bp = target_sp->GetBreakpointByID(m_return_bp_id).get();
    if (return_bp != nullptr)
      return_bp->SetEnabled(false);

    until_collection::iterator pos, end = m_until_points.end();
    for (pos = m_until_points.begin(); pos != end; pos++) {
      Breakpoint *until_bp = target_sp->GetBreakpointByID((*pos).second).get();
      if (until_bp != nullptr)
        until_bp->SetEnabled(false);
    }
  }
  return true;
}

bool ThreadPlanStepUntil::MischiefManaged() {
  // I'm letting "PlanExplainsStop" do all the work, and just reporting that
  // here.
  bool done = false;
  if (IsPlanComplete()) {
    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
    if (log)
      log->Printf("Completed step until plan.");

    Clear();
    done = true;
  }
  if (done)
    ThreadPlan::MischiefManaged();

  return done;
}
