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"
1530fdc8d8SChris Lattner #include "lldb/Core/Log.h"
1630fdc8d8SChris Lattner #include "lldb/Core/Stream.h"
17513c6bb8SJim Ingham #include "lldb/Symbol/Block.h"
183bfa753fSJim Ingham #include "lldb/Symbol/CompileUnit.h"
19513c6bb8SJim Ingham #include "lldb/Symbol/Function.h"
203bfa753fSJim Ingham #include "lldb/Symbol/LineTable.h"
2130fdc8d8SChris Lattner #include "lldb/Target/Process.h"
2230fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
23514487e8SGreg Clayton #include "lldb/Target/Target.h"
2430fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2530fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepOut.h"
2630fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepThrough.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
35b9c1b51eSKate Stone // into
3630fdc8d8SChris Lattner // based on the value of \a type.
3730fdc8d8SChris Lattner //----------------------------------------------------------------------
3830fdc8d8SChris Lattner 
39b9c1b51eSKate Stone ThreadPlanStepOverRange::ThreadPlanStepOverRange(
40b9c1b51eSKate Stone     Thread &thread, const AddressRange &range,
41b9c1b51eSKate Stone     const SymbolContext &addr_context, lldb::RunMode stop_others,
42b9c1b51eSKate Stone     LazyBool step_out_avoids_code_without_debug_info)
43b9c1b51eSKate Stone     : ThreadPlanStepRange(ThreadPlan::eKindStepOverRange,
44b9c1b51eSKate Stone                           "Step range stepping over", thread, range,
45b9c1b51eSKate Stone                           addr_context, stop_others),
46b9c1b51eSKate Stone       ThreadPlanShouldStopHere(this), m_first_resume(true) {
474b4b2478SJim Ingham   SetFlagsToDefault();
484b4b2478SJim Ingham   SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
4930fdc8d8SChris Lattner }
5030fdc8d8SChris Lattner 
51e65b2cf2SEugene Zelenko ThreadPlanStepOverRange::~ThreadPlanStepOverRange() = default;
5230fdc8d8SChris Lattner 
53b9c1b51eSKate Stone void ThreadPlanStepOverRange::GetDescription(Stream *s,
54b9c1b51eSKate Stone                                              lldb::DescriptionLevel level) {
55b9c1b51eSKate Stone   if (level == lldb::eDescriptionLevelBrief) {
562bdbfd50SJim Ingham     s->Printf("step over");
572bdbfd50SJim Ingham     return;
582bdbfd50SJim Ingham   }
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 
722bdbfd50SJim Ingham   s->PutChar('.');
7330fdc8d8SChris Lattner }
7430fdc8d8SChris Lattner 
75b9c1b51eSKate Stone void ThreadPlanStepOverRange::SetupAvoidNoDebug(
76b9c1b51eSKate Stone     LazyBool step_out_avoids_code_without_debug_info) {
774b4b2478SJim Ingham   bool avoid_nodebug = true;
78b9c1b51eSKate Stone   switch (step_out_avoids_code_without_debug_info) {
794b4b2478SJim Ingham   case eLazyBoolYes:
804b4b2478SJim Ingham     avoid_nodebug = true;
814b4b2478SJim Ingham     break;
824b4b2478SJim Ingham   case eLazyBoolNo:
834b4b2478SJim Ingham     avoid_nodebug = false;
844b4b2478SJim Ingham     break;
854b4b2478SJim Ingham   case eLazyBoolCalculate:
864b4b2478SJim Ingham     avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
874b4b2478SJim Ingham     break;
884b4b2478SJim Ingham   }
894b4b2478SJim Ingham   if (avoid_nodebug)
904b4b2478SJim Ingham     GetFlags().Set(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
914b4b2478SJim Ingham   else
924b4b2478SJim Ingham     GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
93b9c1b51eSKate Stone   // Step Over plans should always avoid no-debug on step in.  Seems like you
94b9c1b51eSKate Stone   // shouldn't
95b9c1b51eSKate Stone   // have to say this, but a tail call looks more like a step in that a step
96b9c1b51eSKate Stone   // out, so
97862d1bbdSJim Ingham   // 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) {
1034b86728bSDaniel Malea   // Match as much as is specified in the m_addr_context:
104b9c1b51eSKate Stone   // This is a fairly loose sanity check.  Note, sometimes the target doesn't
105b9c1b51eSKate Stone   // get filled
106b9c1b51eSKate Stone   // in so I left out the target check.  And sometimes the module comes in as
107b9c1b51eSKate Stone   // the .o file from the
1084b86728bSDaniel Malea   // inlined range, so I left that out too...
109b9c1b51eSKate Stone   if (m_addr_context.comp_unit) {
110b9c1b51eSKate Stone     if (m_addr_context.comp_unit == context.comp_unit) {
111b9c1b51eSKate Stone       if (m_addr_context.function &&
112b9c1b51eSKate Stone           m_addr_context.function == context.function) {
113b9c1b51eSKate Stone         // It is okay to return to a different block of a straight function, we
114b9c1b51eSKate Stone         // only have to
1157766c4a8SJim Ingham         // be more careful if returning from one inlined block to another.
116b9c1b51eSKate Stone         if (m_addr_context.block->GetInlinedFunctionInfo() == nullptr &&
117b9c1b51eSKate Stone             context.block->GetInlinedFunctionInfo() == nullptr)
1187766c4a8SJim Ingham           return true;
1197766c4a8SJim Ingham 
1204b86728bSDaniel Malea         if (m_addr_context.block && m_addr_context.block == context.block)
1214b86728bSDaniel Malea           return true;
1224b86728bSDaniel Malea       }
1234b86728bSDaniel Malea     }
124b9c1b51eSKate Stone   } else if (m_addr_context.symbol && m_addr_context.symbol == context.symbol) {
1254b86728bSDaniel Malea     return true;
1264b86728bSDaniel Malea   }
1274b86728bSDaniel Malea   return false;
1284b86728bSDaniel Malea }
1294b86728bSDaniel Malea 
130b9c1b51eSKate Stone bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
1315160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
13230fdc8d8SChris Lattner 
133b9c1b51eSKate Stone   if (log) {
13430fdc8d8SChris Lattner     StreamString s;
135b9c1b51eSKate Stone     s.Address(
136b9c1b51eSKate Stone         m_thread.GetRegisterContext()->GetPC(),
1371ac04c30SGreg Clayton         m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
13830fdc8d8SChris Lattner     log->Printf("ThreadPlanStepOverRange reached %s.", s.GetData());
13930fdc8d8SChris Lattner   }
14030fdc8d8SChris Lattner 
14130fdc8d8SChris Lattner   // If we're out of the range but in the same frame or in our caller's frame
14230fdc8d8SChris Lattner   // then we should stop.
1434a58e968SJim Ingham   // When stepping out we only stop others if we are forcing running one thread.
144e65b2cf2SEugene Zelenko   bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
1454d56e9c1SJim Ingham   ThreadPlanSP new_plan_sp;
146b5c0d1ccSJim Ingham   FrameComparison frame_order = CompareCurrentFrameToStartFrame();
147b5c0d1ccSJim Ingham 
148b9c1b51eSKate Stone   if (frame_order == eFrameCompareOlder) {
1495822173bSJim Ingham     // If we're in an older frame then we should stop.
1505822173bSJim Ingham     //
151b9c1b51eSKate Stone     // A caveat to this is if we think the frame is older but we're actually in
152b9c1b51eSKate Stone     // a trampoline.
153b9c1b51eSKate Stone     // I'm going to make the assumption that you wouldn't RETURN to a
154b9c1b51eSKate Stone     // trampoline.  So if we are
155b9c1b51eSKate Stone     // in a trampoline we think the frame is older because the trampoline
156b9c1b51eSKate Stone     // confused the backtracer.
157b9c1b51eSKate Stone     // As below, we step through first, and then try to figure out how to get
158b9c1b51eSKate Stone     // back out again.
1595822173bSJim Ingham 
160b9c1b51eSKate Stone     new_plan_sp =
161b9c1b51eSKate Stone         m_thread.QueueThreadPlanForStepThrough(m_stack_id, false, stop_others);
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
168b9c1b51eSKate Stone     // if the
169b5c0d1ccSJim Ingham     // start function really is our start function...
170b9c1b51eSKate Stone     for (uint32_t i = 1;; ++i) {
171b57e4a1bSJason Molenda       StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(i);
1724b86728bSDaniel Malea       if (!older_frame_sp) {
173b9c1b51eSKate Stone         // We can't unwind the next frame we should just get out of here &
174b9c1b51eSKate Stone         // stop...
1754b86728bSDaniel Malea         break;
1764b86728bSDaniel Malea       }
1774b86728bSDaniel Malea 
178b9c1b51eSKate Stone       const SymbolContext &older_context =
179b9c1b51eSKate Stone           older_frame_sp->GetSymbolContext(eSymbolContextEverything);
180b9c1b51eSKate Stone       if (IsEquivalentContext(older_context)) {
181b9c1b51eSKate Stone         new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
182b9c1b51eSKate Stone             false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
183fd4cea53SJason Molenda             true);
1844b86728bSDaniel Malea         break;
185b9c1b51eSKate Stone       } else {
186b9c1b51eSKate Stone         new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
187b9c1b51eSKate Stone                                                              stop_others);
1885beccb22SJim Ingham         // If we found a way through, then we should stop recursing.
1895beccb22SJim Ingham         if (new_plan_sp)
1905beccb22SJim Ingham           break;
191b5c0d1ccSJim Ingham       }
192b5c0d1ccSJim Ingham     }
193b9c1b51eSKate Stone   } else {
194564d8bc2SJim Ingham     // If we're still in the range, keep going.
195b9c1b51eSKate Stone     if (InRange()) {
196564d8bc2SJim Ingham       SetNextBranchBreakpoint();
197564d8bc2SJim Ingham       return false;
198564d8bc2SJim Ingham     }
199564d8bc2SJim Ingham 
200b9c1b51eSKate Stone     if (!InSymbol()) {
201b9c1b51eSKate Stone       // This one is a little tricky.  Sometimes we may be in a stub or
202b9c1b51eSKate Stone       // something similar,
203b9c1b51eSKate Stone       // in which case we need to get out of there.  But if we are in a stub
204b9c1b51eSKate Stone       // then it's
205b9c1b51eSKate Stone       // likely going to be hard to get out from here.  It is probably easiest
206b9c1b51eSKate Stone       // to step into the
20730fdc8d8SChris Lattner       // stub, and then it will be straight-forward to step out.
208b9c1b51eSKate Stone       new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
209b9c1b51eSKate Stone                                                            stop_others);
210b9c1b51eSKate Stone     } else {
211b9c1b51eSKate Stone       // The current clang (at least through 424) doesn't always get the address
212b9c1b51eSKate Stone       // range for the
213b9c1b51eSKate Stone       // DW_TAG_inlined_subroutines right, so that when you leave the inlined
214b9c1b51eSKate Stone       // range the line table says
215b9c1b51eSKate Stone       // you are still in the source file of the inlining function.  This is
216b9c1b51eSKate Stone       // bad, because now you are missing
217b9c1b51eSKate Stone       // the stack frame for the function containing the inlining, and if you
218b9c1b51eSKate Stone       // sensibly do "finish" to get
2193bfa753fSJim Ingham       // out of this function you will instead exit the containing function.
220b9c1b51eSKate Stone       // To work around this, we check whether we are still in the source file
221b9c1b51eSKate Stone       // we started in, and if not assume
222b9c1b51eSKate Stone       // it is an error, and push a plan to get us out of this line and back to
223b9c1b51eSKate Stone       // the containing file.
2243bfa753fSJim Ingham 
225b9c1b51eSKate Stone       if (m_addr_context.line_entry.IsValid()) {
2263bfa753fSJim Ingham         SymbolContext sc;
227b57e4a1bSJason Molenda         StackFrameSP frame_sp = m_thread.GetStackFrameAtIndex(0);
2283bfa753fSJim Ingham         sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
229b9c1b51eSKate Stone         if (sc.line_entry.IsValid()) {
230b9c1b51eSKate Stone           if (sc.line_entry.original_file !=
231b9c1b51eSKate Stone                   m_addr_context.line_entry.original_file &&
232b9c1b51eSKate Stone               sc.comp_unit == m_addr_context.comp_unit &&
233b9c1b51eSKate Stone               sc.function == m_addr_context.function) {
23458ef391fSBruce Mitchener             // Okay, find the next occurrence of this file in the line table:
2353bfa753fSJim Ingham             LineTable *line_table = m_addr_context.comp_unit->GetLineTable();
236b9c1b51eSKate Stone             if (line_table) {
2373bfa753fSJim Ingham               Address cur_address = frame_sp->GetFrameCodeAddress();
2383bfa753fSJim Ingham               uint32_t entry_idx;
2393bfa753fSJim Ingham               LineEntry line_entry;
240b9c1b51eSKate Stone               if (line_table->FindLineEntryByAddress(cur_address, line_entry,
241b9c1b51eSKate Stone                                                      &entry_idx)) {
2423bfa753fSJim Ingham                 LineEntry next_line_entry;
2433bfa753fSJim Ingham                 bool step_past_remaining_inline = false;
244b9c1b51eSKate Stone                 if (entry_idx > 0) {
245b9c1b51eSKate Stone                   // We require the previous line entry and the current line
246b9c1b51eSKate Stone                   // entry come
2473bfa753fSJim Ingham                   // from the same file.
248b9c1b51eSKate Stone                   // The other requirement is that the previous line table entry
249b9c1b51eSKate Stone                   // be part of an
250b9c1b51eSKate Stone                   // inlined block, we don't want to step past cases where
251b9c1b51eSKate Stone                   // people have inlined
252b9c1b51eSKate Stone                   // some code fragment by using #include <source-fragment.c>
253b9c1b51eSKate Stone                   // directly.
2543bfa753fSJim Ingham                   LineEntry prev_line_entry;
255b9c1b51eSKate Stone                   if (line_table->GetLineEntryAtIndex(entry_idx - 1,
256b9c1b51eSKate Stone                                                       prev_line_entry) &&
257b9c1b51eSKate Stone                       prev_line_entry.original_file ==
258b9c1b51eSKate Stone                           line_entry.original_file) {
2593bfa753fSJim Ingham                     SymbolContext prev_sc;
260b9c1b51eSKate Stone                     Address prev_address =
261b9c1b51eSKate Stone                         prev_line_entry.range.GetBaseAddress();
2623bfa753fSJim Ingham                     prev_address.CalculateSymbolContext(&prev_sc);
263b9c1b51eSKate Stone                     if (prev_sc.block) {
264b9c1b51eSKate Stone                       Block *inlined_block =
265b9c1b51eSKate Stone                           prev_sc.block->GetContainingInlinedBlock();
266b9c1b51eSKate Stone                       if (inlined_block) {
2673bfa753fSJim Ingham                         AddressRange inline_range;
268b9c1b51eSKate Stone                         inlined_block->GetRangeContainingAddress(prev_address,
269b9c1b51eSKate Stone                                                                  inline_range);
270b9c1b51eSKate Stone                         if (!inline_range.ContainsFileAddress(cur_address)) {
2713bfa753fSJim Ingham 
2723bfa753fSJim Ingham                           step_past_remaining_inline = true;
2733bfa753fSJim Ingham                         }
2743bfa753fSJim Ingham                       }
2753bfa753fSJim Ingham                     }
2763bfa753fSJim Ingham                   }
2773bfa753fSJim Ingham                 }
2783bfa753fSJim Ingham 
279b9c1b51eSKate Stone                 if (step_past_remaining_inline) {
2803bfa753fSJim Ingham                   uint32_t look_ahead_step = 1;
281b9c1b51eSKate Stone                   while (line_table->GetLineEntryAtIndex(
282b9c1b51eSKate Stone                       entry_idx + look_ahead_step, next_line_entry)) {
283b9c1b51eSKate Stone                     // Make sure we haven't wandered out of the function we
284b9c1b51eSKate Stone                     // started from...
285b9c1b51eSKate Stone                     Address next_line_address =
286b9c1b51eSKate Stone                         next_line_entry.range.GetBaseAddress();
287b9c1b51eSKate Stone                     Function *next_line_function =
288b9c1b51eSKate Stone                         next_line_address.CalculateSymbolContextFunction();
2893bfa753fSJim Ingham                     if (next_line_function != m_addr_context.function)
2903bfa753fSJim Ingham                       break;
2913bfa753fSJim Ingham 
292b9c1b51eSKate Stone                     if (next_line_entry.original_file ==
293b9c1b51eSKate Stone                         m_addr_context.line_entry.original_file) {
2943bfa753fSJim Ingham                       const bool abort_other_plans = false;
29555828080SJim Ingham                       const RunMode stop_other_threads = RunMode::eAllThreads;
296b9c1b51eSKate Stone                       lldb::addr_t cur_pc = m_thread.GetStackFrameAtIndex(0)
297b9c1b51eSKate Stone                                                 ->GetRegisterContext()
298b9c1b51eSKate Stone                                                 ->GetPC();
299b9c1b51eSKate Stone                       AddressRange step_range(
300b9c1b51eSKate Stone                           cur_pc,
301b9c1b51eSKate Stone                           next_line_address.GetLoadAddress(&GetTarget()) -
302b9c1b51eSKate Stone                               cur_pc);
30355828080SJim Ingham 
304b9c1b51eSKate Stone                       new_plan_sp = m_thread.QueueThreadPlanForStepOverRange(
305b9c1b51eSKate Stone                           abort_other_plans, step_range, sc,
3063bfa753fSJim Ingham                           stop_other_threads);
3073bfa753fSJim Ingham                       break;
3083bfa753fSJim Ingham                     }
3093bfa753fSJim Ingham                     look_ahead_step++;
3103bfa753fSJim Ingham                   }
3113bfa753fSJim Ingham                 }
3123bfa753fSJim Ingham               }
3133bfa753fSJim Ingham             }
3143bfa753fSJim Ingham           }
3153bfa753fSJim Ingham         }
3163bfa753fSJim Ingham       }
3173bfa753fSJim Ingham     }
318564d8bc2SJim Ingham   }
319564d8bc2SJim Ingham 
320b9c1b51eSKate Stone   // If we get to this point, we're not going to use a previously set "next
321b9c1b51eSKate Stone   // branch" breakpoint, so delete it:
322564d8bc2SJim Ingham   ClearNextBranchBreakpoint();
32330fdc8d8SChris Lattner 
324b9c1b51eSKate Stone   // If we haven't figured out something to do yet, then ask the ShouldStopHere
325b9c1b51eSKate Stone   // callback:
326b9c1b51eSKate Stone   if (!new_plan_sp) {
3274b4b2478SJim Ingham     new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
3284b4b2478SJim Ingham   }
3294b4b2478SJim Ingham 
3304d56e9c1SJim Ingham   if (!new_plan_sp)
33130fdc8d8SChris Lattner     m_no_more_plans = true;
332b9c1b51eSKate Stone   else {
3332bdbfd50SJim Ingham     // Any new plan will be an implementation plan, so mark it private:
3342bdbfd50SJim Ingham     new_plan_sp->SetPrivate(true);
33530fdc8d8SChris Lattner     m_no_more_plans = false;
3362bdbfd50SJim Ingham   }
33730fdc8d8SChris Lattner 
338b9c1b51eSKate Stone   if (!new_plan_sp) {
339b9c1b51eSKate Stone     // For efficiencies sake, we know we're done here so we don't have to do
340b9c1b51eSKate Stone     // this
34130fdc8d8SChris Lattner     // calculation again in MischiefManaged.
34230fdc8d8SChris Lattner     SetPlanComplete();
34330fdc8d8SChris Lattner     return true;
344b9c1b51eSKate Stone   } else
34530fdc8d8SChris Lattner     return false;
34630fdc8d8SChris Lattner }
347fbbfe6ecSJim Ingham 
348b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoPlanExplainsStop(Event *event_ptr) {
349b9c1b51eSKate Stone   // For crashes, breakpoint hits, signals, etc, let the base plan (or some plan
350b9c1b51eSKate Stone   // above us)
351b9c1b51eSKate Stone   // handle the stop.  That way the user can see the stop, step around, and then
352b9c1b51eSKate Stone   // when they
353b9c1b51eSKate Stone   // are done, continue and have their step complete.  The exception is if we've
354b9c1b51eSKate Stone   // hit our
355fbbfe6ecSJim Ingham   // "run to next branch" breakpoint.
356b9c1b51eSKate Stone   // Note, unlike the step in range plan, we don't mark ourselves complete if we
357b9c1b51eSKate Stone   // hit an
358fbbfe6ecSJim Ingham   // unexplained breakpoint/crash.
359fbbfe6ecSJim Ingham 
3605160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
36160c4118cSJim Ingham   StopInfoSP stop_info_sp = GetPrivateStopInfo();
362221d51cfSJim Ingham   bool return_value;
363221d51cfSJim Ingham 
364b9c1b51eSKate Stone   if (stop_info_sp) {
365fbbfe6ecSJim Ingham     StopReason reason = stop_info_sp->GetStopReason();
366fbbfe6ecSJim Ingham 
367b9c1b51eSKate Stone     if (reason == eStopReasonTrace) {
368221d51cfSJim Ingham       return_value = true;
369b9c1b51eSKate Stone     } else if (reason == eStopReasonBreakpoint) {
370e65b2cf2SEugene Zelenko       return_value = NextRangeBreakpointExplainsStop(stop_info_sp);
371b9c1b51eSKate Stone     } else {
372fbbfe6ecSJim Ingham       if (log)
373b9c1b51eSKate Stone         log->PutCString("ThreadPlanStepInRange got asked if it explains the "
374b9c1b51eSKate Stone                         "stop for some reason other than step.");
375221d51cfSJim Ingham       return_value = false;
376fbbfe6ecSJim Ingham     }
377b9c1b51eSKate Stone   } else
378221d51cfSJim Ingham     return_value = true;
379221d51cfSJim Ingham 
380221d51cfSJim Ingham   return return_value;
381fbbfe6ecSJim Ingham }
382513c6bb8SJim Ingham 
383b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoWillResume(lldb::StateType resume_state,
384b9c1b51eSKate Stone                                            bool current_plan) {
385b9c1b51eSKate Stone   if (resume_state != eStateSuspended && m_first_resume) {
386513c6bb8SJim Ingham     m_first_resume = false;
387b9c1b51eSKate Stone     if (resume_state == eStateStepping && current_plan) {
388b9c1b51eSKate Stone       // See if we are about to step over an inlined call in the middle of the
389b9c1b51eSKate Stone       // inlined stack, if so figure
390513c6bb8SJim Ingham       // out its extents and reset our range to step over that.
391513c6bb8SJim Ingham       bool in_inlined_stack = m_thread.DecrementCurrentInlinedDepth();
392b9c1b51eSKate Stone       if (in_inlined_stack) {
3935160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
394513c6bb8SJim Ingham         if (log)
395b9c1b51eSKate Stone           log->Printf("ThreadPlanStepInRange::DoWillResume: adjusting range to "
396b9c1b51eSKate Stone                       "the frame at inlined depth %d.",
397513c6bb8SJim Ingham                       m_thread.GetCurrentInlinedDepth());
398b57e4a1bSJason Molenda         StackFrameSP stack_sp = m_thread.GetStackFrameAtIndex(0);
399b9c1b51eSKate Stone         if (stack_sp) {
400513c6bb8SJim Ingham           Block *frame_block = stack_sp->GetFrameBlock();
401513c6bb8SJim Ingham           lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
402513c6bb8SJim Ingham           AddressRange my_range;
403b9c1b51eSKate Stone           if (frame_block->GetRangeContainingLoadAddress(
404b9c1b51eSKate Stone                   curr_pc, m_thread.GetProcess()->GetTarget(), my_range)) {
405513c6bb8SJim Ingham             m_address_ranges.clear();
406513c6bb8SJim Ingham             m_address_ranges.push_back(my_range);
407b9c1b51eSKate Stone             if (log) {
408513c6bb8SJim Ingham               StreamString s;
409b9c1b51eSKate Stone               const InlineFunctionInfo *inline_info =
410b9c1b51eSKate Stone                   frame_block->GetInlinedFunctionInfo();
411513c6bb8SJim Ingham               const char *name;
412513c6bb8SJim Ingham               if (inline_info)
413b9c1b51eSKate Stone                 name =
414b9c1b51eSKate Stone                     inline_info
415b9c1b51eSKate Stone                         ->GetName(frame_block->CalculateSymbolContextFunction()
416b9c1b51eSKate Stone                                       ->GetLanguage())
417b9c1b51eSKate Stone                         .AsCString();
418513c6bb8SJim Ingham               else
419513c6bb8SJim Ingham                 name = "<unknown-notinlined>";
420513c6bb8SJim Ingham 
421b9c1b51eSKate Stone               s.Printf(
422b9c1b51eSKate Stone                   "Stepping over inlined function \"%s\" in inlined stack: ",
423b9c1b51eSKate Stone                   name);
424513c6bb8SJim Ingham               DumpRanges(&s);
425*c156427dSZachary Turner               log->PutString(s.GetString());
426513c6bb8SJim Ingham             }
427513c6bb8SJim Ingham           }
428513c6bb8SJim Ingham         }
429513c6bb8SJim Ingham       }
430513c6bb8SJim Ingham     }
431513c6bb8SJim Ingham   }
432513c6bb8SJim Ingham 
433221d51cfSJim Ingham   return true;
434513c6bb8SJim Ingham }
435