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) {
110*592fa122SSam McCall     if (m_addr_context.comp_unit != context.comp_unit)
111*592fa122SSam McCall       return false;
112*592fa122SSam McCall     if (m_addr_context.function) {
113*592fa122SSam McCall       if (m_addr_context.function != context.function)
114*592fa122SSam McCall         return false;
115b9c1b51eSKate Stone       // It is okay to return to a different block of a straight function, we
116b9c1b51eSKate Stone       // only have to
1177766c4a8SJim Ingham       // be more careful if returning from one inlined block to another.
118b9c1b51eSKate Stone       if (m_addr_context.block->GetInlinedFunctionInfo() == nullptr &&
119b9c1b51eSKate Stone           context.block->GetInlinedFunctionInfo() == nullptr)
1207766c4a8SJim Ingham         return true;
121*592fa122SSam McCall       return m_addr_context.block == context.block;
1224b86728bSDaniel Malea     }
1234b86728bSDaniel Malea   }
124*592fa122SSam McCall   // Fall back to symbol if we have no decision from comp_unit/function/block.
125*592fa122SSam McCall   if (m_addr_context.symbol && m_addr_context.symbol == context.symbol) {
1264b86728bSDaniel Malea     return true;
1274b86728bSDaniel Malea   }
1284b86728bSDaniel Malea   return false;
1294b86728bSDaniel Malea }
1304b86728bSDaniel Malea 
131b9c1b51eSKate Stone bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
1325160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
13330fdc8d8SChris Lattner 
134b9c1b51eSKate Stone   if (log) {
13530fdc8d8SChris Lattner     StreamString s;
136b9c1b51eSKate Stone     s.Address(
137b9c1b51eSKate Stone         m_thread.GetRegisterContext()->GetPC(),
1381ac04c30SGreg Clayton         m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
13930fdc8d8SChris Lattner     log->Printf("ThreadPlanStepOverRange reached %s.", s.GetData());
14030fdc8d8SChris Lattner   }
14130fdc8d8SChris Lattner 
14230fdc8d8SChris Lattner   // If we're out of the range but in the same frame or in our caller's frame
14330fdc8d8SChris Lattner   // then we should stop.
1444a58e968SJim Ingham   // When stepping out we only stop others if we are forcing running one thread.
145e65b2cf2SEugene Zelenko   bool stop_others = (m_stop_others == lldb::eOnlyThisThread);
1464d56e9c1SJim Ingham   ThreadPlanSP new_plan_sp;
147b5c0d1ccSJim Ingham   FrameComparison frame_order = CompareCurrentFrameToStartFrame();
148b5c0d1ccSJim Ingham 
149b9c1b51eSKate Stone   if (frame_order == eFrameCompareOlder) {
1505822173bSJim Ingham     // If we're in an older frame then we should stop.
1515822173bSJim Ingham     //
152b9c1b51eSKate Stone     // A caveat to this is if we think the frame is older but we're actually in
153b9c1b51eSKate Stone     // a trampoline.
154b9c1b51eSKate Stone     // I'm going to make the assumption that you wouldn't RETURN to a
155b9c1b51eSKate Stone     // trampoline.  So if we are
156b9c1b51eSKate Stone     // in a trampoline we think the frame is older because the trampoline
157b9c1b51eSKate Stone     // confused the backtracer.
158b9c1b51eSKate Stone     // As below, we step through first, and then try to figure out how to get
159b9c1b51eSKate Stone     // back out again.
1605822173bSJim Ingham 
161b9c1b51eSKate Stone     new_plan_sp =
162b9c1b51eSKate Stone         m_thread.QueueThreadPlanForStepThrough(m_stack_id, false, stop_others);
1635822173bSJim Ingham 
1644d56e9c1SJim Ingham     if (new_plan_sp && log)
165b9c1b51eSKate Stone       log->Printf(
166b9c1b51eSKate Stone           "Thought I stepped out, but in fact arrived at a trampoline.");
167b9c1b51eSKate Stone   } else if (frame_order == eFrameCompareYounger) {
168b9c1b51eSKate Stone     // Make sure we really are in a new frame.  Do that by unwinding and seeing
169b9c1b51eSKate Stone     // if the
170b5c0d1ccSJim Ingham     // start function really is our start function...
171b9c1b51eSKate Stone     for (uint32_t i = 1;; ++i) {
172b57e4a1bSJason Molenda       StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(i);
1734b86728bSDaniel Malea       if (!older_frame_sp) {
174b9c1b51eSKate Stone         // We can't unwind the next frame we should just get out of here &
175b9c1b51eSKate Stone         // stop...
1764b86728bSDaniel Malea         break;
1774b86728bSDaniel Malea       }
1784b86728bSDaniel Malea 
179b9c1b51eSKate Stone       const SymbolContext &older_context =
180b9c1b51eSKate Stone           older_frame_sp->GetSymbolContext(eSymbolContextEverything);
181b9c1b51eSKate Stone       if (IsEquivalentContext(older_context)) {
182b9c1b51eSKate Stone         new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
183b9c1b51eSKate Stone             false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
184fd4cea53SJason Molenda             true);
1854b86728bSDaniel Malea         break;
186b9c1b51eSKate Stone       } else {
187b9c1b51eSKate Stone         new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
188b9c1b51eSKate Stone                                                              stop_others);
1895beccb22SJim Ingham         // If we found a way through, then we should stop recursing.
1905beccb22SJim Ingham         if (new_plan_sp)
1915beccb22SJim Ingham           break;
192b5c0d1ccSJim Ingham       }
193b5c0d1ccSJim Ingham     }
194b9c1b51eSKate Stone   } else {
195564d8bc2SJim Ingham     // If we're still in the range, keep going.
196b9c1b51eSKate Stone     if (InRange()) {
197564d8bc2SJim Ingham       SetNextBranchBreakpoint();
198564d8bc2SJim Ingham       return false;
199564d8bc2SJim Ingham     }
200564d8bc2SJim Ingham 
201b9c1b51eSKate Stone     if (!InSymbol()) {
202b9c1b51eSKate Stone       // This one is a little tricky.  Sometimes we may be in a stub or
203b9c1b51eSKate Stone       // something similar,
204b9c1b51eSKate Stone       // in which case we need to get out of there.  But if we are in a stub
205b9c1b51eSKate Stone       // then it's
206b9c1b51eSKate Stone       // likely going to be hard to get out from here.  It is probably easiest
207b9c1b51eSKate Stone       // to step into the
20830fdc8d8SChris Lattner       // stub, and then it will be straight-forward to step out.
209b9c1b51eSKate Stone       new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
210b9c1b51eSKate Stone                                                            stop_others);
211b9c1b51eSKate Stone     } else {
212b9c1b51eSKate Stone       // The current clang (at least through 424) doesn't always get the address
213b9c1b51eSKate Stone       // range for the
214b9c1b51eSKate Stone       // DW_TAG_inlined_subroutines right, so that when you leave the inlined
215b9c1b51eSKate Stone       // range the line table says
216b9c1b51eSKate Stone       // you are still in the source file of the inlining function.  This is
217b9c1b51eSKate Stone       // bad, because now you are missing
218b9c1b51eSKate Stone       // the stack frame for the function containing the inlining, and if you
219b9c1b51eSKate Stone       // sensibly do "finish" to get
2203bfa753fSJim Ingham       // out of this function you will instead exit the containing function.
221b9c1b51eSKate Stone       // To work around this, we check whether we are still in the source file
222b9c1b51eSKate Stone       // we started in, and if not assume
223b9c1b51eSKate Stone       // it is an error, and push a plan to get us out of this line and back to
224b9c1b51eSKate Stone       // the containing file.
2253bfa753fSJim Ingham 
226b9c1b51eSKate Stone       if (m_addr_context.line_entry.IsValid()) {
2273bfa753fSJim Ingham         SymbolContext sc;
228b57e4a1bSJason Molenda         StackFrameSP frame_sp = m_thread.GetStackFrameAtIndex(0);
2293bfa753fSJim Ingham         sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
230b9c1b51eSKate Stone         if (sc.line_entry.IsValid()) {
231b9c1b51eSKate Stone           if (sc.line_entry.original_file !=
232b9c1b51eSKate Stone                   m_addr_context.line_entry.original_file &&
233b9c1b51eSKate Stone               sc.comp_unit == m_addr_context.comp_unit &&
234b9c1b51eSKate Stone               sc.function == m_addr_context.function) {
23558ef391fSBruce Mitchener             // Okay, find the next occurrence of this file in the line table:
2363bfa753fSJim Ingham             LineTable *line_table = m_addr_context.comp_unit->GetLineTable();
237b9c1b51eSKate Stone             if (line_table) {
2383bfa753fSJim Ingham               Address cur_address = frame_sp->GetFrameCodeAddress();
2393bfa753fSJim Ingham               uint32_t entry_idx;
2403bfa753fSJim Ingham               LineEntry line_entry;
241b9c1b51eSKate Stone               if (line_table->FindLineEntryByAddress(cur_address, line_entry,
242b9c1b51eSKate Stone                                                      &entry_idx)) {
2433bfa753fSJim Ingham                 LineEntry next_line_entry;
2443bfa753fSJim Ingham                 bool step_past_remaining_inline = false;
245b9c1b51eSKate Stone                 if (entry_idx > 0) {
246b9c1b51eSKate Stone                   // We require the previous line entry and the current line
247b9c1b51eSKate Stone                   // entry come
2483bfa753fSJim Ingham                   // from the same file.
249b9c1b51eSKate Stone                   // The other requirement is that the previous line table entry
250b9c1b51eSKate Stone                   // be part of an
251b9c1b51eSKate Stone                   // inlined block, we don't want to step past cases where
252b9c1b51eSKate Stone                   // people have inlined
253b9c1b51eSKate Stone                   // some code fragment by using #include <source-fragment.c>
254b9c1b51eSKate Stone                   // directly.
2553bfa753fSJim Ingham                   LineEntry prev_line_entry;
256b9c1b51eSKate Stone                   if (line_table->GetLineEntryAtIndex(entry_idx - 1,
257b9c1b51eSKate Stone                                                       prev_line_entry) &&
258b9c1b51eSKate Stone                       prev_line_entry.original_file ==
259b9c1b51eSKate Stone                           line_entry.original_file) {
2603bfa753fSJim Ingham                     SymbolContext prev_sc;
261b9c1b51eSKate Stone                     Address prev_address =
262b9c1b51eSKate Stone                         prev_line_entry.range.GetBaseAddress();
2633bfa753fSJim Ingham                     prev_address.CalculateSymbolContext(&prev_sc);
264b9c1b51eSKate Stone                     if (prev_sc.block) {
265b9c1b51eSKate Stone                       Block *inlined_block =
266b9c1b51eSKate Stone                           prev_sc.block->GetContainingInlinedBlock();
267b9c1b51eSKate Stone                       if (inlined_block) {
2683bfa753fSJim Ingham                         AddressRange inline_range;
269b9c1b51eSKate Stone                         inlined_block->GetRangeContainingAddress(prev_address,
270b9c1b51eSKate Stone                                                                  inline_range);
271b9c1b51eSKate Stone                         if (!inline_range.ContainsFileAddress(cur_address)) {
2723bfa753fSJim Ingham 
2733bfa753fSJim Ingham                           step_past_remaining_inline = true;
2743bfa753fSJim Ingham                         }
2753bfa753fSJim Ingham                       }
2763bfa753fSJim Ingham                     }
2773bfa753fSJim Ingham                   }
2783bfa753fSJim Ingham                 }
2793bfa753fSJim Ingham 
280b9c1b51eSKate Stone                 if (step_past_remaining_inline) {
2813bfa753fSJim Ingham                   uint32_t look_ahead_step = 1;
282b9c1b51eSKate Stone                   while (line_table->GetLineEntryAtIndex(
283b9c1b51eSKate Stone                       entry_idx + look_ahead_step, next_line_entry)) {
284b9c1b51eSKate Stone                     // Make sure we haven't wandered out of the function we
285b9c1b51eSKate Stone                     // started from...
286b9c1b51eSKate Stone                     Address next_line_address =
287b9c1b51eSKate Stone                         next_line_entry.range.GetBaseAddress();
288b9c1b51eSKate Stone                     Function *next_line_function =
289b9c1b51eSKate Stone                         next_line_address.CalculateSymbolContextFunction();
2903bfa753fSJim Ingham                     if (next_line_function != m_addr_context.function)
2913bfa753fSJim Ingham                       break;
2923bfa753fSJim Ingham 
293b9c1b51eSKate Stone                     if (next_line_entry.original_file ==
294b9c1b51eSKate Stone                         m_addr_context.line_entry.original_file) {
2953bfa753fSJim Ingham                       const bool abort_other_plans = false;
29655828080SJim Ingham                       const RunMode stop_other_threads = RunMode::eAllThreads;
297b9c1b51eSKate Stone                       lldb::addr_t cur_pc = m_thread.GetStackFrameAtIndex(0)
298b9c1b51eSKate Stone                                                 ->GetRegisterContext()
299b9c1b51eSKate Stone                                                 ->GetPC();
300b9c1b51eSKate Stone                       AddressRange step_range(
301b9c1b51eSKate Stone                           cur_pc,
302b9c1b51eSKate Stone                           next_line_address.GetLoadAddress(&GetTarget()) -
303b9c1b51eSKate Stone                               cur_pc);
30455828080SJim Ingham 
305b9c1b51eSKate Stone                       new_plan_sp = m_thread.QueueThreadPlanForStepOverRange(
306b9c1b51eSKate Stone                           abort_other_plans, step_range, sc,
3073bfa753fSJim Ingham                           stop_other_threads);
3083bfa753fSJim Ingham                       break;
3093bfa753fSJim Ingham                     }
3103bfa753fSJim Ingham                     look_ahead_step++;
3113bfa753fSJim Ingham                   }
3123bfa753fSJim Ingham                 }
3133bfa753fSJim Ingham               }
3143bfa753fSJim Ingham             }
3153bfa753fSJim Ingham           }
3163bfa753fSJim Ingham         }
3173bfa753fSJim Ingham       }
3183bfa753fSJim Ingham     }
319564d8bc2SJim Ingham   }
320564d8bc2SJim Ingham 
321b9c1b51eSKate Stone   // If we get to this point, we're not going to use a previously set "next
322b9c1b51eSKate Stone   // branch" breakpoint, so delete it:
323564d8bc2SJim Ingham   ClearNextBranchBreakpoint();
32430fdc8d8SChris Lattner 
325b9c1b51eSKate Stone   // If we haven't figured out something to do yet, then ask the ShouldStopHere
326b9c1b51eSKate Stone   // callback:
327b9c1b51eSKate Stone   if (!new_plan_sp) {
3284b4b2478SJim Ingham     new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
3294b4b2478SJim Ingham   }
3304b4b2478SJim Ingham 
3314d56e9c1SJim Ingham   if (!new_plan_sp)
33230fdc8d8SChris Lattner     m_no_more_plans = true;
333b9c1b51eSKate Stone   else {
3342bdbfd50SJim Ingham     // Any new plan will be an implementation plan, so mark it private:
3352bdbfd50SJim Ingham     new_plan_sp->SetPrivate(true);
33630fdc8d8SChris Lattner     m_no_more_plans = false;
3372bdbfd50SJim Ingham   }
33830fdc8d8SChris Lattner 
339b9c1b51eSKate Stone   if (!new_plan_sp) {
340b9c1b51eSKate Stone     // For efficiencies sake, we know we're done here so we don't have to do
341b9c1b51eSKate Stone     // this
34230fdc8d8SChris Lattner     // calculation again in MischiefManaged.
34330fdc8d8SChris Lattner     SetPlanComplete();
34430fdc8d8SChris Lattner     return true;
345b9c1b51eSKate Stone   } else
34630fdc8d8SChris Lattner     return false;
34730fdc8d8SChris Lattner }
348fbbfe6ecSJim Ingham 
349b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoPlanExplainsStop(Event *event_ptr) {
350b9c1b51eSKate Stone   // For crashes, breakpoint hits, signals, etc, let the base plan (or some plan
351b9c1b51eSKate Stone   // above us)
352b9c1b51eSKate Stone   // handle the stop.  That way the user can see the stop, step around, and then
353b9c1b51eSKate Stone   // when they
354b9c1b51eSKate Stone   // are done, continue and have their step complete.  The exception is if we've
355b9c1b51eSKate Stone   // hit our
356fbbfe6ecSJim Ingham   // "run to next branch" breakpoint.
357b9c1b51eSKate Stone   // Note, unlike the step in range plan, we don't mark ourselves complete if we
358b9c1b51eSKate Stone   // hit an
359fbbfe6ecSJim Ingham   // unexplained breakpoint/crash.
360fbbfe6ecSJim Ingham 
3615160ce5cSGreg Clayton   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
36260c4118cSJim Ingham   StopInfoSP stop_info_sp = GetPrivateStopInfo();
363221d51cfSJim Ingham   bool return_value;
364221d51cfSJim Ingham 
365b9c1b51eSKate Stone   if (stop_info_sp) {
366fbbfe6ecSJim Ingham     StopReason reason = stop_info_sp->GetStopReason();
367fbbfe6ecSJim Ingham 
368b9c1b51eSKate Stone     if (reason == eStopReasonTrace) {
369221d51cfSJim Ingham       return_value = true;
370b9c1b51eSKate Stone     } else if (reason == eStopReasonBreakpoint) {
371e65b2cf2SEugene Zelenko       return_value = NextRangeBreakpointExplainsStop(stop_info_sp);
372b9c1b51eSKate Stone     } else {
373fbbfe6ecSJim Ingham       if (log)
374b9c1b51eSKate Stone         log->PutCString("ThreadPlanStepInRange got asked if it explains the "
375b9c1b51eSKate Stone                         "stop for some reason other than step.");
376221d51cfSJim Ingham       return_value = false;
377fbbfe6ecSJim Ingham     }
378b9c1b51eSKate Stone   } else
379221d51cfSJim Ingham     return_value = true;
380221d51cfSJim Ingham 
381221d51cfSJim Ingham   return return_value;
382fbbfe6ecSJim Ingham }
383513c6bb8SJim Ingham 
384b9c1b51eSKate Stone bool ThreadPlanStepOverRange::DoWillResume(lldb::StateType resume_state,
385b9c1b51eSKate Stone                                            bool current_plan) {
386b9c1b51eSKate Stone   if (resume_state != eStateSuspended && m_first_resume) {
387513c6bb8SJim Ingham     m_first_resume = false;
388b9c1b51eSKate Stone     if (resume_state == eStateStepping && current_plan) {
389b9c1b51eSKate Stone       // See if we are about to step over an inlined call in the middle of the
390b9c1b51eSKate Stone       // inlined stack, if so figure
391513c6bb8SJim Ingham       // out its extents and reset our range to step over that.
392513c6bb8SJim Ingham       bool in_inlined_stack = m_thread.DecrementCurrentInlinedDepth();
393b9c1b51eSKate Stone       if (in_inlined_stack) {
3945160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
395513c6bb8SJim Ingham         if (log)
396b9c1b51eSKate Stone           log->Printf("ThreadPlanStepInRange::DoWillResume: adjusting range to "
397b9c1b51eSKate Stone                       "the frame at inlined depth %d.",
398513c6bb8SJim Ingham                       m_thread.GetCurrentInlinedDepth());
399b57e4a1bSJason Molenda         StackFrameSP stack_sp = m_thread.GetStackFrameAtIndex(0);
400b9c1b51eSKate Stone         if (stack_sp) {
401513c6bb8SJim Ingham           Block *frame_block = stack_sp->GetFrameBlock();
402513c6bb8SJim Ingham           lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
403513c6bb8SJim Ingham           AddressRange my_range;
404b9c1b51eSKate Stone           if (frame_block->GetRangeContainingLoadAddress(
405b9c1b51eSKate Stone                   curr_pc, m_thread.GetProcess()->GetTarget(), my_range)) {
406513c6bb8SJim Ingham             m_address_ranges.clear();
407513c6bb8SJim Ingham             m_address_ranges.push_back(my_range);
408b9c1b51eSKate Stone             if (log) {
409513c6bb8SJim Ingham               StreamString s;
410b9c1b51eSKate Stone               const InlineFunctionInfo *inline_info =
411b9c1b51eSKate Stone                   frame_block->GetInlinedFunctionInfo();
412513c6bb8SJim Ingham               const char *name;
413513c6bb8SJim Ingham               if (inline_info)
414b9c1b51eSKate Stone                 name =
415b9c1b51eSKate Stone                     inline_info
416b9c1b51eSKate Stone                         ->GetName(frame_block->CalculateSymbolContextFunction()
417b9c1b51eSKate Stone                                       ->GetLanguage())
418b9c1b51eSKate Stone                         .AsCString();
419513c6bb8SJim Ingham               else
420513c6bb8SJim Ingham                 name = "<unknown-notinlined>";
421513c6bb8SJim Ingham 
422b9c1b51eSKate Stone               s.Printf(
423b9c1b51eSKate Stone                   "Stepping over inlined function \"%s\" in inlined stack: ",
424b9c1b51eSKate Stone                   name);
425513c6bb8SJim Ingham               DumpRanges(&s);
426c156427dSZachary Turner               log->PutString(s.GetString());
427513c6bb8SJim Ingham             }
428513c6bb8SJim Ingham           }
429513c6bb8SJim Ingham         }
430513c6bb8SJim Ingham       }
431513c6bb8SJim Ingham     }
432513c6bb8SJim Ingham   }
433513c6bb8SJim Ingham 
434221d51cfSJim Ingham   return true;
435513c6bb8SJim Ingham }
436