//===-- ThreadPlanStepRange.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/ThreadPlanStepRange.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"

using namespace lldb;
using namespace lldb_private;

// ThreadPlanStepRange: Step through a stack range, either stepping over or
// into based on the value of \a type.

ThreadPlanStepRange::ThreadPlanStepRange(ThreadPlanKind kind, const char *name,
                                         Thread &thread,
                                         const AddressRange &range,
                                         const SymbolContext &addr_context,
                                         lldb::RunMode stop_others,
                                         bool given_ranges_only)
    : ThreadPlan(kind, name, thread, eVoteNoOpinion, eVoteNoOpinion),
      m_addr_context(addr_context), m_address_ranges(),
      m_stop_others(stop_others), m_stack_id(), m_parent_stack_id(),
      m_no_more_plans(false), m_first_run_event(true), m_use_fast_step(false),
      m_given_ranges_only(given_ranges_only) {
  m_use_fast_step = GetTarget().GetUseFastStepping();
  AddRange(range);
  m_stack_id = thread.GetStackFrameAtIndex(0)->GetStackID();
  StackFrameSP parent_stack = thread.GetStackFrameAtIndex(1);
  if (parent_stack)
    m_parent_stack_id = parent_stack->GetStackID();
}

ThreadPlanStepRange::~ThreadPlanStepRange() { ClearNextBranchBreakpoint(); }

void ThreadPlanStepRange::DidPush() {
  // See if we can find a "next range" breakpoint:
  SetNextBranchBreakpoint();
}

bool ThreadPlanStepRange::ValidatePlan(Stream *error) {
  if (m_could_not_resolve_hw_bp) {
    if (error)
      error->PutCString(
          "Could not create hardware breakpoint for thread plan.");
    return false;
  }
  return true;
}

Vote ThreadPlanStepRange::ShouldReportStop(Event *event_ptr) {
  Log *log = GetLog(LLDBLog::Step);

  const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo;
  LLDB_LOGF(log, "ThreadPlanStepRange::ShouldReportStop() returning vote %i\n",
            vote);
  return vote;
}

void ThreadPlanStepRange::AddRange(const AddressRange &new_range) {
  // For now I'm just adding the ranges.  At some point we may want to condense
  // the ranges if they overlap, though I don't think it is likely to be very
  // important.
  m_address_ranges.push_back(new_range);

  // Fill the slot for this address range with an empty DisassemblerSP in the
  // instruction ranges. I want the indices to match, but I don't want to do
  // the work to disassemble this range if I don't step into it.
  m_instruction_ranges.push_back(DisassemblerSP());
}

void ThreadPlanStepRange::DumpRanges(Stream *s) {
  size_t num_ranges = m_address_ranges.size();
  if (num_ranges == 1) {
    m_address_ranges[0].Dump(s, &GetTarget(), Address::DumpStyleLoadAddress);
  } else {
    for (size_t i = 0; i < num_ranges; i++) {
      s->Printf(" %" PRIu64 ": ", uint64_t(i));
      m_address_ranges[i].Dump(s, &GetTarget(), Address::DumpStyleLoadAddress);
    }
  }
}

