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) {
50*e103ae92SJonas Devlieghere   auto PrintFailureIfAny = [&]() {
51*e103ae92SJonas Devlieghere     if (m_status.Success())
52*e103ae92SJonas Devlieghere       return;
53*e103ae92SJonas Devlieghere     s->Printf(" failed (%s)", m_status.AsCString());
54*e103ae92SJonas Devlieghere   };
55*e103ae92SJonas Devlieghere 
56b9c1b51eSKate Stone   if (level == lldb::eDescriptionLevelBrief) {
572bdbfd50SJim Ingham     s->Printf("step over");
58*e103ae92SJonas Devlieghere     PrintFailureIfAny();
592bdbfd50SJim Ingham     return;
602bdbfd50SJim Ingham   }
61*e103ae92SJonas 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 
75*e103ae92SJonas Devlieghere   PrintFailureIfAny();
76*e103ae92SJonas 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.
126592fa122SSam McCall   if (m_addr_context.symbol && m_addr_context.symbol == context.symbol) {
1274b86728bSDaniel Malea     return true;
1284b86728bSDaniel Malea   }
1294b86728bSDaniel Malea   return false;
1304b86728bSDaniel Malea }
1314b86728bSDaniel Malea 
132b9c1b51eSKate Stone bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
1335160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
13430fdc8d8SChris Lattner 
135b9c1b51eSKate Stone   if (log) {
13630fdc8d8SChris Lattner     StreamString s;
137b9c1b51eSKate Stone     s.Address(
138b9c1b51eSKate Stone         m_thread.GetRegisterContext()->GetPC(),
1391ac04c30SGreg Clayton         m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
14030fdc8d8SChris Lattner     log->Printf("ThreadPlanStepOverRange reached %s.", s.GetData());
14130fdc8d8SChris Lattner   }
14230fdc8d8SChris Lattner 
14330fdc8d8SChris Lattner   // If we're out of the range but in the same frame or in our caller's frame
14405097246SAdrian Prantl   // then we should stop. When stepping out we only stop others if we are
14505097246SAdrian Prantl   // forcing running one thread.
146e65b2cf2SEugene Zelenko   bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
1474d56e9c1SJim Ingham   ThreadPlanSP new_plan_sp;
148b5c0d1ccSJim Ingham   FrameComparison frame_order = CompareCurrentFrameToStartFrame();
149b5c0d1ccSJim Ingham 
150b9c1b51eSKate Stone   if (frame_order == eFrameCompareOlder) {
1515822173bSJim Ingham     // If we're in an older frame then we should stop.
1525822173bSJim Ingham     //
153b9c1b51eSKate Stone     // A caveat to this is if we think the frame is older but we're actually in
154b9c1b51eSKate Stone     // a trampoline.
155b9c1b51eSKate Stone     // I'm going to make the assumption that you wouldn't RETURN to a
15605097246SAdrian Prantl     // trampoline.  So if we are in a trampoline we think the frame is older
15705097246SAdrian Prantl     // because the trampoline confused the backtracer. As below, we step
15805097246SAdrian Prantl     // through first, and then try to figure out how to get back out again.
1595822173bSJim Ingham 
160*e103ae92SJonas Devlieghere     new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
161*e103ae92SJonas Devlieghere                                                          stop_others, m_status);
1625822173bSJim Ingham 
1634d56e9c1SJim Ingham     if (new_plan_sp && log)
164b9c1b51eSKate Stone       log->Printf(
165b9c1b51eSKate Stone           "Thought I stepped out, but in fact arrived at a trampoline.");
166b9c1b51eSKate Stone   } else if (frame_order == eFrameCompareYounger) {
167b9c1b51eSKate Stone     // Make sure we really are in a new frame.  Do that by unwinding and seeing
16805097246SAdrian Prantl     // if the start function really is our start function...
169b9c1b51eSKate Stone     for (uint32_t i = 1;; ++i) {
170b57e4a1bSJason Molenda       StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(i);
1714b86728bSDaniel Malea       if (!older_frame_sp) {
172b9c1b51eSKate Stone         // We can't unwind the next frame we should just get out of here &
173b9c1b51eSKate Stone         // stop...
1744b86728bSDaniel Malea         break;
1754b86728bSDaniel Malea       }
1764b86728bSDaniel Malea 
177b9c1b51eSKate Stone       const SymbolContext &older_context =
178b9c1b51eSKate Stone           older_frame_sp->GetSymbolContext(eSymbolContextEverything);
179b9c1b51eSKate Stone       if (IsEquivalentContext(older_context)) {
180b9c1b51eSKate Stone         new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
181b9c1b51eSKate Stone             false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
182*e103ae92SJonas Devlieghere             m_status, true);
1834b86728bSDaniel Malea         break;
184b9c1b51eSKate Stone       } else {
185*e103ae92SJonas Devlieghere         new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
186*e103ae92SJonas Devlieghere             m_stack_id, false, stop_others, m_status);
1875beccb22SJim Ingham         // If we found a way through, then we should stop recursing.
1885beccb22SJim Ingham         if (new_plan_sp)
1895beccb22SJim Ingham           break;
190b5c0d1ccSJim Ingham       }
191b5c0d1ccSJim Ingham     }
192b9c1b51eSKate Stone   } else {
193564d8bc2SJim Ingham     // If we're still in the range, keep going.
194b9c1b51eSKate Stone     if (InRange()) {
195564d8bc2SJim Ingham       SetNextBranchBreakpoint();
196564d8bc2SJim Ingham       return false;
197564d8bc2SJim Ingham     }
198564d8bc2SJim Ingham 
199b9c1b51eSKate Stone     if (!InSymbol()) {
200b9c1b51eSKate Stone       // This one is a little tricky.  Sometimes we may be in a stub or
20105097246SAdrian Prantl       // something similar, in which case we need to get out of there.  But if
20205097246SAdrian Prantl       // we are in a stub then it's likely going to be hard to get out from
20305097246SAdrian Prantl       // here.  It is probably easiest to step into the stub, and then it will
20405097246SAdrian Prantl       // be straight-forward to step out.
205*e103ae92SJonas Devlieghere       new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
206*e103ae92SJonas Devlieghere           m_stack_id, false, stop_others, m_status);
207b9c1b51eSKate Stone     } else {
20805097246SAdrian Prantl       // The current clang (at least through 424) doesn't always get the
20905097246SAdrian Prantl       // address range for the DW_TAG_inlined_subroutines right, so that when
21005097246SAdrian Prantl       // you leave the inlined range the line table says you are still in the
21105097246SAdrian Prantl       // source file of the inlining function.  This is bad, because now you
21205097246SAdrian Prantl       // are missing the stack frame for the function containing the inlining,
21305097246SAdrian Prantl       // and if you sensibly do "finish" to get out of this function you will
21405097246SAdrian Prantl       // instead exit the containing function. To work around this, we check
21505097246SAdrian Prantl       // whether we are still in the source file we started in, and if not
21605097246SAdrian Prantl       // assume it is an error, and push a plan to get us out of this line and
21705097246SAdrian Prantl       // back to the containing file.
2183bfa753fSJim Ingham 
219b9c1b51eSKate Stone       if (m_addr_context.line_entry.IsValid()) {
2203bfa753fSJim Ingham         SymbolContext sc;
221b57e4a1bSJason Molenda         StackFrameSP frame_sp = m_thread.GetStackFrameAtIndex(0);
2223bfa753fSJim Ingham         sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
223b9c1b51eSKate Stone         if (sc.line_entry.IsValid()) {
224b9c1b51eSKate Stone           if (sc.line_entry.original_file !=
225b9c1b51eSKate Stone                   m_addr_context.line_entry.original_file &&
226b9c1b51eSKate Stone               sc.comp_unit == m_addr_context.comp_unit &&
227b9c1b51eSKate Stone               sc.function == m_addr_context.function) {
22858ef391fSBruce Mitchener             // Okay, find the next occurrence of this file in the line table:
2293bfa753fSJim Ingham             LineTable *line_table = m_addr_context.comp_unit->GetLineTable();
230b9c1b51eSKate Stone             if (line_table) {
2313bfa753fSJim Ingham               Address cur_address = frame_sp->GetFrameCodeAddress();
2323bfa753fSJim Ingham               uint32_t entry_idx;
2333bfa753fSJim Ingham               LineEntry line_entry;
234b9c1b51eSKate Stone               if (line_table->FindLineEntryByAddress(cur_address, line_entry,
235b9c1b51eSKate Stone                                                      &entry_idx)) {
2363bfa753fSJim Ingham                 LineEntry next_line_entry;
2373bfa753fSJim Ingham                 bool step_past_remaining_inline = false;
238b9c1b51eSKate Stone                 if (entry_idx > 0) {
239b9c1b51eSKate Stone                   // We require the previous line entry and the current line
24005097246SAdrian Prantl                   // entry come from the same file. The other requirement is
24105097246SAdrian Prantl                   // that the previous line table entry be part of an inlined
24205097246SAdrian Prantl                   // block, we don't want to step past cases where people have
24305097246SAdrian Prantl                   // inlined some code fragment by using #include <source-
24405097246SAdrian Prantl                   // fragment.c> directly.
2453bfa753fSJim Ingham                   LineEntry prev_line_entry;
246b9c1b51eSKate Stone                   if (line_table->GetLineEntryAtIndex(entry_idx - 1,
247b9c1b51eSKate Stone                                                       prev_line_entry) &&
248b9c1b51eSKate Stone                       prev_line_entry.original_file ==
249b9c1b51eSKate Stone                           line_entry.original_file) {
2503bfa753fSJim Ingham                     SymbolContext prev_sc;
251b9c1b51eSKate Stone                     Address prev_address =
252b9c1b51eSKate Stone                         prev_line_entry.range.GetBaseAddress();
2533bfa753fSJim Ingham                     prev_address.CalculateSymbolContext(&prev_sc);
254b9c1b51eSKate Stone                     if (prev_sc.block) {
255b9c1b51eSKate Stone                       Block *inlined_block =
256b9c1b51eSKate Stone                           prev_sc.block->GetContainingInlinedBlock();
257b9c1b51eSKate Stone                       if (inlined_block) {
2583bfa753fSJim Ingham                         AddressRange inline_range;
259b9c1b51eSKate Stone                         inlined_block->GetRangeContainingAddress(prev_address,
260b9c1b51eSKate Stone                                                                  inline_range);
261b9c1b51eSKate Stone                         if (!inline_range.ContainsFileAddress(cur_address)) {
2623bfa753fSJim Ingham 
2633bfa753fSJim Ingham                           step_past_remaining_inline = true;
2643bfa753fSJim Ingham                         }
2653bfa753fSJim Ingham                       }
2663bfa753fSJim Ingham                     }
2673bfa753fSJim Ingham                   }
2683bfa753fSJim Ingham                 }
2693bfa753fSJim Ingham 
270b9c1b51eSKate Stone                 if (step_past_remaining_inline) {
2713bfa753fSJim Ingham                   uint32_t look_ahead_step = 1;
272b9c1b51eSKate Stone                   while (line_table->GetLineEntryAtIndex(
273b9c1b51eSKate Stone                       entry_idx + look_ahead_step, next_line_entry)) {
274b9c1b51eSKate Stone                     // Make sure we haven't wandered out of the function we
275b9c1b51eSKate Stone                     // started from...
276b9c1b51eSKate Stone                     Address next_line_address =
277b9c1b51eSKate Stone                         next_line_entry.range.GetBaseAddress();
278b9c1b51eSKate Stone                     Function *next_line_function =
279b9c1b51eSKate Stone                         next_line_address.CalculateSymbolContextFunction();
2803bfa753fSJim Ingham                     if (next_line_function != m_addr_context.function)
2813bfa753fSJim Ingham                       break;
2823bfa753fSJim Ingham 
283b9c1b51eSKate Stone                     if (next_line_entry.original_file ==
284b9c1b51eSKate Stone                         m_addr_context.line_entry.original_file) {
2853bfa753fSJim Ingham                       const bool abort_other_plans = false;
28655828080SJim Ingham                       const RunMode stop_other_threads = RunMode::eAllThreads;
287b9c1b51eSKate Stone                       lldb::addr_t cur_pc = m_thread.GetStackFrameAtIndex(0)
288b9c1b51eSKate Stone                                                 ->GetRegisterContext()
289b9c1b51eSKate Stone                                                 ->GetPC();
290b9c1b51eSKate Stone                       AddressRange step_range(
291b9c1b51eSKate Stone                           cur_pc,
292b9c1b51eSKate Stone                           next_line_address.GetLoadAddress(&GetTarget()) -
293b9c1b51eSKate Stone                               cur_pc);
29455828080SJim Ingham 
295b9c1b51eSKate Stone                       new_plan_sp = m_thread.QueueThreadPlanForStepOverRange(
296*e103ae92SJonas Devlieghere                           abort_other_plans, step_range, sc, stop_other_threads,
297*e103ae92SJonas Devlieghere                           m_status);
2983bfa753fSJim Ingham                       break;
2993bfa753fSJim Ingham                     }
3003bfa753fSJim Ingham                     look_ahead_step++;
3013bfa753fSJim Ingham                   }
3023bfa753fSJim Ingham                 }
3033bfa753fSJim Ingham               }
3043bfa753fSJim Ingham             }
3053bfa753fSJim Ingham           }
3063bfa753fSJim Ingham         }
3073bfa753fSJim Ingham       }
3083bfa753fSJim Ingham     }
309564d8bc2SJim Ingham   }
310564d8bc2SJim Ingham 
311b9c1b51eSKate Stone   // If we get to this point, we're not going to use a previously set "next
312b9c1b51eSKate Stone   // branch" breakpoint, so delete it:
313564d8bc2SJim Ingham   ClearNextBranchBreakpoint();
31430fdc8d8SChris Lattner 
315b9c1b51eSKate Stone   // If we haven't figured out something to do yet, then ask the ShouldStopHere
316b9c1b51eSKate Stone   // callback:
317b9c1b51eSKate Stone   if (!new_plan_sp) {
318*e103ae92SJonas Devlieghere     new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
3194b4b2478SJim Ingham   }
3204b4b2478SJim Ingham 
3214d56e9c1SJim Ingham   if (!new_plan_sp)
32230fdc8d8SChris Lattner     m_no_more_plans = true;
323b9c1b51eSKate Stone   else {
3242bdbfd50SJim Ingham     // Any new plan will be an implementation plan, so mark it private:
3252bdbfd50SJim Ingham     new_plan_sp->SetPrivate(true);
32630fdc8d8SChris Lattner     m_no_more_plans = false;
3272bdbfd50SJim Ingham   }
32830fdc8d8SChris Lattner 
329b9c1b51eSKate Stone   if (!new_plan_sp) {
330b9c1b51eSKate Stone     // For efficiencies sake, we know we're done here so we don't have to do
33105097246SAdrian Prantl     // this calculation again in MischiefManaged.
332*e103ae92SJonas Devlieghere     SetPlanComplete(m_status.Success());
33330fdc8d8SChris Lattner     return true;
334b9c1b51eSKate Stone   } else
33530fdc8d8SChris Lattner     return false;
33630fdc8d8SChris Lattner }
337fbbfe6ecSJim Ingham 
338b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoPlanExplainsStop(Event *event_ptr) {
33905097246SAdrian Prantl   // For crashes, breakpoint hits, signals, etc, let the base plan (or some
34005097246SAdrian Prantl   // plan above us) handle the stop.  That way the user can see the stop, step
34105097246SAdrian Prantl   // around, and then when they are done, continue and have their step
34205097246SAdrian Prantl   // complete.  The exception is if we've hit our "run to next branch"
34305097246SAdrian Prantl   // breakpoint. Note, unlike the step in range plan, we don't mark ourselves
34405097246SAdrian Prantl   // complete if we hit an unexplained breakpoint/crash.
345fbbfe6ecSJim Ingham 
3465160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
34760c4118cSJim Ingham   StopInfoSP stop_info_sp = GetPrivateStopInfo();
348221d51cfSJim Ingham   bool return_value;
349221d51cfSJim Ingham 
350b9c1b51eSKate Stone   if (stop_info_sp) {
351fbbfe6ecSJim Ingham     StopReason reason = stop_info_sp->GetStopReason();
352fbbfe6ecSJim Ingham 
353b9c1b51eSKate Stone     if (reason == eStopReasonTrace) {
354221d51cfSJim Ingham       return_value = true;
355b9c1b51eSKate Stone     } else if (reason == eStopReasonBreakpoint) {
356e65b2cf2SEugene Zelenko       return_value = NextRangeBreakpointExplainsStop(stop_info_sp);
357b9c1b51eSKate Stone     } else {
358fbbfe6ecSJim Ingham       if (log)
359b9c1b51eSKate Stone         log->PutCString("ThreadPlanStepInRange got asked if it explains the "
360b9c1b51eSKate Stone                         "stop for some reason other than step.");
361221d51cfSJim Ingham       return_value = false;
362fbbfe6ecSJim Ingham     }
363b9c1b51eSKate Stone   } else
364221d51cfSJim Ingham     return_value = true;
365221d51cfSJim Ingham 
366221d51cfSJim Ingham   return return_value;
367fbbfe6ecSJim Ingham }
368513c6bb8SJim Ingham 
369b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoWillResume(lldb::StateType resume_state,
370b9c1b51eSKate Stone                                            bool current_plan) {
371b9c1b51eSKate Stone   if (resume_state != eStateSuspended && m_first_resume) {
372513c6bb8SJim Ingham     m_first_resume = false;
373b9c1b51eSKate Stone     if (resume_state == eStateStepping && current_plan) {
374b9c1b51eSKate Stone       // See if we are about to step over an inlined call in the middle of the
37505097246SAdrian Prantl       // inlined stack, if so figure out its extents and reset our range to
37605097246SAdrian Prantl       // step over that.
377513c6bb8SJim Ingham       bool in_inlined_stack = m_thread.DecrementCurrentInlinedDepth();
378b9c1b51eSKate Stone       if (in_inlined_stack) {
3795160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
380513c6bb8SJim Ingham         if (log)
381b9c1b51eSKate Stone           log->Printf("ThreadPlanStepInRange::DoWillResume: adjusting range to "
382b9c1b51eSKate Stone                       "the frame at inlined depth %d.",
383513c6bb8SJim Ingham                       m_thread.GetCurrentInlinedDepth());
384b57e4a1bSJason Molenda         StackFrameSP stack_sp = m_thread.GetStackFrameAtIndex(0);
385b9c1b51eSKate Stone         if (stack_sp) {
386513c6bb8SJim Ingham           Block *frame_block = stack_sp->GetFrameBlock();
387513c6bb8SJim Ingham           lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
388513c6bb8SJim Ingham           AddressRange my_range;
389b9c1b51eSKate Stone           if (frame_block->GetRangeContainingLoadAddress(
390b9c1b51eSKate Stone                   curr_pc, m_thread.GetProcess()->GetTarget(), my_range)) {
391513c6bb8SJim Ingham             m_address_ranges.clear();
392513c6bb8SJim Ingham             m_address_ranges.push_back(my_range);
393b9c1b51eSKate Stone             if (log) {
394513c6bb8SJim Ingham               StreamString s;
395b9c1b51eSKate Stone               const InlineFunctionInfo *inline_info =
396b9c1b51eSKate Stone                   frame_block->GetInlinedFunctionInfo();
397513c6bb8SJim Ingham               const char *name;
398513c6bb8SJim Ingham               if (inline_info)
399b9c1b51eSKate Stone                 name =
400b9c1b51eSKate Stone                     inline_info
401b9c1b51eSKate Stone                         ->GetName(frame_block->CalculateSymbolContextFunction()
402b9c1b51eSKate Stone                                       ->GetLanguage())
403b9c1b51eSKate Stone                         .AsCString();
404513c6bb8SJim Ingham               else
405513c6bb8SJim Ingham                 name = "<unknown-notinlined>";
406513c6bb8SJim Ingham 
407b9c1b51eSKate Stone               s.Printf(
408b9c1b51eSKate Stone                   "Stepping over inlined function \"%s\" in inlined stack: ",
409b9c1b51eSKate Stone                   name);
410513c6bb8SJim Ingham               DumpRanges(&s);
411c156427dSZachary Turner               log->PutString(s.GetString());
412513c6bb8SJim Ingham             }
413513c6bb8SJim Ingham           }
414513c6bb8SJim Ingham         }
415513c6bb8SJim Ingham       }
416513c6bb8SJim Ingham     }
417513c6bb8SJim Ingham   }
418513c6bb8SJim Ingham 
419221d51cfSJim Ingham   return true;
420513c6bb8SJim Ingham }
421