brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.7 KiB · 42bee79 Raw
255 lines · cpp
1//===-- ThreadPlanStepInstruction.cpp -------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Target/ThreadPlanStepInstruction.h"10#include "lldb/Target/Process.h"11#include "lldb/Target/RegisterContext.h"12#include "lldb/Target/StopInfo.h"13#include "lldb/Target/Target.h"14#include "lldb/Utility/LLDBLog.h"15#include "lldb/Utility/Log.h"16#include "lldb/Utility/Stream.h"17 18using namespace lldb;19using namespace lldb_private;20 21// ThreadPlanStepInstruction: Step over the current instruction22 23ThreadPlanStepInstruction::ThreadPlanStepInstruction(Thread &thread,24                                                     bool step_over,25                                                     bool stop_other_threads,26                                                     Vote report_stop_vote,27                                                     Vote report_run_vote)28    : ThreadPlan(ThreadPlan::eKindStepInstruction,29                 "Step over single instruction", thread, report_stop_vote,30                 report_run_vote),31      m_instruction_addr(0), m_stop_other_threads(stop_other_threads),32      m_step_over(step_over) {33  m_takes_iteration_count = true;34  SetUpState();35}36 37ThreadPlanStepInstruction::~ThreadPlanStepInstruction() = default;38 39void ThreadPlanStepInstruction::SetUpState() {40  Thread &thread = GetThread();41  m_instruction_addr = thread.GetRegisterContext()->GetPC(0);42  StackFrameSP start_frame_sp(thread.GetStackFrameAtIndex(0));43  m_stack_id = start_frame_sp->GetStackID();44 45  m_start_has_symbol =46      start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != nullptr;47 48  StackFrameSP parent_frame_sp = thread.GetStackFrameAtIndex(1);49  if (parent_frame_sp)50    m_parent_frame_id = parent_frame_sp->GetStackID();51}52 53void ThreadPlanStepInstruction::GetDescription(Stream *s,54                                               lldb::DescriptionLevel level) {55  auto PrintFailureIfAny = [&]() {56    if (m_status.Success())57      return;58    s->Printf(" failed (%s)", m_status.AsCString());59  };60 61  if (level == lldb::eDescriptionLevelBrief) {62    if (m_step_over)63      s->Printf("instruction step over");64    else65      s->Printf("instruction step into");66 67    PrintFailureIfAny();68  } else {69    s->Printf("Stepping one instruction past ");70    DumpAddress(s->AsRawOstream(), m_instruction_addr, sizeof(addr_t));71    if (!m_start_has_symbol)72      s->Printf(" which has no symbol");73 74    if (m_step_over)75      s->Printf(" stepping over calls");76    else77      s->Printf(" stepping into calls");78 79    PrintFailureIfAny();80  }81}82 83bool ThreadPlanStepInstruction::ValidatePlan(Stream *error) {84  // Since we read the instruction we're stepping over from the thread, this85  // plan will always work.86  return true;87}88 89bool ThreadPlanStepInstruction::DoPlanExplainsStop(Event *event_ptr) {90  StopInfoSP stop_info_sp = GetPrivateStopInfo();91  if (stop_info_sp) {92    StopReason reason = stop_info_sp->GetStopReason();93    return (reason == eStopReasonTrace || reason == eStopReasonNone);94  }95  return false;96}97 98bool ThreadPlanStepInstruction::IsPlanStale() {99  Log *log = GetLog(LLDBLog::Step);100  Thread &thread = GetThread();101  StackID cur_frame_id = thread.GetStackFrameAtIndex(0)->GetStackID();102  if (cur_frame_id == m_stack_id) {103    // Set plan Complete when we reach next instruction104    uint64_t pc = thread.GetRegisterContext()->GetPC(0);105    uint32_t max_opcode_size =106        GetTarget().GetArchitecture().GetMaximumOpcodeByteSize();107    bool next_instruction_reached = (pc > m_instruction_addr) &&108        (pc <= m_instruction_addr + max_opcode_size);109    if (next_instruction_reached) {110      SetPlanComplete();111    }112    return (thread.GetRegisterContext()->GetPC(0) != m_instruction_addr);113  } else if (cur_frame_id < m_stack_id) {114    // If the current frame is younger than the start frame and we are stepping115    // over, then we need to continue, but if we are doing just one step, we're116    // done.117    return !m_step_over;118  } else {119    if (log) {120      LLDB_LOGF(log,121                "ThreadPlanStepInstruction::IsPlanStale - Current frame is "122                "older than start frame, plan is stale.");123    }124    return true;125  }126}127 128bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) {129  Thread &thread = GetThread();130  if (m_step_over) {131    Log *log = GetLog(LLDBLog::Step);132    StackFrameSP cur_frame_sp = thread.GetStackFrameAtIndex(0);133    if (!cur_frame_sp) {134      LLDB_LOGF(135          log,136          "ThreadPlanStepInstruction couldn't get the 0th frame, stopping.");137      SetPlanComplete();138      return true;139    }140 141    StackID cur_frame_zero_id = cur_frame_sp->GetStackID();142 143    if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id) {144      if (thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) {145        if (--m_iteration_count <= 0) {146          SetPlanComplete();147          return true;148        } else {149          // We are still stepping, reset the start pc, and in case we've150          // stepped out, reset the current stack id.151          SetUpState();152          return false;153        }154      } else155        return false;156    } else {157      // We've stepped in, step back out again:158      StackFrame *return_frame = thread.GetStackFrameAtIndex(1).get();159      if (return_frame) {160        if (return_frame->GetStackID() != m_parent_frame_id ||161            m_start_has_symbol) {162          // next-instruction shouldn't step out of inlined functions.  But we163          // may have stepped into a real function that starts with an inlined164          // function, and we do want to step out of that...165 166          if (cur_frame_sp->IsInlined()) {167            StackFrameSP parent_frame_sp =168                thread.GetFrameWithStackID(m_stack_id);169 170            if (parent_frame_sp &&171                parent_frame_sp->GetConcreteFrameIndex() ==172                    cur_frame_sp->GetConcreteFrameIndex()) {173              SetPlanComplete();174              if (log) {175                LLDB_LOGF(log,176                          "Frame we stepped into is inlined into the frame "177                          "we were stepping from, stopping.");178              }179              return true;180            }181          }182 183          if (log) {184            StreamString s;185            s.PutCString("Stepped in to: ");186            addr_t stop_addr =187                thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();188            DumpAddress(s.AsRawOstream(), stop_addr,189                        GetTarget().GetArchitecture().GetAddressByteSize());190            s.PutCString(" stepping out to: ");191            addr_t return_addr = return_frame->GetRegisterContext()->GetPC();192            DumpAddress(s.AsRawOstream(), return_addr,193                        GetTarget().GetArchitecture().GetAddressByteSize());194            LLDB_LOGF(log, "%s.", s.GetData());195          }196 197          // StepInstruction should probably have the tri-state RunMode, but198          // for now it is safer to run others.199          const bool stop_others = false;200          thread.QueueThreadPlanForStepOutNoShouldStop(201              false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,202              m_status);203          return false;204        } else {205          if (log) {206            log->PutCString(207                "The stack id we are stepping in changed, but our parent frame "208                "did not when stepping from code with no symbols.  "209                "We are probably just confused about where we are, stopping.");210          }211          SetPlanComplete();212          return true;213        }214      } else {215        LLDB_LOGF(log, "Could not find previous frame, stopping.");216        SetPlanComplete();217        return true;218      }219    }220  } else {221    lldb::addr_t pc_addr = thread.GetRegisterContext()->GetPC(0);222    if (pc_addr != m_instruction_addr) {223      if (--m_iteration_count <= 0) {224        SetPlanComplete();225        return true;226      } else {227        // We are still stepping, reset the start pc, and in case we've stepped228        // in or out, reset the current stack id.229        SetUpState();230        return false;231      }232    } else233      return false;234  }235}236 237bool ThreadPlanStepInstruction::StopOthers() { return m_stop_other_threads; }238 239StateType ThreadPlanStepInstruction::GetPlanRunState() {240  return eStateStepping;241}242 243bool ThreadPlanStepInstruction::WillStop() { return true; }244 245bool ThreadPlanStepInstruction::MischiefManaged() {246  if (IsPlanComplete()) {247    Log *log = GetLog(LLDBLog::Step);248    LLDB_LOGF(log, "Completed single instruction step plan.");249    ThreadPlan::MischiefManaged();250    return true;251  } else {252    return false;253  }254}255