180814287SRaphael Isemann //===-- ThreadPlanStepOverRange.cpp ---------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler 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 
28b9c1b51eSKate Stone // ThreadPlanStepOverRange: Step through a stack range, either stepping over or
2905097246SAdrian Prantl // into based on the value of \a type.
3030fdc8d8SChris Lattner 
31b9c1b51eSKate Stone ThreadPlanStepOverRange::ThreadPlanStepOverRange(
32b9c1b51eSKate Stone     Thread &thread, const AddressRange &range,
33b9c1b51eSKate Stone     const SymbolContext &addr_context, lldb::RunMode stop_others,
34b9c1b51eSKate Stone     LazyBool step_out_avoids_code_without_debug_info)
35b9c1b51eSKate Stone     : ThreadPlanStepRange(ThreadPlan::eKindStepOverRange,
36b9c1b51eSKate Stone                           "Step range stepping over", thread, range,
37b9c1b51eSKate Stone                           addr_context, stop_others),
38b9c1b51eSKate Stone       ThreadPlanShouldStopHere(this), m_first_resume(true) {
394b4b2478SJim Ingham   SetFlagsToDefault();
404b4b2478SJim Ingham   SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
4130fdc8d8SChris Lattner }
4230fdc8d8SChris Lattner 
43e65b2cf2SEugene Zelenko ThreadPlanStepOverRange::~ThreadPlanStepOverRange() = default;
4430fdc8d8SChris Lattner 
45b9c1b51eSKate Stone void ThreadPlanStepOverRange::GetDescription(Stream *s,
46b9c1b51eSKate Stone                                              lldb::DescriptionLevel level) {
47e103ae92SJonas Devlieghere   auto PrintFailureIfAny = [&]() {
48e103ae92SJonas Devlieghere     if (m_status.Success())
49e103ae92SJonas Devlieghere       return;
50e103ae92SJonas Devlieghere     s->Printf(" failed (%s)", m_status.AsCString());
51e103ae92SJonas Devlieghere   };
52e103ae92SJonas Devlieghere 
53b9c1b51eSKate Stone   if (level == lldb::eDescriptionLevelBrief) {
542bdbfd50SJim Ingham     s->Printf("step over");
55e103ae92SJonas Devlieghere     PrintFailureIfAny();
562bdbfd50SJim Ingham     return;
572bdbfd50SJim Ingham   }
58e103ae92SJonas Devlieghere 
592bdbfd50SJim Ingham   s->Printf("Stepping over");
602bdbfd50SJim Ingham   bool printed_line_info = false;
61b9c1b51eSKate Stone   if (m_addr_context.line_entry.IsValid()) {
622bdbfd50SJim Ingham     s->Printf(" line ");
632bdbfd50SJim Ingham     m_addr_context.line_entry.DumpStopContext(s, false);
642bdbfd50SJim Ingham     printed_line_info = true;
652bdbfd50SJim Ingham   }
662bdbfd50SJim Ingham 
67b9c1b51eSKate Stone   if (!printed_line_info || level == eDescriptionLevelVerbose) {
682bdbfd50SJim Ingham     s->Printf(" using ranges: ");
69c4c9fedcSJim Ingham     DumpRanges(s);
7030fdc8d8SChris Lattner   }
712bdbfd50SJim Ingham 
72e103ae92SJonas Devlieghere   PrintFailureIfAny();
73e103ae92SJonas Devlieghere 
742bdbfd50SJim Ingham   s->PutChar('.');
7530fdc8d8SChris Lattner }
7630fdc8d8SChris Lattner 
77b9c1b51eSKate Stone void ThreadPlanStepOverRange::SetupAvoidNoDebug(
78b9c1b51eSKate Stone     LazyBool step_out_avoids_code_without_debug_info) {
794b4b2478SJim Ingham   bool avoid_nodebug = true;
80b9c1b51eSKate Stone   switch (step_out_avoids_code_without_debug_info) {
814b4b2478SJim Ingham   case eLazyBoolYes:
824b4b2478SJim Ingham     avoid_nodebug = true;
834b4b2478SJim Ingham     break;
844b4b2478SJim Ingham   case eLazyBoolNo:
854b4b2478SJim Ingham     avoid_nodebug = false;
864b4b2478SJim Ingham     break;
874b4b2478SJim Ingham   case eLazyBoolCalculate:
884b4b2478SJim Ingham     avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
894b4b2478SJim Ingham     break;
904b4b2478SJim Ingham   }
914b4b2478SJim Ingham   if (avoid_nodebug)
924b4b2478SJim Ingham     GetFlags().Set(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
934b4b2478SJim Ingham   else
944b4b2478SJim Ingham     GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
95b9c1b51eSKate Stone   // Step Over plans should always avoid no-debug on step in.  Seems like you
9605097246SAdrian Prantl   // shouldn't have to say this, but a tail call looks more like a step in that
9705097246SAdrian Prantl   // a step out, so we want to catch this case.
98862d1bbdSJim Ingham   GetFlags().Set(ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
994b4b2478SJim Ingham }
1004b4b2478SJim Ingham 
101b9c1b51eSKate Stone bool ThreadPlanStepOverRange::IsEquivalentContext(
102b9c1b51eSKate Stone     const SymbolContext &context) {
10305097246SAdrian Prantl   // Match as much as is specified in the m_addr_context: This is a fairly
10405097246SAdrian Prantl   // loose sanity check.  Note, sometimes the target doesn't get filled in so I
10505097246SAdrian Prantl   // left out the target check.  And sometimes the module comes in as the .o
10605097246SAdrian Prantl   // file from the inlined range, so I left that out too...
107b9c1b51eSKate Stone   if (m_addr_context.comp_unit) {
108592fa122SSam McCall     if (m_addr_context.comp_unit != context.comp_unit)
109592fa122SSam McCall       return false;
110592fa122SSam McCall     if (m_addr_context.function) {
111592fa122SSam McCall       if (m_addr_context.function != context.function)
112592fa122SSam McCall         return false;
113b9c1b51eSKate Stone       // It is okay to return to a different block of a straight function, we
11405097246SAdrian Prantl       // only have to be more careful if returning from one inlined block to
11505097246SAdrian Prantl       // another.
116b9c1b51eSKate Stone       if (m_addr_context.block->GetInlinedFunctionInfo() == nullptr &&
117b9c1b51eSKate Stone           context.block->GetInlinedFunctionInfo() == nullptr)
1187766c4a8SJim Ingham         return true;
119592fa122SSam McCall       return m_addr_context.block == context.block;
1204b86728bSDaniel Malea     }
1214b86728bSDaniel Malea   }
122592fa122SSam McCall   // Fall back to symbol if we have no decision from comp_unit/function/block.
123a6682a41SJonas Devlieghere   return m_addr_context.symbol && m_addr_context.symbol == context.symbol;
1244b86728bSDaniel Malea }
1254b86728bSDaniel Malea 
126b9c1b51eSKate Stone bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
1275160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
12830fdc8d8SChris Lattner 
129b9c1b51eSKate Stone   if (log) {
13030fdc8d8SChris Lattner     StreamString s;
1311462f5a4SRaphael Isemann     DumpAddress(
1321462f5a4SRaphael Isemann         s.AsRawOstream(), m_thread.GetRegisterContext()->GetPC(),
1331ac04c30SGreg Clayton         m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
13463e5fb76SJonas Devlieghere     LLDB_LOGF(log, "ThreadPlanStepOverRange reached %s.", s.GetData());
13530fdc8d8SChris Lattner   }
13630fdc8d8SChris Lattner 
13730fdc8d8SChris Lattner   // If we're out of the range but in the same frame or in our caller's frame
13805097246SAdrian Prantl   // then we should stop. When stepping out we only stop others if we are
13905097246SAdrian Prantl   // forcing running one thread.
140e65b2cf2SEugene Zelenko   bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
1414d56e9c1SJim Ingham   ThreadPlanSP new_plan_sp;
142b5c0d1ccSJim Ingham   FrameComparison frame_order = CompareCurrentFrameToStartFrame();
143b5c0d1ccSJim Ingham 
144b9c1b51eSKate Stone   if (frame_order == eFrameCompareOlder) {
1455822173bSJim Ingham     // If we're in an older frame then we should stop.
1465822173bSJim Ingham     //
147b9c1b51eSKate Stone     // A caveat to this is if we think the frame is older but we're actually in
148b9c1b51eSKate Stone     // a trampoline.
149b9c1b51eSKate Stone     // I'm going to make the assumption that you wouldn't RETURN to a
15005097246SAdrian Prantl     // trampoline.  So if we are in a trampoline we think the frame is older
15105097246SAdrian Prantl     // because the trampoline confused the backtracer. As below, we step
15205097246SAdrian Prantl     // through first, and then try to figure out how to get back out again.
1535822173bSJim Ingham 
154e103ae92SJonas Devlieghere     new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
155e103ae92SJonas Devlieghere                                                          stop_others, m_status);
1565822173bSJim Ingham 
1574d56e9c1SJim Ingham     if (new_plan_sp && log)
15863e5fb76SJonas Devlieghere       LLDB_LOGF(log,
159b9c1b51eSKate Stone                 "Thought I stepped out, but in fact arrived at a trampoline.");
160b9c1b51eSKate Stone   } else if (frame_order == eFrameCompareYounger) {
161b9c1b51eSKate Stone     // Make sure we really are in a new frame.  Do that by unwinding and seeing
16205097246SAdrian Prantl     // if the start function really is our start function...
163b9c1b51eSKate Stone     for (uint32_t i = 1;; ++i) {
164b57e4a1bSJason Molenda       StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(i);
1654b86728bSDaniel Malea       if (!older_frame_sp) {
166b9c1b51eSKate Stone         // We can't unwind the next frame we should just get out of here &
167b9c1b51eSKate Stone         // stop...
1684b86728bSDaniel Malea         break;
1694b86728bSDaniel Malea       }
1704b86728bSDaniel Malea 
171b9c1b51eSKate Stone       const SymbolContext &older_context =
172b9c1b51eSKate Stone           older_frame_sp->GetSymbolContext(eSymbolContextEverything);
173b9c1b51eSKate Stone       if (IsEquivalentContext(older_context)) {
174*089cfe11SJaroslav Sevcik         // If we have the  next-branch-breakpoint in the range, we can just
175*089cfe11SJaroslav Sevcik         // rely on that breakpoint to trigger once we return to the range.
176*089cfe11SJaroslav Sevcik         if (m_next_branch_bp_sp)
177*089cfe11SJaroslav Sevcik           return false;
178b9c1b51eSKate Stone         new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
179b9c1b51eSKate Stone             false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
180e103ae92SJonas Devlieghere             m_status, true);
1814b86728bSDaniel Malea         break;
182b9c1b51eSKate Stone       } else {
183e103ae92SJonas Devlieghere         new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
184e103ae92SJonas Devlieghere             m_stack_id, false, stop_others, m_status);
1855beccb22SJim Ingham         // If we found a way through, then we should stop recursing.
1865beccb22SJim Ingham         if (new_plan_sp)
1875beccb22SJim Ingham           break;
188b5c0d1ccSJim Ingham       }
189b5c0d1ccSJim Ingham     }
190b9c1b51eSKate Stone   } else {
191564d8bc2SJim Ingham     // If we're still in the range, keep going.
192b9c1b51eSKate Stone     if (InRange()) {
193564d8bc2SJim Ingham       SetNextBranchBreakpoint();
194564d8bc2SJim Ingham       return false;
195564d8bc2SJim Ingham     }
196564d8bc2SJim Ingham 
197b9c1b51eSKate Stone     if (!InSymbol()) {
198b9c1b51eSKate Stone       // This one is a little tricky.  Sometimes we may be in a stub or
19905097246SAdrian Prantl       // something similar, in which case we need to get out of there.  But if
20005097246SAdrian Prantl       // we are in a stub then it's likely going to be hard to get out from
20105097246SAdrian Prantl       // here.  It is probably easiest to step into the stub, and then it will
20205097246SAdrian Prantl       // be straight-forward to step out.
203e103ae92SJonas Devlieghere       new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
204e103ae92SJonas Devlieghere           m_stack_id, false, stop_others, m_status);
205b9c1b51eSKate Stone     } else {
20605097246SAdrian Prantl       // The current clang (at least through 424) doesn't always get the
20705097246SAdrian Prantl       // address range for the DW_TAG_inlined_subroutines right, so that when
20805097246SAdrian Prantl       // you leave the inlined range the line table says you are still in the
20905097246SAdrian Prantl       // source file of the inlining function.  This is bad, because now you
21005097246SAdrian Prantl       // are missing the stack frame for the function containing the inlining,
21105097246SAdrian Prantl       // and if you sensibly do "finish" to get out of this function you will
21205097246SAdrian Prantl       // instead exit the containing function. To work around this, we check
21305097246SAdrian Prantl       // whether we are still in the source file we started in, and if not
21405097246SAdrian Prantl       // assume it is an error, and push a plan to get us out of this line and
21505097246SAdrian Prantl       // back to the containing file.
2163bfa753fSJim Ingham 
217b9c1b51eSKate Stone       if (m_addr_context.line_entry.IsValid()) {
2183bfa753fSJim Ingham         SymbolContext sc;
219b57e4a1bSJason Molenda         StackFrameSP frame_sp = m_thread.GetStackFrameAtIndex(0);
2203bfa753fSJim Ingham         sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
221b9c1b51eSKate Stone         if (sc.line_entry.IsValid()) {
222b9c1b51eSKate Stone           if (sc.line_entry.original_file !=
223b9c1b51eSKate Stone                   m_addr_context.line_entry.original_file &&
224b9c1b51eSKate Stone               sc.comp_unit == m_addr_context.comp_unit &&
225b9c1b51eSKate Stone               sc.function == m_addr_context.function) {
22658ef391fSBruce Mitchener             // Okay, find the next occurrence of this file in the line table:
2273bfa753fSJim Ingham             LineTable *line_table = m_addr_context.comp_unit->GetLineTable();
228b9c1b51eSKate Stone             if (line_table) {
2293bfa753fSJim Ingham               Address cur_address = frame_sp->GetFrameCodeAddress();
2303bfa753fSJim Ingham               uint32_t entry_idx;
2313bfa753fSJim Ingham               LineEntry line_entry;
232b9c1b51eSKate Stone               if (line_table->FindLineEntryByAddress(cur_address, line_entry,
233b9c1b51eSKate Stone                                                      &entry_idx)) {
2343bfa753fSJim Ingham                 LineEntry next_line_entry;
2353bfa753fSJim Ingham                 bool step_past_remaining_inline = false;
236b9c1b51eSKate Stone                 if (entry_idx > 0) {
237b9c1b51eSKate Stone                   // We require the previous line entry and the current line
23805097246SAdrian Prantl                   // entry come from the same file. The other requirement is
23905097246SAdrian Prantl                   // that the previous line table entry be part of an inlined
24005097246SAdrian Prantl                   // block, we don't want to step past cases where people have
24105097246SAdrian Prantl                   // inlined some code fragment by using #include <source-
24205097246SAdrian Prantl                   // fragment.c> directly.
2433bfa753fSJim Ingham                   LineEntry prev_line_entry;
244b9c1b51eSKate Stone                   if (line_table->GetLineEntryAtIndex(entry_idx - 1,
245b9c1b51eSKate Stone                                                       prev_line_entry) &&
246b9c1b51eSKate Stone                       prev_line_entry.original_file ==
247b9c1b51eSKate Stone                           line_entry.original_file) {
2483bfa753fSJim Ingham                     SymbolContext prev_sc;
249b9c1b51eSKate Stone                     Address prev_address =
250b9c1b51eSKate Stone                         prev_line_entry.range.GetBaseAddress();
2513bfa753fSJim Ingham                     prev_address.CalculateSymbolContext(&prev_sc);
252b9c1b51eSKate Stone                     if (prev_sc.block) {
253b9c1b51eSKate Stone                       Block *inlined_block =
254b9c1b51eSKate Stone                           prev_sc.block->GetContainingInlinedBlock();
255b9c1b51eSKate Stone                       if (inlined_block) {
2563bfa753fSJim Ingham                         AddressRange inline_range;
257b9c1b51eSKate Stone                         inlined_block->GetRangeContainingAddress(prev_address,
258b9c1b51eSKate Stone                                                                  inline_range);
259b9c1b51eSKate Stone                         if (!inline_range.ContainsFileAddress(cur_address)) {
2603bfa753fSJim Ingham 
2613bfa753fSJim Ingham                           step_past_remaining_inline = true;
2623bfa753fSJim Ingham                         }
2633bfa753fSJim Ingham                       }
2643bfa753fSJim Ingham                     }
2653bfa753fSJim Ingham                   }
2663bfa753fSJim Ingham                 }
2673bfa753fSJim Ingham 
268b9c1b51eSKate Stone                 if (step_past_remaining_inline) {
2693bfa753fSJim Ingham                   uint32_t look_ahead_step = 1;
270b9c1b51eSKate Stone                   while (line_table->GetLineEntryAtIndex(
271b9c1b51eSKate Stone                       entry_idx + look_ahead_step, next_line_entry)) {
272b9c1b51eSKate Stone                     // Make sure we haven't wandered out of the function we
273b9c1b51eSKate Stone                     // started from...
274b9c1b51eSKate Stone                     Address next_line_address =
275b9c1b51eSKate Stone                         next_line_entry.range.GetBaseAddress();
276b9c1b51eSKate Stone                     Function *next_line_function =
277b9c1b51eSKate Stone                         next_line_address.CalculateSymbolContextFunction();
2783bfa753fSJim Ingham                     if (next_line_function != m_addr_context.function)
2793bfa753fSJim Ingham                       break;
2803bfa753fSJim Ingham 
281b9c1b51eSKate Stone                     if (next_line_entry.original_file ==
282b9c1b51eSKate Stone                         m_addr_context.line_entry.original_file) {
2833bfa753fSJim Ingham                       const bool abort_other_plans = false;
28455828080SJim Ingham                       const RunMode stop_other_threads = RunMode::eAllThreads;
285b9c1b51eSKate Stone                       lldb::addr_t cur_pc = m_thread.GetStackFrameAtIndex(0)
286b9c1b51eSKate Stone                                                 ->GetRegisterContext()
287b9c1b51eSKate Stone                                                 ->GetPC();
288b9c1b51eSKate Stone                       AddressRange step_range(
289b9c1b51eSKate Stone                           cur_pc,
290b9c1b51eSKate Stone                           next_line_address.GetLoadAddress(&GetTarget()) -
291b9c1b51eSKate Stone                               cur_pc);
29255828080SJim Ingham 
293b9c1b51eSKate Stone                       new_plan_sp = m_thread.QueueThreadPlanForStepOverRange(
294e103ae92SJonas Devlieghere                           abort_other_plans, step_range, sc, stop_other_threads,
295e103ae92SJonas Devlieghere                           m_status);
2963bfa753fSJim Ingham                       break;
2973bfa753fSJim Ingham                     }
2983bfa753fSJim Ingham                     look_ahead_step++;
2993bfa753fSJim Ingham                   }
3003bfa753fSJim Ingham                 }
3013bfa753fSJim Ingham               }
3023bfa753fSJim Ingham             }
3033bfa753fSJim Ingham           }
3043bfa753fSJim Ingham         }
3053bfa753fSJim Ingham       }
3063bfa753fSJim Ingham     }
307564d8bc2SJim Ingham   }
308564d8bc2SJim Ingham 
309b9c1b51eSKate Stone   // If we get to this point, we're not going to use a previously set "next
310b9c1b51eSKate Stone   // branch" breakpoint, so delete it:
311564d8bc2SJim Ingham   ClearNextBranchBreakpoint();
31230fdc8d8SChris Lattner 
313b9c1b51eSKate Stone   // If we haven't figured out something to do yet, then ask the ShouldStopHere
314b9c1b51eSKate Stone   // callback:
315b9c1b51eSKate Stone   if (!new_plan_sp) {
316e103ae92SJonas Devlieghere     new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
3174b4b2478SJim Ingham   }
3184b4b2478SJim Ingham 
3194d56e9c1SJim Ingham   if (!new_plan_sp)
32030fdc8d8SChris Lattner     m_no_more_plans = true;
321b9c1b51eSKate Stone   else {
3222bdbfd50SJim Ingham     // Any new plan will be an implementation plan, so mark it private:
3232bdbfd50SJim Ingham     new_plan_sp->SetPrivate(true);
32430fdc8d8SChris Lattner     m_no_more_plans = false;
3252bdbfd50SJim Ingham   }
32630fdc8d8SChris Lattner 
327b9c1b51eSKate Stone   if (!new_plan_sp) {
328b9c1b51eSKate Stone     // For efficiencies sake, we know we're done here so we don't have to do
32905097246SAdrian Prantl     // this calculation again in MischiefManaged.
330e103ae92SJonas Devlieghere     SetPlanComplete(m_status.Success());
33130fdc8d8SChris Lattner     return true;
332b9c1b51eSKate Stone   } else
33330fdc8d8SChris Lattner     return false;
33430fdc8d8SChris Lattner }
335fbbfe6ecSJim Ingham 
336b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoPlanExplainsStop(Event *event_ptr) {
33705097246SAdrian Prantl   // For crashes, breakpoint hits, signals, etc, let the base plan (or some
33805097246SAdrian Prantl   // plan above us) handle the stop.  That way the user can see the stop, step
33905097246SAdrian Prantl   // around, and then when they are done, continue and have their step
34005097246SAdrian Prantl   // complete.  The exception is if we've hit our "run to next branch"
34105097246SAdrian Prantl   // breakpoint. Note, unlike the step in range plan, we don't mark ourselves
34205097246SAdrian Prantl   // complete if we hit an unexplained breakpoint/crash.
343fbbfe6ecSJim Ingham 
3445160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
34560c4118cSJim Ingham   StopInfoSP stop_info_sp = GetPrivateStopInfo();
346221d51cfSJim Ingham   bool return_value;
347221d51cfSJim Ingham 
348b9c1b51eSKate Stone   if (stop_info_sp) {
349fbbfe6ecSJim Ingham     StopReason reason = stop_info_sp->GetStopReason();
350fbbfe6ecSJim Ingham 
351b9c1b51eSKate Stone     if (reason == eStopReasonTrace) {
352221d51cfSJim Ingham       return_value = true;
353b9c1b51eSKate Stone     } else if (reason == eStopReasonBreakpoint) {
354e65b2cf2SEugene Zelenko       return_value = NextRangeBreakpointExplainsStop(stop_info_sp);
355b9c1b51eSKate Stone     } else {
356fbbfe6ecSJim Ingham       if (log)
357b9c1b51eSKate Stone         log->PutCString("ThreadPlanStepInRange got asked if it explains the "
358b9c1b51eSKate Stone                         "stop for some reason other than step.");
359221d51cfSJim Ingham       return_value = false;
360fbbfe6ecSJim Ingham     }
361b9c1b51eSKate Stone   } else
362221d51cfSJim Ingham     return_value = true;
363221d51cfSJim Ingham 
364221d51cfSJim Ingham   return return_value;
365fbbfe6ecSJim Ingham }
366513c6bb8SJim Ingham 
367b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoWillResume(lldb::StateType resume_state,
368b9c1b51eSKate Stone                                            bool current_plan) {
369b9c1b51eSKate Stone   if (resume_state != eStateSuspended && m_first_resume) {
370513c6bb8SJim Ingham     m_first_resume = false;
371b9c1b51eSKate Stone     if (resume_state == eStateStepping && current_plan) {
372b9c1b51eSKate Stone       // See if we are about to step over an inlined call in the middle of the
37305097246SAdrian Prantl       // inlined stack, if so figure out its extents and reset our range to
37405097246SAdrian Prantl       // step over that.
375513c6bb8SJim Ingham       bool in_inlined_stack = m_thread.DecrementCurrentInlinedDepth();
376b9c1b51eSKate Stone       if (in_inlined_stack) {
3775160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
37863e5fb76SJonas Devlieghere         LLDB_LOGF(log,
37963e5fb76SJonas Devlieghere                   "ThreadPlanStepInRange::DoWillResume: adjusting range to "
380b9c1b51eSKate Stone                   "the frame at inlined depth %d.",
381513c6bb8SJim Ingham                   m_thread.GetCurrentInlinedDepth());
382b57e4a1bSJason Molenda         StackFrameSP stack_sp = m_thread.GetStackFrameAtIndex(0);
383b9c1b51eSKate Stone         if (stack_sp) {
384513c6bb8SJim Ingham           Block *frame_block = stack_sp->GetFrameBlock();
385513c6bb8SJim Ingham           lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
386513c6bb8SJim Ingham           AddressRange my_range;
387b9c1b51eSKate Stone           if (frame_block->GetRangeContainingLoadAddress(
388b9c1b51eSKate Stone                   curr_pc, m_thread.GetProcess()->GetTarget(), my_range)) {
389513c6bb8SJim Ingham             m_address_ranges.clear();
390513c6bb8SJim Ingham             m_address_ranges.push_back(my_range);
391b9c1b51eSKate Stone             if (log) {
392513c6bb8SJim Ingham               StreamString s;
393b9c1b51eSKate Stone               const InlineFunctionInfo *inline_info =
394b9c1b51eSKate Stone                   frame_block->GetInlinedFunctionInfo();
395513c6bb8SJim Ingham               const char *name;
396513c6bb8SJim Ingham               if (inline_info)
39722b04487SAlex Langford                 name = inline_info->GetName().AsCString();
398513c6bb8SJim Ingham               else
399513c6bb8SJim Ingham                 name = "<unknown-notinlined>";
400513c6bb8SJim Ingham 
401b9c1b51eSKate Stone               s.Printf(
402b9c1b51eSKate Stone                   "Stepping over inlined function \"%s\" in inlined stack: ",
403b9c1b51eSKate Stone                   name);
404513c6bb8SJim Ingham               DumpRanges(&s);
405c156427dSZachary Turner               log->PutString(s.GetString());
406513c6bb8SJim Ingham             }
407513c6bb8SJim Ingham           }
408513c6bb8SJim Ingham         }
409513c6bb8SJim Ingham       }
410513c6bb8SJim Ingham     }
411513c6bb8SJim Ingham   }
412513c6bb8SJim Ingham 
413221d51cfSJim Ingham   return true;
414513c6bb8SJim Ingham }
415