1 //===-- ThreadPlanStepInRange.cpp -------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 // Other libraries and framework includes
14 #include "lldb/Target/ThreadPlanStepInRange.h"
15 #include "lldb/Core/Architecture.h"
16 #include "lldb/Core/Module.h"
17 #include "lldb/Symbol/Function.h"
18 #include "lldb/Symbol/Symbol.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Target/RegisterContext.h"
21 #include "lldb/Target/SectionLoadList.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Target/Thread.h"
24 #include "lldb/Target/ThreadPlanStepOut.h"
25 #include "lldb/Target/ThreadPlanStepThrough.h"
26 #include "lldb/Utility/Log.h"
27 #include "lldb/Utility/RegularExpression.h"
28 #include "lldb/Utility/Stream.h"
31 using namespace lldb_private;
33 uint32_t ThreadPlanStepInRange::s_default_flag_values =
34 ThreadPlanShouldStopHere::eStepInAvoidNoDebug;
36 //----------------------------------------------------------------------
37 // ThreadPlanStepInRange: Step through a stack range, either stepping over or
38 // into based on the value of \a type.
39 //----------------------------------------------------------------------
41 ThreadPlanStepInRange::ThreadPlanStepInRange(
42 Thread &thread, const AddressRange &range,
43 const SymbolContext &addr_context, lldb::RunMode stop_others,
44 LazyBool step_in_avoids_code_without_debug_info,
45 LazyBool step_out_avoids_code_without_debug_info)
46 : ThreadPlanStepRange(ThreadPlan::eKindStepInRange,
47 "Step Range stepping in", thread, range, addr_context,
49 ThreadPlanShouldStopHere(this), m_step_past_prologue(true),
50 m_virtual_step(false) {
53 SetupAvoidNoDebug(step_in_avoids_code_without_debug_info,
54 step_out_avoids_code_without_debug_info);
57 ThreadPlanStepInRange::ThreadPlanStepInRange(
58 Thread &thread, const AddressRange &range,
59 const SymbolContext &addr_context, const char *step_into_target,
60 lldb::RunMode stop_others, LazyBool step_in_avoids_code_without_debug_info,
61 LazyBool step_out_avoids_code_without_debug_info)
62 : ThreadPlanStepRange(ThreadPlan::eKindStepInRange,
63 "Step Range stepping in", thread, range, addr_context,
65 ThreadPlanShouldStopHere(this), m_step_past_prologue(true),
66 m_virtual_step(false), m_step_into_target(step_into_target) {
69 SetupAvoidNoDebug(step_in_avoids_code_without_debug_info,
70 step_out_avoids_code_without_debug_info);
73 ThreadPlanStepInRange::~ThreadPlanStepInRange() = default;
75 void ThreadPlanStepInRange::SetupAvoidNoDebug(
76 LazyBool step_in_avoids_code_without_debug_info,
77 LazyBool step_out_avoids_code_without_debug_info) {
78 bool avoid_nodebug = true;
80 switch (step_in_avoids_code_without_debug_info) {
85 avoid_nodebug = false;
87 case eLazyBoolCalculate:
88 avoid_nodebug = m_thread.GetStepInAvoidsNoDebug();
92 GetFlags().Set(ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
94 GetFlags().Clear(ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
96 switch (step_out_avoids_code_without_debug_info) {
101 avoid_nodebug = false;
103 case eLazyBoolCalculate:
104 avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
108 GetFlags().Set(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
110 GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
113 void ThreadPlanStepInRange::GetDescription(Stream *s,
114 lldb::DescriptionLevel level) {
115 if (level == lldb::eDescriptionLevelBrief) {
116 s->Printf("step in");
120 s->Printf("Stepping in");
121 bool printed_line_info = false;
122 if (m_addr_context.line_entry.IsValid()) {
123 s->Printf(" through line ");
124 m_addr_context.line_entry.DumpStopContext(s, false);
125 printed_line_info = true;
128 const char *step_into_target = m_step_into_target.AsCString();
129 if (step_into_target && step_into_target[0] != '\0')
130 s->Printf(" targeting %s", m_step_into_target.AsCString());
132 if (!printed_line_info || level == eDescriptionLevelVerbose) {
133 s->Printf(" using ranges:");
140 bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
141 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
146 m_thread.GetRegisterContext()->GetPC(),
147 m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
148 log->Printf("ThreadPlanStepInRange reached %s.", s.GetData());
151 if (IsPlanComplete())
154 m_no_more_plans = false;
155 if (m_sub_plan_sp && m_sub_plan_sp->IsPlanComplete()) {
156 if (!m_sub_plan_sp->PlanSucceeded()) {
158 m_no_more_plans = true;
161 m_sub_plan_sp.reset();
164 if (m_virtual_step) {
165 // If we've just completed a virtual step, all we need to do is check for a
166 // ShouldStopHere plan, and otherwise we're done.
167 // FIXME - This can be both a step in and a step out. Probably should
168 // record which in the m_virtual_step.
169 m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger);
171 // Stepping through should be done running other threads in general, since
172 // we're setting a breakpoint and continuing. So only stop others if we
173 // are explicitly told to do so.
175 bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
177 FrameComparison frame_order = CompareCurrentFrameToStartFrame();
179 if (frame_order == eFrameCompareOlder ||
180 frame_order == eFrameCompareSameParent) {
181 // If we're in an older frame then we should stop.
183 // A caveat to this is if we think the frame is older but we're actually
185 // I'm going to make the assumption that you wouldn't RETURN to a
186 // trampoline. So if we are in a trampoline we think the frame is older
187 // because the trampoline confused the backtracer.
188 m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
190 if (!m_sub_plan_sp) {
191 // Otherwise check the ShouldStopHere for step out:
192 m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
195 log->Printf("ShouldStopHere found plan to step out of this frame.");
197 log->Printf("ShouldStopHere no plan to step out of this frame.");
201 "Thought I stepped out, but in fact arrived at a trampoline.");
203 } else if (frame_order == eFrameCompareEqual && InSymbol()) {
204 // If we are not in a place we should step through, we're done. One
205 // tricky bit here is that some stubs don't push a frame, so we have to
206 // check both the case of a frame that is younger, or the same as this
207 // frame. However, if the frame is the same, and we are still in the
208 // symbol we started in, the we don't need to do this. This first check
209 // isn't strictly necessary, but it is more efficient.
211 // If we're still in the range, keep going, either by running to the next
212 // branch breakpoint, or by stepping.
214 SetNextBranchBreakpoint();
219 m_no_more_plans = true;
223 // If we get to this point, we're not going to use a previously set "next
224 // branch" breakpoint, so delete it:
225 ClearNextBranchBreakpoint();
227 // We may have set the plan up above in the FrameIsOlder section:
230 m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
235 log->Printf("Found a step through plan: %s", m_sub_plan_sp->GetName());
237 log->Printf("No step through plan found.");
240 // If not, give the "should_stop" callback a chance to push a plan to get
241 // us out of here. But only do that if we actually have stepped in.
242 if (!m_sub_plan_sp && frame_order == eFrameCompareYounger)
243 m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
245 // If we've stepped in and we are going to stop here, check to see if we
246 // were asked to run past the prologue, and if so do that.
248 if (!m_sub_plan_sp && frame_order == eFrameCompareYounger &&
249 m_step_past_prologue) {
250 lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0);
252 size_t bytes_to_skip = 0;
253 lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC();
254 Address func_start_address;
256 SymbolContext sc = curr_frame->GetSymbolContext(eSymbolContextFunction |
257 eSymbolContextSymbol);
260 func_start_address = sc.function->GetAddressRange().GetBaseAddress();
262 func_start_address.GetLoadAddress(
263 m_thread.CalculateTarget().get()))
264 bytes_to_skip = sc.function->GetPrologueByteSize();
265 } else if (sc.symbol) {
266 func_start_address = sc.symbol->GetAddress();
268 func_start_address.GetLoadAddress(
269 m_thread.CalculateTarget().get()))
270 bytes_to_skip = sc.symbol->GetPrologueByteSize();
273 if (bytes_to_skip == 0 && sc.symbol) {
274 TargetSP target = m_thread.CalculateTarget();
275 const Architecture *arch = target->GetArchitecturePlugin();
277 Address curr_sec_addr;
278 target->GetSectionLoadList().ResolveLoadAddress(curr_addr,
280 bytes_to_skip = arch->GetBytesToSkip(*sc.symbol, curr_sec_addr);
284 if (bytes_to_skip != 0) {
285 func_start_address.Slide(bytes_to_skip);
286 log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP);
288 log->Printf("Pushing past prologue ");
290 m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress(
291 false, func_start_address, true);
297 if (!m_sub_plan_sp) {
298 m_no_more_plans = true;
302 m_no_more_plans = false;
303 m_sub_plan_sp->SetPrivate(true);
308 void ThreadPlanStepInRange::SetAvoidRegexp(const char *name) {
309 auto name_ref = llvm::StringRef::withNullAsEmpty(name);
310 if (!m_avoid_regexp_ap)
311 m_avoid_regexp_ap.reset(new RegularExpression(name_ref));
313 m_avoid_regexp_ap->Compile(name_ref);
316 void ThreadPlanStepInRange::SetDefaultFlagValue(uint32_t new_value) {
317 // TODO: Should we test this for sanity?
318 ThreadPlanStepInRange::s_default_flag_values = new_value;
321 bool ThreadPlanStepInRange::FrameMatchesAvoidCriteria() {
322 StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get();
324 // Check the library list first, as that's cheapest:
325 bool libraries_say_avoid = false;
327 FileSpecList libraries_to_avoid(GetThread().GetLibrariesToAvoid());
328 size_t num_libraries = libraries_to_avoid.GetSize();
329 if (num_libraries > 0) {
330 SymbolContext sc(frame->GetSymbolContext(eSymbolContextModule));
331 FileSpec frame_library(sc.module_sp->GetFileSpec());
334 for (size_t i = 0; i < num_libraries; i++) {
335 const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i));
336 if (FileSpec::Equal(file_spec, frame_library, false)) {
337 libraries_say_avoid = true;
343 if (libraries_say_avoid)
346 const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get();
347 if (avoid_regexp_to_use == nullptr)
348 avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp();
350 if (avoid_regexp_to_use != nullptr) {
351 SymbolContext sc = frame->GetSymbolContext(
352 eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol);
353 if (sc.symbol != nullptr) {
354 const char *frame_function_name =
355 sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments)
357 if (frame_function_name) {
358 size_t num_matches = 0;
359 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
363 RegularExpression::Match regex_match(num_matches);
366 avoid_regexp_to_use->Execute(frame_function_name, ®ex_match);
370 regex_match.GetMatchAtIndex(frame_function_name, 0, match);
371 log->Printf("Stepping out of function \"%s\" because it matches "
372 "the avoid regexp \"%s\" - match substring: \"%s\".",
374 avoid_regexp_to_use->GetText().str().c_str(),
385 bool ThreadPlanStepInRange::DefaultShouldStopHereCallback(
386 ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
388 bool should_stop_here = true;
389 StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
390 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
392 // First see if the ThreadPlanShouldStopHere default implementation thinks we
393 // should get out of here:
394 should_stop_here = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
395 current_plan, flags, operation, baton);
396 if (!should_stop_here)
397 return should_stop_here;
399 if (should_stop_here && current_plan->GetKind() == eKindStepInRange &&
400 operation == eFrameCompareYounger) {
401 ThreadPlanStepInRange *step_in_range_plan =
402 static_cast<ThreadPlanStepInRange *>(current_plan);
403 if (step_in_range_plan->m_step_into_target) {
404 SymbolContext sc = frame->GetSymbolContext(
405 eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol);
406 if (sc.symbol != nullptr) {
407 // First try an exact match, since that's cheap with ConstStrings.
408 // Then do a strstr compare.
409 if (step_in_range_plan->m_step_into_target == sc.GetFunctionName()) {
410 should_stop_here = true;
412 const char *target_name =
413 step_in_range_plan->m_step_into_target.AsCString();
414 const char *function_name = sc.GetFunctionName().AsCString();
416 if (function_name == nullptr)
417 should_stop_here = false;
418 else if (strstr(function_name, target_name) == nullptr)
419 should_stop_here = false;
421 if (log && !should_stop_here)
422 log->Printf("Stepping out of frame %s which did not match step into "
424 sc.GetFunctionName().AsCString(),
425 step_in_range_plan->m_step_into_target.AsCString());
429 if (should_stop_here) {
430 ThreadPlanStepInRange *step_in_range_plan =
431 static_cast<ThreadPlanStepInRange *>(current_plan);
432 // Don't log the should_step_out here, it's easier to do it in
433 // FrameMatchesAvoidCriteria.
434 should_stop_here = !step_in_range_plan->FrameMatchesAvoidCriteria();
438 return should_stop_here;
441 bool ThreadPlanStepInRange::DoPlanExplainsStop(Event *event_ptr) {
442 // We always explain a stop. Either we've just done a single step, in which
443 // case we'll do our ordinary processing, or we stopped for some reason that
444 // isn't handled by our sub-plans, in which case we want to just stop right
445 // away. In general, we don't want to mark the plan as complete for
446 // unexplained stops. For instance, if you step in to some code with no debug
447 // info, so you step out and in the course of that hit a breakpoint, then you
448 // want to stop & show the user the breakpoint, but not unship the step in
449 // plan, since you still may want to complete that plan when you continue.
450 // This is particularly true when doing "step in to target function."
453 // The only variation is that if we are doing "step by running to next
454 // branch" in which case if we hit our branch breakpoint we don't set the
457 bool return_value = false;
459 if (m_virtual_step) {
462 StopInfoSP stop_info_sp = GetPrivateStopInfo();
464 StopReason reason = stop_info_sp->GetStopReason();
466 if (reason == eStopReasonBreakpoint) {
467 if (NextRangeBreakpointExplainsStop(stop_info_sp)) {
470 } else if (IsUsuallyUnexplainedStopReason(reason)) {
471 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
473 log->PutCString("ThreadPlanStepInRange got asked if it explains the "
474 "stop for some reason other than step.");
475 return_value = false;
486 bool ThreadPlanStepInRange::DoWillResume(lldb::StateType resume_state,
488 m_virtual_step = false;
489 if (resume_state == eStateStepping && current_plan) {
490 // See if we are about to step over a virtual inlined call.
491 bool step_without_resume = m_thread.DecrementCurrentInlinedDepth();
492 if (step_without_resume) {
493 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
495 log->Printf("ThreadPlanStepInRange::DoWillResume: returning false, "
497 m_thread.GetCurrentInlinedDepth());
498 SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread));
500 // FIXME: Maybe it would be better to create a InlineStep stop reason, but
502 // the whole rest of the world would have to handle that stop reason.
503 m_virtual_step = true;
505 return !step_without_resume;
510 bool ThreadPlanStepInRange::IsVirtualStep() { return m_virtual_step; }