bool ThreadPlanStepRange::InRange() {
  Log *log = GetLog(LLDBLog::Step);
  bool ret_value = false;
  Thread &thread = GetThread();
  lldb::addr_t pc_load_addr = thread.GetRegisterContext()->GetPC();

  size_t num_ranges = m_address_ranges.size();
  for (size_t i = 0; i < num_ranges; i++) {
    ret_value = 
        m_address_ranges[i].ContainsLoadAddress(pc_load_addr, &GetTarget());
    if (ret_value)
      break;
  }

  if (!ret_value && !m_given_ranges_only) {
    // See if we've just stepped to another part of the same line number...
    StackFrame *frame = thread.GetStackFrameAtIndex(0).get();

    SymbolContext new_context(
        frame->GetSymbolContext(eSymbolContextEverything));
    if (m_addr_context.line_entry.IsValid() &&
        new_context.line_entry.IsValid()) {
      if (m_addr_context.line_entry.original_file_sp->Equal(
              *new_context.line_entry.original_file_sp,
              SupportFile::eEqualFileSpecAndChecksumIfSet)) {
        if (m_addr_context.line_entry.line == new_context.line_entry.line) {
          m_addr_context = new_context;
          const bool include_inlined_functions =
              GetKind() == eKindStepOverRange;
          AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange(
              include_inlined_functions));
          ret_value = true;
          if (log) {
            StreamString s;
            m_addr_context.line_entry.Dump(&s, &GetTarget(), true,
                                           Address::DumpStyleLoadAddress,
                                           Address::DumpStyleLoadAddress, true);

            LLDB_LOGF(
                log,
                "Step range plan stepped to another range of same line: %s",
                s.GetData());
          }
        } else if (new_context.line_entry.line == 0) {
          new_context.line_entry.line = m_addr_context.line_entry.line;
          m_addr_context = new_context;
          const bool include_inlined_functions =
              GetKind() == eKindStepOverRange;
          AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange(
              include_inlined_functions));
          ret_value = true;
          if (log) {
            StreamString s;
            m_addr_context.line_entry.Dump(&s, &GetTarget(), true,
                                           Address::DumpStyleLoadAddress,
                                           Address::DumpStyleLoadAddress, true);

            LLDB_LOGF(log,
                      "Step range plan stepped to a range at linenumber 0 "
                      "stepping through that range: %s",
                      s.GetData());
          }
        } else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(
                       &GetTarget()) != pc_load_addr) {
          // Another thing that sometimes happens here is that we step out of
          // one line into the MIDDLE of another line.  So far I mostly see
          // this due to bugs in the debug information. But we probably don't
          // want to be in the middle of a line range, so in that case reset
          // the stepping range to the line we've stepped into the middle of
          // and continue.
          m_addr_context = new_context;
          m_address_ranges.clear();
          AddRange(m_addr_context.line_entry.range);
          ret_value = true;
          if (log) {
            StreamString s;
            m_addr_context.line_entry.Dump(&s, &GetTarget(), true,
                                           Address::DumpStyleLoadAddress,
                                           Address::DumpStyleLoadAddress, true);

            LLDB_LOGF(log,
                      "Step range plan stepped to the middle of new "
                      "line(%d): %s, continuing to clear this line.",
                      new_context.line_entry.line, s.GetData());
          }
        }
      }
    }
  }

  if (!ret_value && log)
    LLDB_LOGF(log, "Step range plan out of range to 0x%" PRIx64, pc_load_addr);

  return ret_value;
}

bool ThreadPlanStepRange::InSymbol() {
  lldb::addr_t cur_pc = GetThread().GetRegisterContext()->GetPC();
  if (m_addr_context.function != nullptr) {
    AddressRange unused_range;
    return m_addr_context.function->GetRangeContainingLoadAddress(
        cur_pc, GetTarget(), unused_range);
  }
  if (m_addr_context.symbol && m_addr_context.symbol->ValueIsAddress()) {
    AddressRange range(m_addr_context.symbol->GetAddressRef(),
                       m_addr_context.symbol->GetByteSize());
    return range.ContainsLoadAddress(cur_pc, &GetTarget());
  }
  return false;
}

// FIXME: This should also handle inlining if we aren't going to do inlining in
// the
// main stack.
//
// Ideally we should remember the whole stack frame list, and then compare that
// to the current list.

lldb::FrameComparison ThreadPlanStepRange::CompareCurrentFrameToStartFrame() {
  FrameComparison frame_order;
  Thread &thread = GetThread();
  StackID cur_frame_id = thread.GetStackFrameAtIndex(0)->GetStackID();

  if (cur_frame_id == m_stack_id) {
    frame_order = eFrameCompareEqual;
  } else if (cur_frame_id.IsYoungerThan(m_stack_id)) {
    frame_order = eFrameCompareYounger;
  } else {
    StackFrameSP cur_parent_frame = thread.GetStackFrameAtIndex(1);
    StackID cur_parent_id;
    if (cur_parent_frame)
      cur_parent_id = cur_parent_frame->GetStackID();
    if (m_parent_stack_id.IsValid() && cur_parent_id.IsValid() &&
        m_parent_stack_id == cur_parent_id)
      frame_order = eFrameCompareSameParent;
    else
      frame_order = eFrameCompareOlder;
  }
  return frame_order;
}

