130fdc8d8SChris Lattner //===-- ThreadPlanStepOverRange.cpp -----------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
10e65b2cf2SEugene Zelenko #include "lldb/Target/ThreadPlanStepOverRange.h"
11513c6bb8SJim Ingham #include "lldb/Symbol/Block.h"
123bfa753fSJim Ingham #include "lldb/Symbol/CompileUnit.h"
13513c6bb8SJim Ingham #include "lldb/Symbol/Function.h"
143bfa753fSJim Ingham #include "lldb/Symbol/LineTable.h"
1530fdc8d8SChris Lattner #include "lldb/Target/Process.h"
1630fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
17514487e8SGreg Clayton #include "lldb/Target/Target.h"
1830fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
1930fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepOut.h"
2030fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepThrough.h"
216f9e6901SZachary Turner #include "lldb/Utility/Log.h"
22bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
2330fdc8d8SChris Lattner 
2430fdc8d8SChris Lattner using namespace lldb_private;
252d4edfbcSGreg Clayton using namespace lldb;
2630fdc8d8SChris Lattner 
274b4b2478SJim Ingham uint32_t ThreadPlanStepOverRange::s_default_flag_values = 0;
2830fdc8d8SChris Lattner 
2930fdc8d8SChris Lattner //----------------------------------------------------------------------
30b9c1b51eSKate Stone // ThreadPlanStepOverRange: Step through a stack range, either stepping over or
3105097246SAdrian Prantl // into based on the value of \a type.
3230fdc8d8SChris Lattner //----------------------------------------------------------------------
3330fdc8d8SChris Lattner 
34b9c1b51eSKate Stone ThreadPlanStepOverRange::ThreadPlanStepOverRange(
35b9c1b51eSKate Stone     Thread &thread, const AddressRange &range,
36b9c1b51eSKate Stone     const SymbolContext &addr_context, lldb::RunMode stop_others,
37b9c1b51eSKate Stone     LazyBool step_out_avoids_code_without_debug_info)
38b9c1b51eSKate Stone     : ThreadPlanStepRange(ThreadPlan::eKindStepOverRange,
39b9c1b51eSKate Stone                           "Step range stepping over", thread, range,
40b9c1b51eSKate Stone                           addr_context, stop_others),
41b9c1b51eSKate Stone       ThreadPlanShouldStopHere(this), m_first_resume(true) {
424b4b2478SJim Ingham   SetFlagsToDefault();
434b4b2478SJim Ingham   SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
4430fdc8d8SChris Lattner }
4530fdc8d8SChris Lattner 
46e65b2cf2SEugene Zelenko ThreadPlanStepOverRange::~ThreadPlanStepOverRange() = default;
4730fdc8d8SChris Lattner 
48b9c1b51eSKate Stone void ThreadPlanStepOverRange::GetDescription(Stream *s,
49b9c1b51eSKate Stone                                              lldb::DescriptionLevel level) {
50e103ae92SJonas Devlieghere   auto PrintFailureIfAny = [&]() {
51e103ae92SJonas Devlieghere     if (m_status.Success())
52e103ae92SJonas Devlieghere       return;
53e103ae92SJonas Devlieghere     s->Printf(" failed (%s)", m_status.AsCString());
54e103ae92SJonas Devlieghere   };
55e103ae92SJonas Devlieghere 
56b9c1b51eSKate Stone   if (level == lldb::eDescriptionLevelBrief) {
572bdbfd50SJim Ingham     s->Printf("step over");
58e103ae92SJonas Devlieghere     PrintFailureIfAny();
592bdbfd50SJim Ingham     return;
602bdbfd50SJim Ingham   }
61e103ae92SJonas Devlieghere 
622bdbfd50SJim Ingham   s->Printf("Stepping over");
632bdbfd50SJim Ingham   bool printed_line_info = false;
64b9c1b51eSKate Stone   if (m_addr_context.line_entry.IsValid()) {
652bdbfd50SJim Ingham     s->Printf(" line ");
662bdbfd50SJim Ingham     m_addr_context.line_entry.DumpStopContext(s, false);
672bdbfd50SJim Ingham     printed_line_info = true;
682bdbfd50SJim Ingham   }
692bdbfd50SJim Ingham 
70b9c1b51eSKate Stone   if (!printed_line_info || level == eDescriptionLevelVerbose) {
712bdbfd50SJim Ingham     s->Printf(" using ranges: ");
72c4c9fedcSJim Ingham     DumpRanges(s);
7330fdc8d8SChris Lattner   }
742bdbfd50SJim Ingham 
75e103ae92SJonas Devlieghere   PrintFailureIfAny();
76e103ae92SJonas Devlieghere 
772bdbfd50SJim Ingham   s->PutChar('.');
7830fdc8d8SChris Lattner }
7930fdc8d8SChris Lattner 
80b9c1b51eSKate Stone void ThreadPlanStepOverRange::SetupAvoidNoDebug(
81b9c1b51eSKate Stone     LazyBool step_out_avoids_code_without_debug_info) {
824b4b2478SJim Ingham   bool avoid_nodebug = true;
83b9c1b51eSKate Stone   switch (step_out_avoids_code_without_debug_info) {
844b4b2478SJim Ingham   case eLazyBoolYes:
854b4b2478SJim Ingham     avoid_nodebug = true;
864b4b2478SJim Ingham     break;
874b4b2478SJim Ingham   case eLazyBoolNo:
884b4b2478SJim Ingham     avoid_nodebug = false;
894b4b2478SJim Ingham     break;
904b4b2478SJim Ingham   case eLazyBoolCalculate:
914b4b2478SJim Ingham     avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
924b4b2478SJim Ingham     break;
934b4b2478SJim Ingham   }
944b4b2478SJim Ingham   if (avoid_nodebug)
954b4b2478SJim Ingham     GetFlags().Set(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
964b4b2478SJim Ingham   else
974b4b2478SJim Ingham     GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
98b9c1b51eSKate Stone   // Step Over plans should always avoid no-debug on step in.  Seems like you
9905097246SAdrian Prantl   // shouldn't have to say this, but a tail call looks more like a step in that
10005097246SAdrian Prantl   // a step out, so we want to catch this case.
101862d1bbdSJim Ingham   GetFlags().Set(ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
1024b4b2478SJim Ingham }
1034b4b2478SJim Ingham 
104b9c1b51eSKate Stone bool ThreadPlanStepOverRange::IsEquivalentContext(
105b9c1b51eSKate Stone     const SymbolContext &context) {
10605097246SAdrian Prantl   // Match as much as is specified in the m_addr_context: This is a fairly
10705097246SAdrian Prantl   // loose sanity check.  Note, sometimes the target doesn't get filled in so I
10805097246SAdrian Prantl   // left out the target check.  And sometimes the module comes in as the .o
10905097246SAdrian Prantl   // file from the inlined range, so I left that out too...
110b9c1b51eSKate Stone   if (m_addr_context.comp_unit) {
111592fa122SSam McCall     if (m_addr_context.comp_unit != context.comp_unit)
112592fa122SSam McCall       return false;
113592fa122SSam McCall     if (m_addr_context.function) {
114592fa122SSam McCall       if (m_addr_context.function != context.function)
115592fa122SSam McCall         return false;
116b9c1b51eSKate Stone       // It is okay to return to a different block of a straight function, we
11705097246SAdrian Prantl       // only have to be more careful if returning from one inlined block to
11805097246SAdrian Prantl       // another.
119b9c1b51eSKate Stone       if (m_addr_context.block->GetInlinedFunctionInfo() == nullptr &&
120b9c1b51eSKate Stone           context.block->GetInlinedFunctionInfo() == nullptr)
1217766c4a8SJim Ingham         return true;
122592fa122SSam McCall       return m_addr_context.block == context.block;
1234b86728bSDaniel Malea     }
1244b86728bSDaniel Malea   }
125592fa122SSam McCall   // Fall back to symbol if we have no decision from comp_unit/function/block.
126*a6682a41SJonas Devlieghere   return m_addr_context.symbol && m_addr_context.symbol == context.symbol;
1274b86728bSDaniel Malea }
1284b86728bSDaniel Malea 
129b9c1b51eSKate Stone bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
1305160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
13130fdc8d8SChris Lattner 
132b9c1b51eSKate Stone   if (log) {
13330fdc8d8SChris Lattner     StreamString s;
134b9c1b51eSKate Stone     s.Address(
135b9c1b51eSKate Stone         m_thread.GetRegisterContext()->GetPC(),
1361ac04c30SGreg Clayton         m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
13730fdc8d8SChris Lattner     log->Printf("ThreadPlanStepOverRange reached %s.", s.GetData());
13830fdc8d8SChris Lattner   }
13930fdc8d8SChris Lattner 
14030fdc8d8SChris Lattner   // If we're out of the range but in the same frame or in our caller's frame
14105097246SAdrian Prantl   // then we should stop. When stepping out we only stop others if we are
14205097246SAdrian Prantl   // forcing running one thread.
143e65b2cf2SEugene Zelenko   bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
1444d56e9c1SJim Ingham   ThreadPlanSP new_plan_sp;
145b5c0d1ccSJim Ingham   FrameComparison frame_order = CompareCurrentFrameToStartFrame();
146b5c0d1ccSJim Ingham 
147b9c1b51eSKate Stone   if (frame_order == eFrameCompareOlder) {
1485822173bSJim Ingham     // If we're in an older frame then we should stop.
1495822173bSJim Ingham     //
150b9c1b51eSKate Stone     // A caveat to this is if we think the frame is older but we're actually in
151b9c1b51eSKate Stone     // a trampoline.
152b9c1b51eSKate Stone     // I'm going to make the assumption that you wouldn't RETURN to a
15305097246SAdrian Prantl     // trampoline.  So if we are in a trampoline we think the frame is older
15405097246SAdrian Prantl     // because the trampoline confused the backtracer. As below, we step
15505097246SAdrian Prantl     // through first, and then try to figure out how to get back out again.
1565822173bSJim Ingham 
157e103ae92SJonas Devlieghere     new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
158e103ae92SJonas Devlieghere                                                          stop_others, m_status);
1595822173bSJim Ingham 
1604d56e9c1SJim Ingham     if (new_plan_sp && log)
161b9c1b51eSKate Stone       log->Printf(
162b9c1b51eSKate Stone           "Thought I stepped out, but in fact arrived at a trampoline.");
163b9c1b51eSKate Stone   } else if (frame_order == eFrameCompareYounger) {
164b9c1b51eSKate Stone     // Make sure we really are in a new frame.  Do that by unwinding and seeing
16505097246SAdrian Prantl     // if the start function really is our start function...
166b9c1b51eSKate Stone     for (uint32_t i = 1;; ++i) {
167b57e4a1bSJason Molenda       StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(i);
1684b86728bSDaniel Malea       if (!older_frame_sp) {
169b9c1b51eSKate Stone         // We can't unwind the next frame we should just get out of here &
170b9c1b51eSKate Stone         // stop...
1714b86728bSDaniel Malea         break;
1724b86728bSDaniel Malea       }
1734b86728bSDaniel Malea 
174b9c1b51eSKate Stone       const SymbolContext &older_context =
175b9c1b51eSKate Stone           older_frame_sp->GetSymbolContext(eSymbolContextEverything);
176b9c1b51eSKate Stone       if (IsEquivalentContext(older_context)) {
177b9c1b51eSKate Stone         new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
178b9c1b51eSKate Stone             false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
179e103ae92SJonas Devlieghere             m_status, true);
1804b86728bSDaniel Malea         break;
181b9c1b51eSKate Stone       } else {
182e103ae92SJonas Devlieghere         new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
183e103ae92SJonas Devlieghere             m_stack_id, false, stop_others, m_status);
1845beccb22SJim Ingham         // If we found a way through, then we should stop recursing.
1855beccb22SJim Ingham         if (new_plan_sp)
1865beccb22SJim Ingham           break;
187b5c0d1ccSJim Ingham       }
188b5c0d1ccSJim Ingham     }
189b9c1b51eSKate Stone   } else {
190564d8bc2SJim Ingham     // If we're still in the range, keep going.
191b9c1b51eSKate Stone     if (InRange()) {
192564d8bc2SJim Ingham       SetNextBranchBreakpoint();
193564d8bc2SJim Ingham       return false;
194564d8bc2SJim Ingham     }
195564d8bc2SJim Ingham 
196b9c1b51eSKate Stone     if (!InSymbol()) {
197b9c1b51eSKate Stone       // This one is a little tricky.  Sometimes we may be in a stub or
19805097246SAdrian Prantl       // something similar, in which case we need to get out of there.  But if
19905097246SAdrian Prantl       // we are in a stub then it's likely going to be hard to get out from
20005097246SAdrian Prantl       // here.  It is probably easiest to step into the stub, and then it will
20105097246SAdrian Prantl       // be straight-forward to step out.
202e103ae92SJonas Devlieghere       new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
203e103ae92SJonas Devlieghere           m_stack_id, false, stop_others, m_status);
204b9c1b51eSKate Stone     } else {
20505097246SAdrian Prantl       // The current clang (at least through 424) doesn't always get the
20605097246SAdrian Prantl       // address range for the DW_TAG_inlined_subroutines right, so that when
20705097246SAdrian Prantl       // you leave the inlined range the line table says you are still in the
20805097246SAdrian Prantl       // source file of the inlining function.  This is bad, because now you
20905097246SAdrian Prantl       // are missing the stack frame for the function containing the inlining,
21005097246SAdrian Prantl       // and if you sensibly do "finish" to get out of this function you will
21105097246SAdrian Prantl       // instead exit the containing function. To work around this, we check
21205097246SAdrian Prantl       // whether we are still in the source file we started in, and if not
21305097246SAdrian Prantl       // assume it is an error, and push a plan to get us out of this line and
21405097246SAdrian Prantl       // back to the containing file.
2153bfa753fSJim Ingham 
216b9c1b51eSKate Stone       if (m_addr_context.line_entry.IsValid()) {
2173bfa753fSJim Ingham         SymbolContext sc;
218b57e4a1bSJason Molenda         StackFrameSP frame_sp = m_thread.GetStackFrameAtIndex(0);
2193bfa753fSJim Ingham         sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
220b9c1b51eSKate Stone         if (sc.line_entry.IsValid()) {
221b9c1b51eSKate Stone           if (sc.line_entry.original_file !=
222b9c1b51eSKate Stone                   m_addr_context.line_entry.original_file &&
223b9c1b51eSKate Stone               sc.comp_unit == m_addr_context.comp_unit &&
224b9c1b51eSKate Stone               sc.function == m_addr_context.function) {
22558ef391fSBruce Mitchener             // Okay, find the next occurrence of this file in the line table:
2263bfa753fSJim Ingham             LineTable *line_table = m_addr_context.comp_unit->GetLineTable();
227b9c1b51eSKate Stone             if (line_table) {
2283bfa753fSJim Ingham               Address cur_address = frame_sp->GetFrameCodeAddress();
2293bfa753fSJim Ingham               uint32_t entry_idx;
2303bfa753fSJim Ingham               LineEntry line_entry;
231b9c1b51eSKate Stone               if (line_table->FindLineEntryByAddress(cur_address, line_entry,
232b9c1b51eSKate Stone                                                      &entry_idx)) {
2333bfa753fSJim Ingham                 LineEntry next_line_entry;
2343bfa753fSJim Ingham                 bool step_past_remaining_inline = false;
235b9c1b51eSKate Stone                 if (entry_idx > 0) {
236b9c1b51eSKate Stone                   // We require the previous line entry and the current line
23705097246SAdrian Prantl                   // entry come from the same file. The other requirement is
23805097246SAdrian Prantl                   // that the previous line table entry be part of an inlined
23905097246SAdrian Prantl                   // block, we don't want to step past cases where people have
24005097246SAdrian Prantl                   // inlined some code fragment by using #include <source-
24105097246SAdrian Prantl                   // fragment.c> directly.
2423bfa753fSJim Ingham                   LineEntry prev_line_entry;
243b9c1b51eSKate Stone                   if (line_table->GetLineEntryAtIndex(entry_idx - 1,
244b9c1b51eSKate Stone                                                       prev_line_entry) &&
245b9c1b51eSKate Stone                       prev_line_entry.original_file ==
246b9c1b51eSKate Stone                           line_entry.original_file) {
2473bfa753fSJim Ingham                     SymbolContext prev_sc;
248b9c1b51eSKate Stone                     Address prev_address =
249b9c1b51eSKate Stone                         prev_line_entry.range.GetBaseAddress();
2503bfa753fSJim Ingham                     prev_address.CalculateSymbolContext(&prev_sc);
251b9c1b51eSKate Stone                     if (prev_sc.block) {
252b9c1b51eSKate Stone                       Block *inlined_block =
253b9c1b51eSKate Stone                           prev_sc.block->GetContainingInlinedBlock();
254b9c1b51eSKate Stone                       if (inlined_block) {
2553bfa753fSJim Ingham                         AddressRange inline_range;
256b9c1b51eSKate Stone                         inlined_block->GetRangeContainingAddress(prev_address,
257b9c1b51eSKate Stone                                                                  inline_range);
258b9c1b51eSKate Stone                         if (!inline_range.ContainsFileAddress(cur_address)) {
2593bfa753fSJim Ingham 
2603bfa753fSJim Ingham                           step_past_remaining_inline = true;
2613bfa753fSJim Ingham                         }
2623bfa753fSJim Ingham                       }
2633bfa753fSJim Ingham                     }
2643bfa753fSJim Ingham                   }
2653bfa753fSJim Ingham                 }
2663bfa753fSJim Ingham 
267b9c1b51eSKate Stone                 if (step_past_remaining_inline) {
2683bfa753fSJim Ingham                   uint32_t look_ahead_step = 1;
269b9c1b51eSKate Stone                   while (line_table->GetLineEntryAtIndex(
270b9c1b51eSKate Stone                       entry_idx + look_ahead_step, next_line_entry)) {
271b9c1b51eSKate Stone                     // Make sure we haven't wandered out of the function we
272b9c1b51eSKate Stone                     // started from...
273b9c1b51eSKate Stone                     Address next_line_address =
274b9c1b51eSKate Stone                         next_line_entry.range.GetBaseAddress();
275b9c1b51eSKate Stone                     Function *next_line_function =
276b9c1b51eSKate Stone                         next_line_address.CalculateSymbolContextFunction();
2773bfa753fSJim Ingham                     if (next_line_function != m_addr_context.function)
2783bfa753fSJim Ingham                       break;
2793bfa753fSJim Ingham 
280b9c1b51eSKate Stone                     if (next_line_entry.original_file ==
281b9c1b51eSKate Stone                         m_addr_context.line_entry.original_file) {
2823bfa753fSJim Ingham                       const bool abort_other_plans = false;
28355828080SJim Ingham                       const RunMode stop_other_threads = RunMode::eAllThreads;
284b9c1b51eSKate Stone                       lldb::addr_t cur_pc = m_thread.GetStackFrameAtIndex(0)
285b9c1b51eSKate Stone                                                 ->GetRegisterContext()
286b9c1b51eSKate Stone                                                 ->GetPC();
287b9c1b51eSKate Stone                       AddressRange step_range(
288b9c1b51eSKate Stone                           cur_pc,
289b9c1b51eSKate Stone                           next_line_address.GetLoadAddress(&GetTarget()) -
290b9c1b51eSKate Stone                               cur_pc);
29155828080SJim Ingham 
292b9c1b51eSKate Stone                       new_plan_sp = m_thread.QueueThreadPlanForStepOverRange(
293e103ae92SJonas Devlieghere                           abort_other_plans, step_range, sc, stop_other_threads,
294e103ae92SJonas Devlieghere                           m_status);
2953bfa753fSJim Ingham                       break;
2963bfa753fSJim Ingham                     }
2973bfa753fSJim Ingham                     look_ahead_step++;
2983bfa753fSJim Ingham                   }
2993bfa753fSJim Ingham                 }
3003bfa753fSJim Ingham               }
3013bfa753fSJim Ingham             }
3023bfa753fSJim Ingham           }
3033bfa753fSJim Ingham         }
3043bfa753fSJim Ingham       }
3053bfa753fSJim Ingham     }
306564d8bc2SJim Ingham   }
307564d8bc2SJim Ingham 
308b9c1b51eSKate Stone   // If we get to this point, we're not going to use a previously set "next
309b9c1b51eSKate Stone   // branch" breakpoint, so delete it:
310564d8bc2SJim Ingham   ClearNextBranchBreakpoint();
31130fdc8d8SChris Lattner 
312b9c1b51eSKate Stone   // If we haven't figured out something to do yet, then ask the ShouldStopHere
313b9c1b51eSKate Stone   // callback:
314b9c1b51eSKate Stone   if (!new_plan_sp) {
315e103ae92SJonas Devlieghere     new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
3164b4b2478SJim Ingham   }
3174b4b2478SJim Ingham 
3184d56e9c1SJim Ingham   if (!new_plan_sp)
31930fdc8d8SChris Lattner     m_no_more_plans = true;
320b9c1b51eSKate Stone   else {
3212bdbfd50SJim Ingham     // Any new plan will be an implementation plan, so mark it private:
3222bdbfd50SJim Ingham     new_plan_sp->SetPrivate(true);
32330fdc8d8SChris Lattner     m_no_more_plans = false;
3242bdbfd50SJim Ingham   }
32530fdc8d8SChris Lattner 
326b9c1b51eSKate Stone   if (!new_plan_sp) {
327b9c1b51eSKate Stone     // For efficiencies sake, we know we're done here so we don't have to do
32805097246SAdrian Prantl     // this calculation again in MischiefManaged.
329e103ae92SJonas Devlieghere     SetPlanComplete(m_status.Success());
33030fdc8d8SChris Lattner     return true;
331b9c1b51eSKate Stone   } else
33230fdc8d8SChris Lattner     return false;
33330fdc8d8SChris Lattner }
334fbbfe6ecSJim Ingham 
335b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoPlanExplainsStop(Event *event_ptr) {
33605097246SAdrian Prantl   // For crashes, breakpoint hits, signals, etc, let the base plan (or some
33705097246SAdrian Prantl   // plan above us) handle the stop.  That way the user can see the stop, step
33805097246SAdrian Prantl   // around, and then when they are done, continue and have their step
33905097246SAdrian Prantl   // complete.  The exception is if we've hit our "run to next branch"
34005097246SAdrian Prantl   // breakpoint. Note, unlike the step in range plan, we don't mark ourselves
34105097246SAdrian Prantl   // complete if we hit an unexplained breakpoint/crash.
342fbbfe6ecSJim Ingham 
3435160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
34460c4118cSJim Ingham   StopInfoSP stop_info_sp = GetPrivateStopInfo();
345221d51cfSJim Ingham   bool return_value;
346221d51cfSJim Ingham 
347b9c1b51eSKate Stone   if (stop_info_sp) {
348fbbfe6ecSJim Ingham     StopReason reason = stop_info_sp->GetStopReason();
349fbbfe6ecSJim Ingham 
350b9c1b51eSKate Stone     if (reason == eStopReasonTrace) {
351221d51cfSJim Ingham       return_value = true;
352b9c1b51eSKate Stone     } else if (reason == eStopReasonBreakpoint) {
353e65b2cf2SEugene Zelenko       return_value = NextRangeBreakpointExplainsStop(stop_info_sp);
354b9c1b51eSKate Stone     } else {
355fbbfe6ecSJim Ingham       if (log)
356b9c1b51eSKate Stone         log->PutCString("ThreadPlanStepInRange got asked if it explains the "
357b9c1b51eSKate Stone                         "stop for some reason other than step.");
358221d51cfSJim Ingham       return_value = false;
359fbbfe6ecSJim Ingham     }
360b9c1b51eSKate Stone   } else
361221d51cfSJim Ingham     return_value = true;
362221d51cfSJim Ingham 
363221d51cfSJim Ingham   return return_value;
364fbbfe6ecSJim Ingham }
365513c6bb8SJim Ingham 
366b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoWillResume(lldb::StateType resume_state,
367b9c1b51eSKate Stone                                            bool current_plan) {
368b9c1b51eSKate Stone   if (resume_state != eStateSuspended && m_first_resume) {
369513c6bb8SJim Ingham     m_first_resume = false;
370b9c1b51eSKate Stone     if (resume_state == eStateStepping && current_plan) {
371b9c1b51eSKate Stone       // See if we are about to step over an inlined call in the middle of the
37205097246SAdrian Prantl       // inlined stack, if so figure out its extents and reset our range to
37305097246SAdrian Prantl       // step over that.
374513c6bb8SJim Ingham       bool in_inlined_stack = m_thread.DecrementCurrentInlinedDepth();
375b9c1b51eSKate Stone       if (in_inlined_stack) {
3765160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
377513c6bb8SJim Ingham         if (log)
378b9c1b51eSKate Stone           log->Printf("ThreadPlanStepInRange::DoWillResume: adjusting range to "
379b9c1b51eSKate Stone                       "the frame at inlined depth %d.",
380513c6bb8SJim Ingham                       m_thread.GetCurrentInlinedDepth());
381b57e4a1bSJason Molenda         StackFrameSP stack_sp = m_thread.GetStackFrameAtIndex(0);
382b9c1b51eSKate Stone         if (stack_sp) {
383513c6bb8SJim Ingham           Block *frame_block = stack_sp->GetFrameBlock();
384513c6bb8SJim Ingham           lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
385513c6bb8SJim Ingham           AddressRange my_range;
386b9c1b51eSKate Stone           if (frame_block->GetRangeContainingLoadAddress(
387b9c1b51eSKate Stone                   curr_pc, m_thread.GetProcess()->GetTarget(), my_range)) {
388513c6bb8SJim Ingham             m_address_ranges.clear();
389513c6bb8SJim Ingham             m_address_ranges.push_back(my_range);
390b9c1b51eSKate Stone             if (log) {
391513c6bb8SJim Ingham               StreamString s;
392b9c1b51eSKate Stone               const InlineFunctionInfo *inline_info =
393b9c1b51eSKate Stone                   frame_block->GetInlinedFunctionInfo();
394513c6bb8SJim Ingham               const char *name;
395513c6bb8SJim Ingham               if (inline_info)
396b9c1b51eSKate Stone                 name =
397b9c1b51eSKate Stone                     inline_info
398b9c1b51eSKate Stone                         ->GetName(frame_block->CalculateSymbolContextFunction()
399b9c1b51eSKate Stone                                       ->GetLanguage())
400b9c1b51eSKate Stone                         .AsCString();
401513c6bb8SJim Ingham               else
402513c6bb8SJim Ingham                 name = "<unknown-notinlined>";
403513c6bb8SJim Ingham 
404b9c1b51eSKate Stone               s.Printf(
405b9c1b51eSKate Stone                   "Stepping over inlined function \"%s\" in inlined stack: ",
406b9c1b51eSKate Stone                   name);
407513c6bb8SJim Ingham               DumpRanges(&s);
408c156427dSZachary Turner               log->PutString(s.GetString());
409513c6bb8SJim Ingham             }
410513c6bb8SJim Ingham           }
411513c6bb8SJim Ingham         }
412513c6bb8SJim Ingham       }
413513c6bb8SJim Ingham     }
414513c6bb8SJim Ingham   }
415513c6bb8SJim Ingham 
416221d51cfSJim Ingham   return true;
417513c6bb8SJim Ingham }
418