//===-- 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 < 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) {
    if (log) {
      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;
}
