brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · d2cca49 Raw
202 lines · cpp
1//===-- ThreadPlanShouldStopHere.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/ThreadPlanShouldStopHere.h"10#include "lldb/Symbol/Symbol.h"11#include "lldb/Target/Language.h"12#include "lldb/Target/LanguageRuntime.h"13#include "lldb/Target/RegisterContext.h"14#include "lldb/Target/Thread.h"15#include "lldb/Utility/LLDBLog.h"16#include "lldb/Utility/Log.h"17 18using namespace lldb;19using namespace lldb_private;20 21// ThreadPlanShouldStopHere constructor22ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner)23    : m_callbacks(), m_baton(nullptr), m_owner(owner),24      m_flags(ThreadPlanShouldStopHere::eNone) {25  m_callbacks.should_stop_here_callback =26      ThreadPlanShouldStopHere::DefaultShouldStopHereCallback;27  m_callbacks.step_from_here_callback =28      ThreadPlanShouldStopHere::DefaultStepFromHereCallback;29}30 31ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(32    ThreadPlan *owner, const ThreadPlanShouldStopHereCallbacks *callbacks,33    void *baton)34    : m_callbacks(), m_baton(), m_owner(owner),35      m_flags(ThreadPlanShouldStopHere::eNone) {36  SetShouldStopHereCallbacks(callbacks, baton);37}38 39ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere() = default;40 41bool ThreadPlanShouldStopHere::InvokeShouldStopHereCallback(42    FrameComparison operation, Status &status) {43  bool should_stop_here = true;44  if (m_callbacks.should_stop_here_callback) {45    should_stop_here = m_callbacks.should_stop_here_callback(46        m_owner, m_flags, operation, status, m_baton);47    Log *log = GetLog(LLDBLog::Step);48    if (log) {49      lldb::addr_t current_addr =50          m_owner->GetThread().GetRegisterContext()->GetPC(0);51 52      LLDB_LOGF(log, "ShouldStopHere callback returned %u from 0x%" PRIx64 ".",53                should_stop_here, current_addr);54    }55  }56 57  return should_stop_here;58}59 60bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(61    ThreadPlan *current_plan, Flags &flags, FrameComparison operation,62    Status &status, void *baton) {63  bool should_stop_here = true;64  StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();65  if (!frame)66    return true;67 68  Log *log = GetLog(LLDBLog::Step);69 70  if ((operation == eFrameCompareOlder && flags.Test(eStepOutAvoidNoDebug)) ||71      (operation == eFrameCompareYounger && flags.Test(eStepInAvoidNoDebug)) ||72      (operation == eFrameCompareSameParent &&73       flags.Test(eStepInAvoidNoDebug))) {74    if (!frame->HasDebugInformation()) {75      LLDB_LOGF(log, "Stepping out of frame with no debug info");76 77      should_stop_here = false;78    }79  }80 81  // Check whether the frame we are in is a language runtime thunk, only for82  // step out:83  if (operation == eFrameCompareOlder) {84    if (Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol) {85      ProcessSP process_sp(current_plan->GetThread().GetProcess());86      for (auto *runtime : process_sp->GetLanguageRuntimes()) {87        if (runtime->IsSymbolARuntimeThunk(*symbol) &&88            flags.Test(ThreadPlanShouldStopHere::eStepOutPastThunks)) {89          LLDB_LOGF(90              log, "Stepping out past a language thunk %s for: %s",91              frame->GetFunctionName(),92              Language::GetNameForLanguageType(runtime->GetLanguageType()));93          should_stop_here = false;94          break;95        }96      }97    }98  }99  // Always avoid code with line number 0.100  // FIXME: At present the ShouldStop and the StepFromHere calculate this101  // independently.  If this ever102  // becomes expensive (this one isn't) we can try to have this set a state103  // that the StepFromHere can use.104  if (frame) {105    SymbolContext sc;106    sc = frame->GetSymbolContext(eSymbolContextLineEntry);107    if (sc.line_entry.line == 0)108      should_stop_here = false;109  }110 111  return should_stop_here;112}113 114ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback(115    ThreadPlan *current_plan, Flags &flags, FrameComparison operation,116    Status &status, void *baton) {117  const bool stop_others = false;118  const size_t frame_index = 0;119  ThreadPlanSP return_plan_sp;120  // If we are stepping through code at line number 0, then we need to step121  // over this range.  Otherwise we will step out.122  Log *log = GetLog(LLDBLog::Step);123 124  StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();125  if (!frame)126    return return_plan_sp;127  SymbolContext sc;128  sc = frame->GetSymbolContext(eSymbolContextLineEntry | eSymbolContextSymbol);129 130  if (sc.line_entry.line == 0) {131    AddressRange range = sc.line_entry.range;132    bool just_step_out = false;133    if (sc.symbol) {134      ProcessSP process_sp(current_plan->GetThread().GetProcess());135 136      // If this is a runtime thunk, step through it, rather than stepping out137      // because it's marked line 0.138      bool is_thunk = false;139      for (auto *runtime : process_sp->GetLanguageRuntimes()) {140        if (runtime->IsSymbolARuntimeThunk(*sc.symbol) &&141            flags.Test(ThreadPlanShouldStopHere::eStepOutPastThunks)) {142          LLDB_LOGF(143              log, "Stepping out past a language thunk %s for: %s",144              frame->GetFunctionName(),145              Language::GetNameForLanguageType(runtime->GetLanguageType()));146          is_thunk = true;147          break;148        }149      }150 151      // If the whole function is marked line 0 just step out, that's easier &152      // faster than continuing to step through it.153      // FIXME: This assumes that the function is a single line range.  It could154      // be a series of contiguous line 0 ranges.  Check for that too.155      if (!is_thunk && sc.symbol->ValueIsAddress()) {156        Address symbol_end = sc.symbol->GetAddress();157        symbol_end.Slide(sc.symbol->GetByteSize() - 1);158        if (range.ContainsFileAddress(sc.symbol->GetAddress()) &&159            range.ContainsFileAddress(symbol_end)) {160          LLDB_LOGF(log, "Stopped in a function with only line 0 lines, just "161                         "stepping out.");162          just_step_out = true;163        }164      }165    }166    if (!just_step_out) {167      LLDB_LOGF(log, "ThreadPlanShouldStopHere::DefaultStepFromHereCallback "168                     "Queueing StepInRange plan to step through line 0 code.");169 170      return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepInRange(171          false, range, sc, nullptr, eOnlyDuringStepping, status,172          eLazyBoolCalculate, eLazyBoolNo);173    }174  }175 176  if (!return_plan_sp)177    return_plan_sp =178        current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop(179            false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion,180            frame_index, status, true);181  return return_plan_sp;182}183 184ThreadPlanSP ThreadPlanShouldStopHere::QueueStepOutFromHerePlan(185    lldb_private::Flags &flags, lldb::FrameComparison operation,186    Status &status) {187  ThreadPlanSP return_plan_sp;188  if (m_callbacks.step_from_here_callback) {189    return_plan_sp = m_callbacks.step_from_here_callback(190        m_owner, flags, operation, status, m_baton);191  }192  return return_plan_sp;193}194 195lldb::ThreadPlanSP ThreadPlanShouldStopHere::CheckShouldStopHereAndQueueStepOut(196    lldb::FrameComparison operation, Status &status) {197  if (!InvokeShouldStopHereCallback(operation, status))198    return QueueStepOutFromHerePlan(m_flags, operation, status);199  else200    return ThreadPlanSP();201}202