bool ThreadPlanStepRange::StopOthers() {
  switch (m_stop_others) {
  case lldb::eOnlyThisThread:
    return true;
  case lldb::eOnlyDuringStepping:
    // If there is a call in the range of the next branch breakpoint,
    // then we should always run all threads, since a call can execute
    // arbitrary code which might for instance take a lock that's held
    // by another thread.
    return !m_found_calls;
  case lldb::eAllThreads:
    return false;
  }
  llvm_unreachable("Unhandled run mode!");
}

InstructionList *ThreadPlanStepRange::GetInstructionsForAddress(
    lldb::addr_t addr, size_t &range_index, size_t &insn_offset) {
  size_t num_ranges = m_address_ranges.size();
  for (size_t i = 0; i < num_ranges; i++) {
    if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) {
      // Some joker added a zero size range to the stepping range...
      if (m_address_ranges[i].GetByteSize() == 0)
        return nullptr;

      if (!m_instruction_ranges[i]) {
        // Disassemble the address range given:
        const char *plugin_name = nullptr;
        const char *flavor = nullptr;
        const char *cpu = nullptr;
        const char *features = nullptr;
        m_instruction_ranges[i] = Disassembler::DisassembleRange(
            GetTarget().GetArchitecture(), plugin_name, flavor, cpu, features,
            GetTarget(), m_address_ranges[i]);
      }
      if (!m_instruction_ranges[i])
        return nullptr;
      else {
        // Find where we are in the instruction list as well.  If we aren't at
        // an instruction, return nullptr. In this case, we're probably lost,
        // and shouldn't try to do anything fancy.

        insn_offset =
            m_instruction_ranges[i]
                ->GetInstructionList()
                .GetIndexOfInstructionAtLoadAddress(addr, GetTarget());
        if (insn_offset == UINT32_MAX)
          return nullptr;
        else {
          range_index = i;
          return &m_instruction_ranges[i]->GetInstructionList();
        }
      }
    }
  }
  return nullptr;
}

bool ThreadPlanStepRange::IsNextBranchBreakpointStop(StopInfoSP stop_info_sp) {
  if (!m_next_branch_bp_sp)
    return false;

  break_id_t bp_site_id = stop_info_sp->GetValue();
  BreakpointSiteSP bp_site_sp =
      m_process.GetBreakpointSiteList().FindByID(bp_site_id);
  if (!bp_site_sp)
    return false;
  else if (!bp_site_sp->IsBreakpointAtThisSite(m_next_branch_bp_sp->GetID()))
    return false;
  return true;
}

void ThreadPlanStepRange::ClearNextBranchBreakpoint() {
  if (m_next_branch_bp_sp) {
    Log *log = GetLog(LLDBLog::Step);
    LLDB_LOGF(log, "Removing next branch breakpoint: %d.",
              m_next_branch_bp_sp->GetID());
    GetTarget().RemoveBreakpointByID(m_next_branch_bp_sp->GetID());
    m_next_branch_bp_sp.reset();
    m_could_not_resolve_hw_bp = false;
    m_found_calls = false;
  }
}

void ThreadPlanStepRange::ClearNextBranchBreakpointExplainedStop() {
  if (IsNextBranchBreakpointStop(GetPrivateStopInfo()))
    ClearNextBranchBreakpoint();
}

bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
  if (m_next_branch_bp_sp)
    return true;

  Log *log = GetLog(LLDBLog::Step);
  // Stepping through ranges using breakpoints doesn't work yet, but with this
  // off we fall back to instruction single stepping.
  if (!m_use_fast_step)
    return false;

  // clear the m_found_calls, we'll rediscover it for this range.
  m_found_calls = false;
  
  lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC();
  // Find the current address in our address ranges, and fetch the disassembly
  // if we haven't already:
  size_t pc_index;
  size_t range_index;
  InstructionList *instructions =
      GetInstructionsForAddress(cur_addr, range_index, pc_index);
  if (instructions == nullptr)
    return false;
  else {
    const bool ignore_calls = GetKind() == eKindStepOverRange;
    uint32_t branch_index = instructions->GetIndexOfNextBranchInstruction(
        pc_index, ignore_calls, &m_found_calls);
    Address run_to_address;

    // If we didn't find a branch, run to the end of the range.
    if (branch_index == UINT32_MAX) {
      uint32_t last_index = instructions->GetSize() - 1;
      if (last_index - pc_index > 1) {
        InstructionSP last_inst =
            instructions->GetInstructionAtIndex(last_index);
        size_t last_inst_size = last_inst->GetOpcode().GetByteSize();
        run_to_address = last_inst->GetAddress();
        run_to_address.Slide(last_inst_size);
      }
    } else if (branch_index - pc_index > 1) {
      run_to_address =
          instructions->GetInstructionAtIndex(branch_index)->GetAddress();
    }
    if (branch_index == pc_index)
      LLDB_LOGF(log, "ThreadPlanStepRange::SetNextBranchBreakpoint - skipping "
                     "because current is branch instruction");
    if (run_to_address.IsValid()) {
      const bool is_internal = true;
      m_next_branch_bp_sp =
          GetTarget().CreateBreakpoint(run_to_address, is_internal, false);
      if (m_next_branch_bp_sp) {

        if (m_next_branch_bp_sp->IsHardware() &&
            !m_next_branch_bp_sp->HasResolvedLocations())
          m_could_not_resolve_hw_bp = true;

        BreakpointLocationSP bp_loc =
            m_next_branch_bp_sp->GetLocationAtIndex(0);
        if (log) {
          lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID;
          if (bp_loc) {
            BreakpointSiteSP bp_site = bp_loc->GetBreakpointSite();
            if (bp_site) {
              bp_site_id = bp_site->GetID();
            }
          }
          LLDB_LOGF(log,
                    "ThreadPlanStepRange::SetNextBranchBreakpoint - Setting "
                    "breakpoint %d (site %d) to run to address 0x%" PRIx64,
                    m_next_branch_bp_sp->GetID(), bp_site_id,
                    run_to_address.GetLoadAddress(&m_process.GetTarget()));
        }
        // The "next branch breakpoint might land on a virtual inlined call
        // stack.  If that's true, we should always stop at the top of the
        // inlined call stack.  Only virtual steps should walk deeper into the
        // inlined call stack.
        Block *block = run_to_address.CalculateSymbolContextBlock();
        if (bp_loc && block) {
          LineEntry top_most_line_entry;
          lldb::addr_t run_to_addr = run_to_address.GetFileAddress();
          for (Block *inlined_parent = block->GetContainingInlinedBlock();
               inlined_parent;
               inlined_parent = inlined_parent->GetInlinedParent()) {
            AddressRange range;
            if (!inlined_parent->GetRangeContainingAddress(run_to_address,
                                                           range))
              break;
            Address range_start_address = range.GetBaseAddress();
            // Only compare addresses here, we may have different symbol
            // contexts (for virtual inlined stacks), but we just want to know
            // that they are all at the same address.
            if (range_start_address.GetFileAddress() != run_to_addr)
              break;
            const InlineFunctionInfo *inline_info =
                inlined_parent->GetInlinedFunctionInfo();
            if (!inline_info)
              break;
            const Declaration &call_site = inline_info->GetCallSite();
            top_most_line_entry.line = call_site.GetLine();
            top_most_line_entry.column = call_site.GetColumn();
            FileSpec call_site_file_spec = call_site.GetFile();
            top_most_line_entry.original_file_sp =
                std::make_shared<SupportFile>(call_site_file_spec);
            top_most_line_entry.range = range;
            top_most_line_entry.file_sp = std::make_shared<SupportFile>();
            top_most_line_entry.ApplyFileMappings(
                GetThread().CalculateTarget());
            if (!top_most_line_entry.file_sp->GetSpecOnly())
              top_most_line_entry.file_sp =
                  top_most_line_entry.original_file_sp;
          }
          if (top_most_line_entry.IsValid()) {
            LLDB_LOG(log, "Setting preferred line entry: {0}:{1}",
                     top_most_line_entry.GetFile(), top_most_line_entry.line);
            bp_loc->SetPreferredLineEntry(top_most_line_entry);
          }
        }
        m_next_branch_bp_sp->SetThreadID(m_tid);
        m_next_branch_bp_sp->SetBreakpointKind("next-branch-location");

        return true;
      } else
        return false;
    } else
      LLDB_LOGF(log, "ThreadPlanStepRange::SetNextBranchBreakpoint - skipping "
                     "invalid run_to_address");
  }
  return false;
}

