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 
1030fdc8d8SChris Lattner // C Includes
1130fdc8d8SChris Lattner // C++ Includes
1230fdc8d8SChris Lattner // Other libraries and framework includes
1330fdc8d8SChris Lattner // Project includes
14e65b2cf2SEugene Zelenko #include "lldb/Target/ThreadPlanStepOverRange.h"
15513c6bb8SJim Ingham #include "lldb/Symbol/Block.h"
163bfa753fSJim Ingham #include "lldb/Symbol/CompileUnit.h"
17513c6bb8SJim Ingham #include "lldb/Symbol/Function.h"
183bfa753fSJim Ingham #include "lldb/Symbol/LineTable.h"
1930fdc8d8SChris Lattner #include "lldb/Target/Process.h"
2030fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
21514487e8SGreg Clayton #include "lldb/Target/Target.h"
2230fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2330fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepOut.h"
2430fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepThrough.h"
256f9e6901SZachary Turner #include "lldb/Utility/Log.h"
26bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
2730fdc8d8SChris Lattner 
2830fdc8d8SChris Lattner using namespace lldb_private;
292d4edfbcSGreg Clayton using namespace lldb;
3030fdc8d8SChris Lattner 
314b4b2478SJim Ingham uint32_t ThreadPlanStepOverRange::s_default_flag_values = 0;
3230fdc8d8SChris Lattner 
3330fdc8d8SChris Lattner //----------------------------------------------------------------------
34b9c1b51eSKate Stone // ThreadPlanStepOverRange: Step through a stack range, either stepping over or
35*05097246SAdrian Prantl // into based on the value of \a type.
3630fdc8d8SChris Lattner //----------------------------------------------------------------------
3730fdc8d8SChris Lattner 
38b9c1b51eSKate Stone ThreadPlanStepOverRange::ThreadPlanStepOverRange(
39b9c1b51eSKate Stone     Thread &thread, const AddressRange &range,
40b9c1b51eSKate Stone     const SymbolContext &addr_context, lldb::RunMode stop_others,
41b9c1b51eSKate Stone     LazyBool step_out_avoids_code_without_debug_info)
42b9c1b51eSKate Stone     : ThreadPlanStepRange(ThreadPlan::eKindStepOverRange,
43b9c1b51eSKate Stone                           "Step range stepping over", thread, range,
44b9c1b51eSKate Stone                           addr_context, stop_others),
45b9c1b51eSKate Stone       ThreadPlanShouldStopHere(this), m_first_resume(true) {
464b4b2478SJim Ingham   SetFlagsToDefault();
474b4b2478SJim Ingham   SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
4830fdc8d8SChris Lattner }
4930fdc8d8SChris Lattner 
50e65b2cf2SEugene Zelenko ThreadPlanStepOverRange::~ThreadPlanStepOverRange() = default;
5130fdc8d8SChris Lattner 
52b9c1b51eSKate Stone void ThreadPlanStepOverRange::GetDescription(Stream *s,
53b9c1b51eSKate Stone                                              lldb::DescriptionLevel level) {
54b9c1b51eSKate Stone   if (level == lldb::eDescriptionLevelBrief) {
552bdbfd50SJim Ingham     s->Printf("step over");
562bdbfd50SJim Ingham     return;
572bdbfd50SJim Ingham   }
582bdbfd50SJim Ingham   s->Printf("Stepping over");
592bdbfd50SJim Ingham   bool printed_line_info = false;
60b9c1b51eSKate Stone   if (m_addr_context.line_entry.IsValid()) {
612bdbfd50SJim Ingham     s->Printf(" line ");
622bdbfd50SJim Ingham     m_addr_context.line_entry.DumpStopContext(s, false);
632bdbfd50SJim Ingham     printed_line_info = true;
642bdbfd50SJim Ingham   }
652bdbfd50SJim Ingham 
66b9c1b51eSKate Stone   if (!printed_line_info || level == eDescriptionLevelVerbose) {
672bdbfd50SJim Ingham     s->Printf(" using ranges: ");
68c4c9fedcSJim Ingham     DumpRanges(s);
6930fdc8d8SChris Lattner   }
702bdbfd50SJim Ingham 
712bdbfd50SJim Ingham   s->PutChar('.');
7230fdc8d8SChris Lattner }
7330fdc8d8SChris Lattner 
74b9c1b51eSKate Stone void ThreadPlanStepOverRange::SetupAvoidNoDebug(
75b9c1b51eSKate Stone     LazyBool step_out_avoids_code_without_debug_info) {
764b4b2478SJim Ingham   bool avoid_nodebug = true;
77b9c1b51eSKate Stone   switch (step_out_avoids_code_without_debug_info) {
784b4b2478SJim Ingham   case eLazyBoolYes:
794b4b2478SJim Ingham     avoid_nodebug = true;
804b4b2478SJim Ingham     break;
814b4b2478SJim Ingham   case eLazyBoolNo:
824b4b2478SJim Ingham     avoid_nodebug = false;
834b4b2478SJim Ingham     break;
844b4b2478SJim Ingham   case eLazyBoolCalculate:
854b4b2478SJim Ingham     avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
864b4b2478SJim Ingham     break;
874b4b2478SJim Ingham   }
884b4b2478SJim Ingham   if (avoid_nodebug)
894b4b2478SJim Ingham     GetFlags().Set(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
904b4b2478SJim Ingham   else
914b4b2478SJim Ingham     GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
92b9c1b51eSKate Stone   // Step Over plans should always avoid no-debug on step in.  Seems like you
93*05097246SAdrian Prantl   // shouldn't have to say this, but a tail call looks more like a step in that
94*05097246SAdrian Prantl   // a step out, so we want to catch this case.
95862d1bbdSJim Ingham   GetFlags().Set(ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
964b4b2478SJim Ingham }
974b4b2478SJim Ingham 
98b9c1b51eSKate Stone bool ThreadPlanStepOverRange::IsEquivalentContext(
99b9c1b51eSKate Stone     const SymbolContext &context) {
100*05097246SAdrian Prantl   // Match as much as is specified in the m_addr_context: This is a fairly
101*05097246SAdrian Prantl   // loose sanity check.  Note, sometimes the target doesn't get filled in so I
102*05097246SAdrian Prantl   // left out the target check.  And sometimes the module comes in as the .o
103*05097246SAdrian Prantl   // file from the inlined range, so I left that out too...
104b9c1b51eSKate Stone   if (m_addr_context.comp_unit) {
105592fa122SSam McCall     if (m_addr_context.comp_unit != context.comp_unit)
106592fa122SSam McCall       return false;
107592fa122SSam McCall     if (m_addr_context.function) {
108592fa122SSam McCall       if (m_addr_context.function != context.function)
109592fa122SSam McCall         return false;
110b9c1b51eSKate Stone       // It is okay to return to a different block of a straight function, we
111*05097246SAdrian Prantl       // only have to be more careful if returning from one inlined block to
112*05097246SAdrian Prantl       // another.
113b9c1b51eSKate Stone       if (m_addr_context.block->GetInlinedFunctionInfo() == nullptr &&
114b9c1b51eSKate Stone           context.block->GetInlinedFunctionInfo() == nullptr)
1157766c4a8SJim Ingham         return true;
116592fa122SSam McCall       return m_addr_context.block == context.block;
1174b86728bSDaniel Malea     }
1184b86728bSDaniel Malea   }
119592fa122SSam McCall   // Fall back to symbol if we have no decision from comp_unit/function/block.
120592fa122SSam McCall   if (m_addr_context.symbol && m_addr_context.symbol == context.symbol) {
1214b86728bSDaniel Malea     return true;
1224b86728bSDaniel Malea   }
1234b86728bSDaniel Malea   return false;
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;
131b9c1b51eSKate Stone     s.Address(
132b9c1b51eSKate Stone         m_thread.GetRegisterContext()->GetPC(),
1331ac04c30SGreg Clayton         m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
13430fdc8d8SChris Lattner     log->Printf("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
138*05097246SAdrian Prantl   // then we should stop. When stepping out we only stop others if we are
139*05097246SAdrian 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
150*05097246SAdrian Prantl     // trampoline.  So if we are in a trampoline we think the frame is older
151*05097246SAdrian Prantl     // because the trampoline confused the backtracer. As below, we step
152*05097246SAdrian Prantl     // through first, and then try to figure out how to get back out again.
1535822173bSJim Ingham 
154b9c1b51eSKate Stone     new_plan_sp =
155b9c1b51eSKate Stone         m_thread.QueueThreadPlanForStepThrough(m_stack_id, false, stop_others);
1565822173bSJim Ingham 
1574d56e9c1SJim Ingham     if (new_plan_sp && log)
158b9c1b51eSKate Stone       log->Printf(
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
162*05097246SAdrian 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)) {
174b9c1b51eSKate Stone         new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
175b9c1b51eSKate Stone             false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
176fd4cea53SJason Molenda             true);
1774b86728bSDaniel Malea         break;
178b9c1b51eSKate Stone       } else {
179b9c1b51eSKate Stone         new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
180b9c1b51eSKate Stone                                                              stop_others);
1815beccb22SJim Ingham         // If we found a way through, then we should stop recursing.
1825beccb22SJim Ingham         if (new_plan_sp)
1835beccb22SJim Ingham           break;
184b5c0d1ccSJim Ingham       }
185b5c0d1ccSJim Ingham     }
186b9c1b51eSKate Stone   } else {
187564d8bc2SJim Ingham     // If we're still in the range, keep going.
188b9c1b51eSKate Stone     if (InRange()) {
189564d8bc2SJim Ingham       SetNextBranchBreakpoint();
190564d8bc2SJim Ingham       return false;
191564d8bc2SJim Ingham     }
192564d8bc2SJim Ingham 
193b9c1b51eSKate Stone     if (!InSymbol()) {
194b9c1b51eSKate Stone       // This one is a little tricky.  Sometimes we may be in a stub or
195*05097246SAdrian Prantl       // something similar, in which case we need to get out of there.  But if
196*05097246SAdrian Prantl       // we are in a stub then it's likely going to be hard to get out from
197*05097246SAdrian Prantl       // here.  It is probably easiest to step into the stub, and then it will
198*05097246SAdrian Prantl       // be straight-forward to step out.
199b9c1b51eSKate Stone       new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
200b9c1b51eSKate Stone                                                            stop_others);
201b9c1b51eSKate Stone     } else {
202*05097246SAdrian Prantl       // The current clang (at least through 424) doesn't always get the
203*05097246SAdrian Prantl       // address range for the DW_TAG_inlined_subroutines right, so that when
204*05097246SAdrian Prantl       // you leave the inlined range the line table says you are still in the
205*05097246SAdrian Prantl       // source file of the inlining function.  This is bad, because now you
206*05097246SAdrian Prantl       // are missing the stack frame for the function containing the inlining,
207*05097246SAdrian Prantl       // and if you sensibly do "finish" to get out of this function you will
208*05097246SAdrian Prantl       // instead exit the containing function. To work around this, we check
209*05097246SAdrian Prantl       // whether we are still in the source file we started in, and if not
210*05097246SAdrian Prantl       // assume it is an error, and push a plan to get us out of this line and
211*05097246SAdrian Prantl       // back to the containing file.
2123bfa753fSJim Ingham 
213b9c1b51eSKate Stone       if (m_addr_context.line_entry.IsValid()) {
2143bfa753fSJim Ingham         SymbolContext sc;
215b57e4a1bSJason Molenda         StackFrameSP frame_sp = m_thread.GetStackFrameAtIndex(0);
2163bfa753fSJim Ingham         sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
217b9c1b51eSKate Stone         if (sc.line_entry.IsValid()) {
218b9c1b51eSKate Stone           if (sc.line_entry.original_file !=
219b9c1b51eSKate Stone                   m_addr_context.line_entry.original_file &&
220b9c1b51eSKate Stone               sc.comp_unit == m_addr_context.comp_unit &&
221b9c1b51eSKate Stone               sc.function == m_addr_context.function) {
22258ef391fSBruce Mitchener             // Okay, find the next occurrence of this file in the line table:
2233bfa753fSJim Ingham             LineTable *line_table = m_addr_context.comp_unit->GetLineTable();
224b9c1b51eSKate Stone             if (line_table) {
2253bfa753fSJim Ingham               Address cur_address = frame_sp->GetFrameCodeAddress();
2263bfa753fSJim Ingham               uint32_t entry_idx;
2273bfa753fSJim Ingham               LineEntry line_entry;
228b9c1b51eSKate Stone               if (line_table->FindLineEntryByAddress(cur_address, line_entry,
229b9c1b51eSKate Stone                                                      &entry_idx)) {
2303bfa753fSJim Ingham                 LineEntry next_line_entry;
2313bfa753fSJim Ingham                 bool step_past_remaining_inline = false;
232b9c1b51eSKate Stone                 if (entry_idx > 0) {
233b9c1b51eSKate Stone                   // We require the previous line entry and the current line
234*05097246SAdrian Prantl                   // entry come from the same file. The other requirement is
235*05097246SAdrian Prantl                   // that the previous line table entry be part of an inlined
236*05097246SAdrian Prantl                   // block, we don't want to step past cases where people have
237*05097246SAdrian Prantl                   // inlined some code fragment by using #include <source-
238*05097246SAdrian Prantl                   // fragment.c> directly.
2393bfa753fSJim Ingham                   LineEntry prev_line_entry;
240b9c1b51eSKate Stone                   if (line_table->GetLineEntryAtIndex(entry_idx - 1,
241b9c1b51eSKate Stone                                                       prev_line_entry) &&
242b9c1b51eSKate Stone                       prev_line_entry.original_file ==
243b9c1b51eSKate Stone                           line_entry.original_file) {
2443bfa753fSJim Ingham                     SymbolContext prev_sc;
245b9c1b51eSKate Stone                     Address prev_address =
246b9c1b51eSKate Stone                         prev_line_entry.range.GetBaseAddress();
2473bfa753fSJim Ingham                     prev_address.CalculateSymbolContext(&prev_sc);
248b9c1b51eSKate Stone                     if (prev_sc.block) {
249b9c1b51eSKate Stone                       Block *inlined_block =
250b9c1b51eSKate Stone                           prev_sc.block->GetContainingInlinedBlock();
251b9c1b51eSKate Stone                       if (inlined_block) {
2523bfa753fSJim Ingham                         AddressRange inline_range;
253b9c1b51eSKate Stone                         inlined_block->GetRangeContainingAddress(prev_address,
254b9c1b51eSKate Stone                                                                  inline_range);
255b9c1b51eSKate Stone                         if (!inline_range.ContainsFileAddress(cur_address)) {
2563bfa753fSJim Ingham 
2573bfa753fSJim Ingham                           step_past_remaining_inline = true;
2583bfa753fSJim Ingham                         }
2593bfa753fSJim Ingham                       }
2603bfa753fSJim Ingham                     }
2613bfa753fSJim Ingham                   }
2623bfa753fSJim Ingham                 }
2633bfa753fSJim Ingham 
264b9c1b51eSKate Stone                 if (step_past_remaining_inline) {
2653bfa753fSJim Ingham                   uint32_t look_ahead_step = 1;
266b9c1b51eSKate Stone                   while (line_table->GetLineEntryAtIndex(
267b9c1b51eSKate Stone                       entry_idx + look_ahead_step, next_line_entry)) {
268b9c1b51eSKate Stone                     // Make sure we haven't wandered out of the function we
269b9c1b51eSKate Stone                     // started from...
270b9c1b51eSKate Stone                     Address next_line_address =
271b9c1b51eSKate Stone                         next_line_entry.range.GetBaseAddress();
272b9c1b51eSKate Stone                     Function *next_line_function =
273b9c1b51eSKate Stone                         next_line_address.CalculateSymbolContextFunction();
2743bfa753fSJim Ingham                     if (next_line_function != m_addr_context.function)
2753bfa753fSJim Ingham                       break;
2763bfa753fSJim Ingham 
277b9c1b51eSKate Stone                     if (next_line_entry.original_file ==
278b9c1b51eSKate Stone                         m_addr_context.line_entry.original_file) {
2793bfa753fSJim Ingham                       const bool abort_other_plans = false;
28055828080SJim Ingham                       const RunMode stop_other_threads = RunMode::eAllThreads;
281b9c1b51eSKate Stone                       lldb::addr_t cur_pc = m_thread.GetStackFrameAtIndex(0)
282b9c1b51eSKate Stone                                                 ->GetRegisterContext()
283b9c1b51eSKate Stone                                                 ->GetPC();
284b9c1b51eSKate Stone                       AddressRange step_range(
285b9c1b51eSKate Stone                           cur_pc,
286b9c1b51eSKate Stone                           next_line_address.GetLoadAddress(&GetTarget()) -
287b9c1b51eSKate Stone                               cur_pc);
28855828080SJim Ingham 
289b9c1b51eSKate Stone                       new_plan_sp = m_thread.QueueThreadPlanForStepOverRange(
290b9c1b51eSKate Stone                           abort_other_plans, step_range, sc,
2913bfa753fSJim Ingham                           stop_other_threads);
2923bfa753fSJim Ingham                       break;
2933bfa753fSJim Ingham                     }
2943bfa753fSJim Ingham                     look_ahead_step++;
2953bfa753fSJim Ingham                   }
2963bfa753fSJim Ingham                 }
2973bfa753fSJim Ingham               }
2983bfa753fSJim Ingham             }
2993bfa753fSJim Ingham           }
3003bfa753fSJim Ingham         }
3013bfa753fSJim Ingham       }
3023bfa753fSJim Ingham     }
303564d8bc2SJim Ingham   }
304564d8bc2SJim Ingham 
305b9c1b51eSKate Stone   // If we get to this point, we're not going to use a previously set "next
306b9c1b51eSKate Stone   // branch" breakpoint, so delete it:
307564d8bc2SJim Ingham   ClearNextBranchBreakpoint();
30830fdc8d8SChris Lattner 
309b9c1b51eSKate Stone   // If we haven't figured out something to do yet, then ask the ShouldStopHere
310b9c1b51eSKate Stone   // callback:
311b9c1b51eSKate Stone   if (!new_plan_sp) {
3124b4b2478SJim Ingham     new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
3134b4b2478SJim Ingham   }
3144b4b2478SJim Ingham 
3154d56e9c1SJim Ingham   if (!new_plan_sp)
31630fdc8d8SChris Lattner     m_no_more_plans = true;
317b9c1b51eSKate Stone   else {
3182bdbfd50SJim Ingham     // Any new plan will be an implementation plan, so mark it private:
3192bdbfd50SJim Ingham     new_plan_sp->SetPrivate(true);
32030fdc8d8SChris Lattner     m_no_more_plans = false;
3212bdbfd50SJim Ingham   }
32230fdc8d8SChris Lattner 
323b9c1b51eSKate Stone   if (!new_plan_sp) {
324b9c1b51eSKate Stone     // For efficiencies sake, we know we're done here so we don't have to do
325*05097246SAdrian Prantl     // this calculation again in MischiefManaged.
32630fdc8d8SChris Lattner     SetPlanComplete();
32730fdc8d8SChris Lattner     return true;
328b9c1b51eSKate Stone   } else
32930fdc8d8SChris Lattner     return false;
33030fdc8d8SChris Lattner }
331fbbfe6ecSJim Ingham 
332b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoPlanExplainsStop(Event *event_ptr) {
333*05097246SAdrian Prantl   // For crashes, breakpoint hits, signals, etc, let the base plan (or some
334*05097246SAdrian Prantl   // plan above us) handle the stop.  That way the user can see the stop, step
335*05097246SAdrian Prantl   // around, and then when they are done, continue and have their step
336*05097246SAdrian Prantl   // complete.  The exception is if we've hit our "run to next branch"
337*05097246SAdrian Prantl   // breakpoint. Note, unlike the step in range plan, we don't mark ourselves
338*05097246SAdrian Prantl   // complete if we hit an unexplained breakpoint/crash.
339fbbfe6ecSJim Ingham 
3405160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
34160c4118cSJim Ingham   StopInfoSP stop_info_sp = GetPrivateStopInfo();
342221d51cfSJim Ingham   bool return_value;
343221d51cfSJim Ingham 
344b9c1b51eSKate Stone   if (stop_info_sp) {
345fbbfe6ecSJim Ingham     StopReason reason = stop_info_sp->GetStopReason();
346fbbfe6ecSJim Ingham 
347b9c1b51eSKate Stone     if (reason == eStopReasonTrace) {
348221d51cfSJim Ingham       return_value = true;
349b9c1b51eSKate Stone     } else if (reason == eStopReasonBreakpoint) {
350e65b2cf2SEugene Zelenko       return_value = NextRangeBreakpointExplainsStop(stop_info_sp);
351b9c1b51eSKate Stone     } else {
352fbbfe6ecSJim Ingham       if (log)
353b9c1b51eSKate Stone         log->PutCString("ThreadPlanStepInRange got asked if it explains the "
354b9c1b51eSKate Stone                         "stop for some reason other than step.");
355221d51cfSJim Ingham       return_value = false;
356fbbfe6ecSJim Ingham     }
357b9c1b51eSKate Stone   } else
358221d51cfSJim Ingham     return_value = true;
359221d51cfSJim Ingham 
360221d51cfSJim Ingham   return return_value;
361fbbfe6ecSJim Ingham }
362513c6bb8SJim Ingham 
363b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoWillResume(lldb::StateType resume_state,
364b9c1b51eSKate Stone                                            bool current_plan) {
365b9c1b51eSKate Stone   if (resume_state != eStateSuspended && m_first_resume) {
366513c6bb8SJim Ingham     m_first_resume = false;
367b9c1b51eSKate Stone     if (resume_state == eStateStepping && current_plan) {
368b9c1b51eSKate Stone       // See if we are about to step over an inlined call in the middle of the
369*05097246SAdrian Prantl       // inlined stack, if so figure out its extents and reset our range to
370*05097246SAdrian Prantl       // step over that.
371513c6bb8SJim Ingham       bool in_inlined_stack = m_thread.DecrementCurrentInlinedDepth();
372b9c1b51eSKate Stone       if (in_inlined_stack) {
3735160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
374513c6bb8SJim Ingham         if (log)
375b9c1b51eSKate Stone           log->Printf("ThreadPlanStepInRange::DoWillResume: adjusting range to "
376b9c1b51eSKate Stone                       "the frame at inlined depth %d.",
377513c6bb8SJim Ingham                       m_thread.GetCurrentInlinedDepth());
378b57e4a1bSJason Molenda         StackFrameSP stack_sp = m_thread.GetStackFrameAtIndex(0);
379b9c1b51eSKate Stone         if (stack_sp) {
380513c6bb8SJim Ingham           Block *frame_block = stack_sp->GetFrameBlock();
381513c6bb8SJim Ingham           lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
382513c6bb8SJim Ingham           AddressRange my_range;
383b9c1b51eSKate Stone           if (frame_block->GetRangeContainingLoadAddress(
384b9c1b51eSKate Stone                   curr_pc, m_thread.GetProcess()->GetTarget(), my_range)) {
385513c6bb8SJim Ingham             m_address_ranges.clear();
386513c6bb8SJim Ingham             m_address_ranges.push_back(my_range);
387b9c1b51eSKate Stone             if (log) {
388513c6bb8SJim Ingham               StreamString s;
389b9c1b51eSKate Stone               const InlineFunctionInfo *inline_info =
390b9c1b51eSKate Stone                   frame_block->GetInlinedFunctionInfo();
391513c6bb8SJim Ingham               const char *name;
392513c6bb8SJim Ingham               if (inline_info)
393b9c1b51eSKate Stone                 name =
394b9c1b51eSKate Stone                     inline_info
395b9c1b51eSKate Stone                         ->GetName(frame_block->CalculateSymbolContextFunction()
396b9c1b51eSKate Stone                                       ->GetLanguage())
397b9c1b51eSKate Stone                         .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