130fdc8d8SChris Lattner //===-- ThreadPlanStepOverRange.cpp -----------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
9e65b2cf2SEugene Zelenko #include "lldb/Target/ThreadPlanStepOverRange.h"
10513c6bb8SJim Ingham #include "lldb/Symbol/Block.h"
113bfa753fSJim Ingham #include "lldb/Symbol/CompileUnit.h"
12513c6bb8SJim Ingham #include "lldb/Symbol/Function.h"
133bfa753fSJim Ingham #include "lldb/Symbol/LineTable.h"
1430fdc8d8SChris Lattner #include "lldb/Target/Process.h"
1530fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
16514487e8SGreg Clayton #include "lldb/Target/Target.h"
1730fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
1830fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepOut.h"
1930fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepThrough.h"
206f9e6901SZachary Turner #include "lldb/Utility/Log.h"
21bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
2230fdc8d8SChris Lattner 
2330fdc8d8SChris Lattner using namespace lldb_private;
242d4edfbcSGreg Clayton using namespace lldb;
2530fdc8d8SChris Lattner 
264b4b2478SJim Ingham uint32_t ThreadPlanStepOverRange::s_default_flag_values = 0;
2730fdc8d8SChris Lattner 
2830fdc8d8SChris Lattner //----------------------------------------------------------------------
29b9c1b51eSKate Stone // ThreadPlanStepOverRange: Step through a stack range, either stepping over or
3005097246SAdrian Prantl // into based on the value of \a type.
3130fdc8d8SChris Lattner //----------------------------------------------------------------------
3230fdc8d8SChris Lattner 
33b9c1b51eSKate Stone ThreadPlanStepOverRange::ThreadPlanStepOverRange(
34b9c1b51eSKate Stone     Thread &thread, const AddressRange &range,
35b9c1b51eSKate Stone     const SymbolContext &addr_context, lldb::RunMode stop_others,
36b9c1b51eSKate Stone     LazyBool step_out_avoids_code_without_debug_info)
37b9c1b51eSKate Stone     : ThreadPlanStepRange(ThreadPlan::eKindStepOverRange,
38b9c1b51eSKate Stone                           "Step range stepping over", thread, range,
39b9c1b51eSKate Stone                           addr_context, stop_others),
40b9c1b51eSKate Stone       ThreadPlanShouldStopHere(this), m_first_resume(true) {
414b4b2478SJim Ingham   SetFlagsToDefault();
424b4b2478SJim Ingham   SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
4330fdc8d8SChris Lattner }
4430fdc8d8SChris Lattner 
45e65b2cf2SEugene Zelenko ThreadPlanStepOverRange::~ThreadPlanStepOverRange() = default;
4630fdc8d8SChris Lattner 
47b9c1b51eSKate Stone void ThreadPlanStepOverRange::GetDescription(Stream *s,
48b9c1b51eSKate Stone                                              lldb::DescriptionLevel level) {
49e103ae92SJonas Devlieghere   auto PrintFailureIfAny = [&]() {
50e103ae92SJonas Devlieghere     if (m_status.Success())
51e103ae92SJonas Devlieghere       return;
52e103ae92SJonas Devlieghere     s->Printf(" failed (%s)", m_status.AsCString());
53e103ae92SJonas Devlieghere   };
54e103ae92SJonas Devlieghere 
55b9c1b51eSKate Stone   if (level == lldb::eDescriptionLevelBrief) {
562bdbfd50SJim Ingham     s->Printf("step over");
57e103ae92SJonas Devlieghere     PrintFailureIfAny();
582bdbfd50SJim Ingham     return;
592bdbfd50SJim Ingham   }
60e103ae92SJonas Devlieghere 
612bdbfd50SJim Ingham   s->Printf("Stepping over");
622bdbfd50SJim Ingham   bool printed_line_info = false;
63b9c1b51eSKate Stone   if (m_addr_context.line_entry.IsValid()) {
642bdbfd50SJim Ingham     s->Printf(" line ");
652bdbfd50SJim Ingham     m_addr_context.line_entry.DumpStopContext(s, false);
662bdbfd50SJim Ingham     printed_line_info = true;
672bdbfd50SJim Ingham   }
682bdbfd50SJim Ingham 
69b9c1b51eSKate Stone   if (!printed_line_info || level == eDescriptionLevelVerbose) {
702bdbfd50SJim Ingham     s->Printf(" using ranges: ");
71c4c9fedcSJim Ingham     DumpRanges(s);
7230fdc8d8SChris Lattner   }
732bdbfd50SJim Ingham 
74e103ae92SJonas Devlieghere   PrintFailureIfAny();
75e103ae92SJonas Devlieghere 
762bdbfd50SJim Ingham   s->PutChar('.');
7730fdc8d8SChris Lattner }
7830fdc8d8SChris Lattner 
79b9c1b51eSKate Stone void ThreadPlanStepOverRange::SetupAvoidNoDebug(
80b9c1b51eSKate Stone     LazyBool step_out_avoids_code_without_debug_info) {
814b4b2478SJim Ingham   bool avoid_nodebug = true;
82b9c1b51eSKate Stone   switch (step_out_avoids_code_without_debug_info) {
834b4b2478SJim Ingham   case eLazyBoolYes:
844b4b2478SJim Ingham     avoid_nodebug = true;
854b4b2478SJim Ingham     break;
864b4b2478SJim Ingham   case eLazyBoolNo:
874b4b2478SJim Ingham     avoid_nodebug = false;
884b4b2478SJim Ingham     break;
894b4b2478SJim Ingham   case eLazyBoolCalculate:
904b4b2478SJim Ingham     avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
914b4b2478SJim Ingham     break;
924b4b2478SJim Ingham   }
934b4b2478SJim Ingham   if (avoid_nodebug)
944b4b2478SJim Ingham     GetFlags().Set(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
954b4b2478SJim Ingham   else
964b4b2478SJim Ingham     GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
97b9c1b51eSKate Stone   // Step Over plans should always avoid no-debug on step in.  Seems like you
9805097246SAdrian Prantl   // shouldn't have to say this, but a tail call looks more like a step in that
9905097246SAdrian Prantl   // a step out, so we want to catch this case.
100862d1bbdSJim Ingham   GetFlags().Set(ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
1014b4b2478SJim Ingham }
1024b4b2478SJim Ingham 
103b9c1b51eSKate Stone bool ThreadPlanStepOverRange::IsEquivalentContext(
104b9c1b51eSKate Stone     const SymbolContext &context) {
10505097246SAdrian Prantl   // Match as much as is specified in the m_addr_context: This is a fairly
10605097246SAdrian Prantl   // loose sanity check.  Note, sometimes the target doesn't get filled in so I
10705097246SAdrian Prantl   // left out the target check.  And sometimes the module comes in as the .o
10805097246SAdrian Prantl   // file from the inlined range, so I left that out too...
109b9c1b51eSKate Stone   if (m_addr_context.comp_unit) {
110592fa122SSam McCall     if (m_addr_context.comp_unit != context.comp_unit)
111592fa122SSam McCall       return false;
112592fa122SSam McCall     if (m_addr_context.function) {
113592fa122SSam McCall       if (m_addr_context.function != context.function)
114592fa122SSam McCall         return false;
115b9c1b51eSKate Stone       // It is okay to return to a different block of a straight function, we
11605097246SAdrian Prantl       // only have to be more careful if returning from one inlined block to
11705097246SAdrian Prantl       // another.
118b9c1b51eSKate Stone       if (m_addr_context.block->GetInlinedFunctionInfo() == nullptr &&
119b9c1b51eSKate Stone           context.block->GetInlinedFunctionInfo() == nullptr)
1207766c4a8SJim Ingham         return true;
121592fa122SSam McCall       return m_addr_context.block == context.block;
1224b86728bSDaniel Malea     }
1234b86728bSDaniel Malea   }
124592fa122SSam McCall   // Fall back to symbol if we have no decision from comp_unit/function/block.
125a6682a41SJonas Devlieghere   return m_addr_context.symbol && m_addr_context.symbol == context.symbol;
1264b86728bSDaniel Malea }
1274b86728bSDaniel Malea 
128b9c1b51eSKate Stone bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
1295160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
13030fdc8d8SChris Lattner 
131b9c1b51eSKate Stone   if (log) {
13230fdc8d8SChris Lattner     StreamString s;
133b9c1b51eSKate Stone     s.Address(
134b9c1b51eSKate Stone         m_thread.GetRegisterContext()->GetPC(),
1351ac04c30SGreg Clayton         m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
13630fdc8d8SChris Lattner     log->Printf("ThreadPlanStepOverRange reached %s.", s.GetData());
13730fdc8d8SChris Lattner   }
13830fdc8d8SChris Lattner 
13930fdc8d8SChris Lattner   // If we're out of the range but in the same frame or in our caller's frame
14005097246SAdrian Prantl   // then we should stop. When stepping out we only stop others if we are
14105097246SAdrian Prantl   // forcing running one thread.
142e65b2cf2SEugene Zelenko   bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
1434d56e9c1SJim Ingham   ThreadPlanSP new_plan_sp;
144b5c0d1ccSJim Ingham   FrameComparison frame_order = CompareCurrentFrameToStartFrame();
145b5c0d1ccSJim Ingham 
146b9c1b51eSKate Stone   if (frame_order == eFrameCompareOlder) {
1475822173bSJim Ingham     // If we're in an older frame then we should stop.
1485822173bSJim Ingham     //
149b9c1b51eSKate Stone     // A caveat to this is if we think the frame is older but we're actually in
150b9c1b51eSKate Stone     // a trampoline.
151b9c1b51eSKate Stone     // I'm going to make the assumption that you wouldn't RETURN to a
15205097246SAdrian Prantl     // trampoline.  So if we are in a trampoline we think the frame is older
15305097246SAdrian Prantl     // because the trampoline confused the backtracer. As below, we step
15405097246SAdrian Prantl     // through first, and then try to figure out how to get back out again.
1555822173bSJim Ingham 
156e103ae92SJonas Devlieghere     new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
157e103ae92SJonas Devlieghere                                                          stop_others, m_status);
1585822173bSJim Ingham 
1594d56e9c1SJim Ingham     if (new_plan_sp && log)
160b9c1b51eSKate Stone       log->Printf(
161b9c1b51eSKate Stone           "Thought I stepped out, but in fact arrived at a trampoline.");
162b9c1b51eSKate Stone   } else if (frame_order == eFrameCompareYounger) {
163b9c1b51eSKate Stone     // Make sure we really are in a new frame.  Do that by unwinding and seeing
16405097246SAdrian Prantl     // if the start function really is our start function...
165b9c1b51eSKate Stone     for (uint32_t i = 1;; ++i) {
166b57e4a1bSJason Molenda       StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(i);
1674b86728bSDaniel Malea       if (!older_frame_sp) {
168b9c1b51eSKate Stone         // We can't unwind the next frame we should just get out of here &
169b9c1b51eSKate Stone         // stop...
1704b86728bSDaniel Malea         break;
1714b86728bSDaniel Malea       }
1724b86728bSDaniel Malea 
173b9c1b51eSKate Stone       const SymbolContext &older_context =
174b9c1b51eSKate Stone           older_frame_sp->GetSymbolContext(eSymbolContextEverything);
175b9c1b51eSKate Stone       if (IsEquivalentContext(older_context)) {
176b9c1b51eSKate Stone         new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
177b9c1b51eSKate Stone             false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
178e103ae92SJonas Devlieghere             m_status, true);
1794b86728bSDaniel Malea         break;
180b9c1b51eSKate Stone       } else {
181e103ae92SJonas Devlieghere         new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
182e103ae92SJonas Devlieghere             m_stack_id, false, stop_others, m_status);
1835beccb22SJim Ingham         // If we found a way through, then we should stop recursing.
1845beccb22SJim Ingham         if (new_plan_sp)
1855beccb22SJim Ingham           break;
186b5c0d1ccSJim Ingham       }
187b5c0d1ccSJim Ingham     }
188b9c1b51eSKate Stone   } else {
189564d8bc2SJim Ingham     // If we're still in the range, keep going.
190b9c1b51eSKate Stone     if (InRange()) {
191564d8bc2SJim Ingham       SetNextBranchBreakpoint();
192564d8bc2SJim Ingham       return false;
193564d8bc2SJim Ingham     }
194564d8bc2SJim Ingham 
195b9c1b51eSKate Stone     if (!InSymbol()) {
196b9c1b51eSKate Stone       // This one is a little tricky.  Sometimes we may be in a stub or
19705097246SAdrian Prantl       // something similar, in which case we need to get out of there.  But if
19805097246SAdrian Prantl       // we are in a stub then it's likely going to be hard to get out from
19905097246SAdrian Prantl       // here.  It is probably easiest to step into the stub, and then it will
20005097246SAdrian Prantl       // be straight-forward to step out.
201e103ae92SJonas Devlieghere       new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
202e103ae92SJonas Devlieghere           m_stack_id, false, stop_others, m_status);
203b9c1b51eSKate Stone     } else {
20405097246SAdrian Prantl       // The current clang (at least through 424) doesn't always get the
20505097246SAdrian Prantl       // address range for the DW_TAG_inlined_subroutines right, so that when
20605097246SAdrian Prantl       // you leave the inlined range the line table says you are still in the
20705097246SAdrian Prantl       // source file of the inlining function.  This is bad, because now you
20805097246SAdrian Prantl       // are missing the stack frame for the function containing the inlining,
20905097246SAdrian Prantl       // and if you sensibly do "finish" to get out of this function you will
21005097246SAdrian Prantl       // instead exit the containing function. To work around this, we check
21105097246SAdrian Prantl       // whether we are still in the source file we started in, and if not
21205097246SAdrian Prantl       // assume it is an error, and push a plan to get us out of this line and
21305097246SAdrian Prantl       // back to the containing file.
2143bfa753fSJim Ingham 
215b9c1b51eSKate Stone       if (m_addr_context.line_entry.IsValid()) {
2163bfa753fSJim Ingham         SymbolContext sc;
217b57e4a1bSJason Molenda         StackFrameSP frame_sp = m_thread.GetStackFrameAtIndex(0);
2183bfa753fSJim Ingham         sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
219b9c1b51eSKate Stone         if (sc.line_entry.IsValid()) {
220b9c1b51eSKate Stone           if (sc.line_entry.original_file !=
221b9c1b51eSKate Stone                   m_addr_context.line_entry.original_file &&
222b9c1b51eSKate Stone               sc.comp_unit == m_addr_context.comp_unit &&
223b9c1b51eSKate Stone               sc.function == m_addr_context.function) {
22458ef391fSBruce Mitchener             // Okay, find the next occurrence of this file in the line table:
2253bfa753fSJim Ingham             LineTable *line_table = m_addr_context.comp_unit->GetLineTable();
226b9c1b51eSKate Stone             if (line_table) {
2273bfa753fSJim Ingham               Address cur_address = frame_sp->GetFrameCodeAddress();
2283bfa753fSJim Ingham               uint32_t entry_idx;
2293bfa753fSJim Ingham               LineEntry line_entry;
230b9c1b51eSKate Stone               if (line_table->FindLineEntryByAddress(cur_address, line_entry,
231b9c1b51eSKate Stone                                                      &entry_idx)) {
2323bfa753fSJim Ingham                 LineEntry next_line_entry;
2333bfa753fSJim Ingham                 bool step_past_remaining_inline = false;
234b9c1b51eSKate Stone                 if (entry_idx > 0) {
235b9c1b51eSKate Stone                   // We require the previous line entry and the current line
23605097246SAdrian Prantl                   // entry come from the same file. The other requirement is
23705097246SAdrian Prantl                   // that the previous line table entry be part of an inlined
23805097246SAdrian Prantl                   // block, we don't want to step past cases where people have
23905097246SAdrian Prantl                   // inlined some code fragment by using #include <source-
24005097246SAdrian Prantl                   // fragment.c> directly.
2413bfa753fSJim Ingham                   LineEntry prev_line_entry;
242b9c1b51eSKate Stone                   if (line_table->GetLineEntryAtIndex(entry_idx - 1,
243b9c1b51eSKate Stone                                                       prev_line_entry) &&
244b9c1b51eSKate Stone                       prev_line_entry.original_file ==
245b9c1b51eSKate Stone                           line_entry.original_file) {
2463bfa753fSJim Ingham                     SymbolContext prev_sc;
247b9c1b51eSKate Stone                     Address prev_address =
248b9c1b51eSKate Stone                         prev_line_entry.range.GetBaseAddress();
2493bfa753fSJim Ingham                     prev_address.CalculateSymbolContext(&prev_sc);
250b9c1b51eSKate Stone                     if (prev_sc.block) {
251b9c1b51eSKate Stone                       Block *inlined_block =
252b9c1b51eSKate Stone                           prev_sc.block->GetContainingInlinedBlock();
253b9c1b51eSKate Stone                       if (inlined_block) {
2543bfa753fSJim Ingham                         AddressRange inline_range;
255b9c1b51eSKate Stone                         inlined_block->GetRangeContainingAddress(prev_address,
256b9c1b51eSKate Stone                                                                  inline_range);
257b9c1b51eSKate Stone                         if (!inline_range.ContainsFileAddress(cur_address)) {
2583bfa753fSJim Ingham 
2593bfa753fSJim Ingham                           step_past_remaining_inline = true;
2603bfa753fSJim Ingham                         }
2613bfa753fSJim Ingham                       }
2623bfa753fSJim Ingham                     }
2633bfa753fSJim Ingham                   }
2643bfa753fSJim Ingham                 }
2653bfa753fSJim Ingham 
266b9c1b51eSKate Stone                 if (step_past_remaining_inline) {
2673bfa753fSJim Ingham                   uint32_t look_ahead_step = 1;
268b9c1b51eSKate Stone                   while (line_table->GetLineEntryAtIndex(
269b9c1b51eSKate Stone                       entry_idx + look_ahead_step, next_line_entry)) {
270b9c1b51eSKate Stone                     // Make sure we haven't wandered out of the function we
271b9c1b51eSKate Stone                     // started from...
272b9c1b51eSKate Stone                     Address next_line_address =
273b9c1b51eSKate Stone                         next_line_entry.range.GetBaseAddress();
274b9c1b51eSKate Stone                     Function *next_line_function =
275b9c1b51eSKate Stone                         next_line_address.CalculateSymbolContextFunction();
2763bfa753fSJim Ingham                     if (next_line_function != m_addr_context.function)
2773bfa753fSJim Ingham                       break;
2783bfa753fSJim Ingham 
279b9c1b51eSKate Stone                     if (next_line_entry.original_file ==
280b9c1b51eSKate Stone                         m_addr_context.line_entry.original_file) {
2813bfa753fSJim Ingham                       const bool abort_other_plans = false;
28255828080SJim Ingham                       const RunMode stop_other_threads = RunMode::eAllThreads;
283b9c1b51eSKate Stone                       lldb::addr_t cur_pc = m_thread.GetStackFrameAtIndex(0)
284b9c1b51eSKate Stone                                                 ->GetRegisterContext()
285b9c1b51eSKate Stone                                                 ->GetPC();
286b9c1b51eSKate Stone                       AddressRange step_range(
287b9c1b51eSKate Stone                           cur_pc,
288b9c1b51eSKate Stone                           next_line_address.GetLoadAddress(&GetTarget()) -
289b9c1b51eSKate Stone                               cur_pc);
29055828080SJim Ingham 
291b9c1b51eSKate Stone                       new_plan_sp = m_thread.QueueThreadPlanForStepOverRange(
292e103ae92SJonas Devlieghere                           abort_other_plans, step_range, sc, stop_other_threads,
293e103ae92SJonas Devlieghere                           m_status);
2943bfa753fSJim Ingham                       break;
2953bfa753fSJim Ingham                     }
2963bfa753fSJim Ingham                     look_ahead_step++;
2973bfa753fSJim Ingham                   }
2983bfa753fSJim Ingham                 }
2993bfa753fSJim Ingham               }
3003bfa753fSJim Ingham             }
3013bfa753fSJim Ingham           }
3023bfa753fSJim Ingham         }
3033bfa753fSJim Ingham       }
3043bfa753fSJim Ingham     }
305564d8bc2SJim Ingham   }
306564d8bc2SJim Ingham 
307b9c1b51eSKate Stone   // If we get to this point, we're not going to use a previously set "next
308b9c1b51eSKate Stone   // branch" breakpoint, so delete it:
309564d8bc2SJim Ingham   ClearNextBranchBreakpoint();
31030fdc8d8SChris Lattner 
311b9c1b51eSKate Stone   // If we haven't figured out something to do yet, then ask the ShouldStopHere
312b9c1b51eSKate Stone   // callback:
313b9c1b51eSKate Stone   if (!new_plan_sp) {
314e103ae92SJonas Devlieghere     new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
3154b4b2478SJim Ingham   }
3164b4b2478SJim Ingham 
3174d56e9c1SJim Ingham   if (!new_plan_sp)
31830fdc8d8SChris Lattner     m_no_more_plans = true;
319b9c1b51eSKate Stone   else {
3202bdbfd50SJim Ingham     // Any new plan will be an implementation plan, so mark it private:
3212bdbfd50SJim Ingham     new_plan_sp->SetPrivate(true);
32230fdc8d8SChris Lattner     m_no_more_plans = false;
3232bdbfd50SJim Ingham   }
32430fdc8d8SChris Lattner 
325b9c1b51eSKate Stone   if (!new_plan_sp) {
326b9c1b51eSKate Stone     // For efficiencies sake, we know we're done here so we don't have to do
32705097246SAdrian Prantl     // this calculation again in MischiefManaged.
328e103ae92SJonas Devlieghere     SetPlanComplete(m_status.Success());
32930fdc8d8SChris Lattner     return true;
330b9c1b51eSKate Stone   } else
33130fdc8d8SChris Lattner     return false;
33230fdc8d8SChris Lattner }
333fbbfe6ecSJim Ingham 
334b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoPlanExplainsStop(Event *event_ptr) {
33505097246SAdrian Prantl   // For crashes, breakpoint hits, signals, etc, let the base plan (or some
33605097246SAdrian Prantl   // plan above us) handle the stop.  That way the user can see the stop, step
33705097246SAdrian Prantl   // around, and then when they are done, continue and have their step
33805097246SAdrian Prantl   // complete.  The exception is if we've hit our "run to next branch"
33905097246SAdrian Prantl   // breakpoint. Note, unlike the step in range plan, we don't mark ourselves
34005097246SAdrian Prantl   // complete if we hit an unexplained breakpoint/crash.
341fbbfe6ecSJim Ingham 
3425160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
34360c4118cSJim Ingham   StopInfoSP stop_info_sp = GetPrivateStopInfo();
344221d51cfSJim Ingham   bool return_value;
345221d51cfSJim Ingham 
346b9c1b51eSKate Stone   if (stop_info_sp) {
347fbbfe6ecSJim Ingham     StopReason reason = stop_info_sp->GetStopReason();
348fbbfe6ecSJim Ingham 
349b9c1b51eSKate Stone     if (reason == eStopReasonTrace) {
350221d51cfSJim Ingham       return_value = true;
351b9c1b51eSKate Stone     } else if (reason == eStopReasonBreakpoint) {
352e65b2cf2SEugene Zelenko       return_value = NextRangeBreakpointExplainsStop(stop_info_sp);
353b9c1b51eSKate Stone     } else {
354fbbfe6ecSJim Ingham       if (log)
355b9c1b51eSKate Stone         log->PutCString("ThreadPlanStepInRange got asked if it explains the "
356b9c1b51eSKate Stone                         "stop for some reason other than step.");
357221d51cfSJim Ingham       return_value = false;
358fbbfe6ecSJim Ingham     }
359b9c1b51eSKate Stone   } else
360221d51cfSJim Ingham     return_value = true;
361221d51cfSJim Ingham 
362221d51cfSJim Ingham   return return_value;
363fbbfe6ecSJim Ingham }
364513c6bb8SJim Ingham 
365b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoWillResume(lldb::StateType resume_state,
366b9c1b51eSKate Stone                                            bool current_plan) {
367b9c1b51eSKate Stone   if (resume_state != eStateSuspended && m_first_resume) {
368513c6bb8SJim Ingham     m_first_resume = false;
369b9c1b51eSKate Stone     if (resume_state == eStateStepping && current_plan) {
370b9c1b51eSKate Stone       // See if we are about to step over an inlined call in the middle of the
37105097246SAdrian Prantl       // inlined stack, if so figure out its extents and reset our range to
37205097246SAdrian Prantl       // step over that.
373513c6bb8SJim Ingham       bool in_inlined_stack = m_thread.DecrementCurrentInlinedDepth();
374b9c1b51eSKate Stone       if (in_inlined_stack) {
3755160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
376513c6bb8SJim Ingham         if (log)
377b9c1b51eSKate Stone           log->Printf("ThreadPlanStepInRange::DoWillResume: adjusting range to "
378b9c1b51eSKate Stone                       "the frame at inlined depth %d.",
379513c6bb8SJim Ingham                       m_thread.GetCurrentInlinedDepth());
380b57e4a1bSJason Molenda         StackFrameSP stack_sp = m_thread.GetStackFrameAtIndex(0);
381b9c1b51eSKate Stone         if (stack_sp) {
382513c6bb8SJim Ingham           Block *frame_block = stack_sp->GetFrameBlock();
383513c6bb8SJim Ingham           lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
384513c6bb8SJim Ingham           AddressRange my_range;
385b9c1b51eSKate Stone           if (frame_block->GetRangeContainingLoadAddress(
386b9c1b51eSKate Stone                   curr_pc, m_thread.GetProcess()->GetTarget(), my_range)) {
387513c6bb8SJim Ingham             m_address_ranges.clear();
388513c6bb8SJim Ingham             m_address_ranges.push_back(my_range);
389b9c1b51eSKate Stone             if (log) {
390513c6bb8SJim Ingham               StreamString s;
391b9c1b51eSKate Stone               const InlineFunctionInfo *inline_info =
392b9c1b51eSKate Stone                   frame_block->GetInlinedFunctionInfo();
393513c6bb8SJim Ingham               const char *name;
394513c6bb8SJim Ingham               if (inline_info)
395b9c1b51eSKate Stone                 name =
396b9c1b51eSKate Stone                     inline_info
397b9c1b51eSKate Stone                         ->GetName(frame_block->CalculateSymbolContextFunction()
398b9c1b51eSKate Stone                                       ->GetLanguage())
399b9c1b51eSKate Stone                         .AsCString();
400513c6bb8SJim Ingham               else
401513c6bb8SJim Ingham                 name = "<unknown-notinlined>";
402513c6bb8SJim Ingham 
403b9c1b51eSKate Stone               s.Printf(
404b9c1b51eSKate Stone                   "Stepping over inlined function \"%s\" in inlined stack: ",
405b9c1b51eSKate Stone                   name);
406513c6bb8SJim Ingham               DumpRanges(&s);
407c156427dSZachary Turner               log->PutString(s.GetString());
408513c6bb8SJim Ingham             }
409513c6bb8SJim Ingham           }
410513c6bb8SJim Ingham         }
411513c6bb8SJim Ingham       }
412513c6bb8SJim Ingham     }
413513c6bb8SJim Ingham   }
414513c6bb8SJim Ingham 
415221d51cfSJim Ingham   return true;
416513c6bb8SJim Ingham }
417