bool ThreadPlanStepRange::NextRangeBreakpointExplainsStop(
    lldb::StopInfoSP stop_info_sp) {
  if (!IsNextBranchBreakpointStop(stop_info_sp))
    return false;

  break_id_t bp_site_id = stop_info_sp->GetValue();
  BreakpointSiteSP bp_site_sp =
      m_process.GetBreakpointSiteList().FindByID(bp_site_id);
  if (!bp_site_sp)
    return false;

  // If we've hit the next branch breakpoint, then clear it.
  size_t num_constituents = bp_site_sp->GetNumberOfConstituents();
  bool explains_stop = true;
  // If all the constituents are internal, then we are probably just stepping
  // over this range from multiple threads, or multiple frames, so we want to
  // continue.  If one is not internal, then we should not explain the stop,
  // and let the user breakpoint handle the stop.
  for (size_t i = 0; i < num_constituents; i++) {
    if (!bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint().IsInternal()) {
      explains_stop = false;
      break;
    }
  }
  Log *log = GetLog(LLDBLog::Step);
  LLDB_LOGF(log,
            "ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit "
            "next range breakpoint which has %" PRIu64
            " constituents - explains stop: %u.",
            (uint64_t)num_constituents, explains_stop);
  return explains_stop;
}

bool ThreadPlanStepRange::WillStop() { return true; }

StateType ThreadPlanStepRange::GetPlanRunState() {
  if (m_next_branch_bp_sp)
    return eStateRunning;
  else
    return eStateStepping;
}

bool ThreadPlanStepRange::MischiefManaged() {
  // If we have pushed some plans between ShouldStop & MischiefManaged, then
  // we're not done...
  // I do this check first because we might have stepped somewhere that will
  // fool InRange into
  // thinking it needs to step past the end of that line.  This happens, for
  // instance, when stepping over inlined code that is in the middle of the
  // current line.

  if (!m_no_more_plans)
    return false;

  bool done = true;
  if (!IsPlanComplete()) {
    if (InRange()) {
      done = false;
    } else {
      FrameComparison frame_order = CompareCurrentFrameToStartFrame();
      done = (frame_order != eFrameCompareOlder) ? m_no_more_plans : true;
    }
  }

  if (done) {
    Log *log = GetLog(LLDBLog::Step);
    LLDB_LOGF(log, "Completed step through range plan.");
    ClearNextBranchBreakpoint();
    ThreadPlan::MischiefManaged();
    return true;
  } else {
    return false;
  }
}

bool ThreadPlanStepRange::IsPlanStale() {
  Log *log = GetLog(LLDBLog::Step);
  FrameComparison frame_order = CompareCurrentFrameToStartFrame();

  if (frame_order == eFrameCompareOlder) {
    LLDB_LOGF(log, "ThreadPlanStepRange::IsPlanStale returning true, we've "
                   "stepped out.");
    return true;
  } else if (frame_order == eFrameCompareEqual && InSymbol()) {
    // If we are not in a place we should step through, we've gotten stale. One
    // tricky bit here is that some stubs don't push a frame, so we should.
    // check that we are in the same symbol.
    if (!InRange()) {
      // Set plan Complete when we reach next instruction just after the range
      lldb::addr_t addr = GetThread().GetRegisterContext()->GetPC() - 1;
      size_t num_ranges = m_address_ranges.size();
      for (size_t i = 0; i < num_ranges; i++) {
        bool in_range = 
            m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget());
        if (in_range) {
          SetPlanComplete();
        }
      }
      return true;
    }
  }
  return false;
}
