xref: /src/contrib/llvm-project/lldb/source/Target/ThreadPlanStepRange.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- ThreadPlanStepRange.cpp -------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9e81d9d49SDimitry Andric #include "lldb/Target/ThreadPlanStepRange.h"
10f034231aSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
11f034231aSEd Maste #include "lldb/Breakpoint/BreakpointSite.h"
12f034231aSEd Maste #include "lldb/Core/Disassembler.h"
13f034231aSEd Maste #include "lldb/Symbol/Function.h"
14f034231aSEd Maste #include "lldb/Symbol/Symbol.h"
15f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
16f034231aSEd Maste #include "lldb/Target/Process.h"
17f034231aSEd Maste #include "lldb/Target/RegisterContext.h"
18f034231aSEd Maste #include "lldb/Target/StopInfo.h"
19f034231aSEd Maste #include "lldb/Target/Target.h"
20f034231aSEd Maste #include "lldb/Target/Thread.h"
21f034231aSEd Maste #include "lldb/Target/ThreadPlanRunToAddress.h"
22145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
2374a628f7SDimitry Andric #include "lldb/Utility/Log.h"
2474a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
25f034231aSEd Maste 
26f034231aSEd Maste using namespace lldb;
27f034231aSEd Maste using namespace lldb_private;
28f034231aSEd Maste 
29f73363f1SDimitry Andric // ThreadPlanStepRange: Step through a stack range, either stepping over or
30f73363f1SDimitry Andric // into based on the value of \a type.
31f034231aSEd Maste 
ThreadPlanStepRange(ThreadPlanKind kind,const char * name,Thread & thread,const AddressRange & range,const SymbolContext & addr_context,lldb::RunMode stop_others,bool given_ranges_only)3214f1b3e8SDimitry Andric ThreadPlanStepRange::ThreadPlanStepRange(ThreadPlanKind kind, const char *name,
33f034231aSEd Maste                                          Thread &thread,
34f034231aSEd Maste                                          const AddressRange &range,
35f034231aSEd Maste                                          const SymbolContext &addr_context,
36205afe67SEd Maste                                          lldb::RunMode stop_others,
3714f1b3e8SDimitry Andric                                          bool given_ranges_only)
3814f1b3e8SDimitry Andric     : ThreadPlan(kind, name, thread, eVoteNoOpinion, eVoteNoOpinion),
3914f1b3e8SDimitry Andric       m_addr_context(addr_context), m_address_ranges(),
4014f1b3e8SDimitry Andric       m_stop_others(stop_others), m_stack_id(), m_parent_stack_id(),
4114f1b3e8SDimitry Andric       m_no_more_plans(false), m_first_run_event(true), m_use_fast_step(false),
4214f1b3e8SDimitry Andric       m_given_ranges_only(given_ranges_only) {
43f034231aSEd Maste   m_use_fast_step = GetTarget().GetUseFastStepping();
44f034231aSEd Maste   AddRange(range);
45cfca06d7SDimitry Andric   m_stack_id = thread.GetStackFrameAtIndex(0)->GetStackID();
46cfca06d7SDimitry Andric   StackFrameSP parent_stack = thread.GetStackFrameAtIndex(1);
470cac4ca3SEd Maste   if (parent_stack)
480cac4ca3SEd Maste     m_parent_stack_id = parent_stack->GetStackID();
49f034231aSEd Maste }
50f034231aSEd Maste 
~ThreadPlanStepRange()5114f1b3e8SDimitry Andric ThreadPlanStepRange::~ThreadPlanStepRange() { ClearNextBranchBreakpoint(); }
52f034231aSEd Maste 
DidPush()5314f1b3e8SDimitry Andric void ThreadPlanStepRange::DidPush() {
54f034231aSEd Maste   // See if we can find a "next range" breakpoint:
55f034231aSEd Maste   SetNextBranchBreakpoint();
56f034231aSEd Maste }
57f034231aSEd Maste 
ValidatePlan(Stream * error)5894994d37SDimitry Andric bool ThreadPlanStepRange::ValidatePlan(Stream *error) {
5994994d37SDimitry Andric   if (m_could_not_resolve_hw_bp) {
6094994d37SDimitry Andric     if (error)
6194994d37SDimitry Andric       error->PutCString(
6294994d37SDimitry Andric           "Could not create hardware breakpoint for thread plan.");
6394994d37SDimitry Andric     return false;
6494994d37SDimitry Andric   }
6594994d37SDimitry Andric   return true;
6694994d37SDimitry Andric }
67f034231aSEd Maste 
ShouldReportStop(Event * event_ptr)6814f1b3e8SDimitry Andric Vote ThreadPlanStepRange::ShouldReportStop(Event *event_ptr) {
69145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
70f034231aSEd Maste 
71f034231aSEd Maste   const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo;
72ead24645SDimitry Andric   LLDB_LOGF(log, "ThreadPlanStepRange::ShouldReportStop() returning vote %i\n",
7314f1b3e8SDimitry Andric             vote);
74f034231aSEd Maste   return vote;
75f034231aSEd Maste }
76f034231aSEd Maste 
AddRange(const AddressRange & new_range)7714f1b3e8SDimitry Andric void ThreadPlanStepRange::AddRange(const AddressRange &new_range) {
78f73363f1SDimitry Andric   // For now I'm just adding the ranges.  At some point we may want to condense
79f73363f1SDimitry Andric   // the ranges if they overlap, though I don't think it is likely to be very
80f73363f1SDimitry Andric   // important.
81f034231aSEd Maste   m_address_ranges.push_back(new_range);
82f034231aSEd Maste 
8314f1b3e8SDimitry Andric   // Fill the slot for this address range with an empty DisassemblerSP in the
84f73363f1SDimitry Andric   // instruction ranges. I want the indices to match, but I don't want to do
85f73363f1SDimitry Andric   // the work to disassemble this range if I don't step into it.
86f034231aSEd Maste   m_instruction_ranges.push_back(DisassemblerSP());
87f034231aSEd Maste }
88f034231aSEd Maste 
DumpRanges(Stream * s)8914f1b3e8SDimitry Andric void ThreadPlanStepRange::DumpRanges(Stream *s) {
90f034231aSEd Maste   size_t num_ranges = m_address_ranges.size();
9114f1b3e8SDimitry Andric   if (num_ranges == 1) {
92cfca06d7SDimitry Andric     m_address_ranges[0].Dump(s, &GetTarget(), Address::DumpStyleLoadAddress);
9314f1b3e8SDimitry Andric   } else {
9414f1b3e8SDimitry Andric     for (size_t i = 0; i < num_ranges; i++) {
95e81d9d49SDimitry Andric       s->Printf(" %" PRIu64 ": ", uint64_t(i));
96cfca06d7SDimitry Andric       m_address_ranges[i].Dump(s, &GetTarget(), Address::DumpStyleLoadAddress);
97f034231aSEd Maste     }
98f034231aSEd Maste   }
99f034231aSEd Maste }
100f034231aSEd Maste 
InRange()10114f1b3e8SDimitry Andric bool ThreadPlanStepRange::InRange() {
102145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
103f034231aSEd Maste   bool ret_value = false;
104cfca06d7SDimitry Andric   Thread &thread = GetThread();
105cfca06d7SDimitry Andric   lldb::addr_t pc_load_addr = thread.GetRegisterContext()->GetPC();
106f034231aSEd Maste 
107f034231aSEd Maste   size_t num_ranges = m_address_ranges.size();
10814f1b3e8SDimitry Andric   for (size_t i = 0; i < num_ranges; i++) {
109cfca06d7SDimitry Andric     ret_value =
110cfca06d7SDimitry Andric         m_address_ranges[i].ContainsLoadAddress(pc_load_addr, &GetTarget());
111f034231aSEd Maste     if (ret_value)
112f034231aSEd Maste       break;
113f034231aSEd Maste   }
114f034231aSEd Maste 
11514f1b3e8SDimitry Andric   if (!ret_value && !m_given_ranges_only) {
116f034231aSEd Maste     // See if we've just stepped to another part of the same line number...
117cfca06d7SDimitry Andric     StackFrame *frame = thread.GetStackFrameAtIndex(0).get();
118f034231aSEd Maste 
11914f1b3e8SDimitry Andric     SymbolContext new_context(
12014f1b3e8SDimitry Andric         frame->GetSymbolContext(eSymbolContextEverything));
12114f1b3e8SDimitry Andric     if (m_addr_context.line_entry.IsValid() &&
12214f1b3e8SDimitry Andric         new_context.line_entry.IsValid()) {
123ac9a064cSDimitry Andric       if (m_addr_context.line_entry.original_file_sp->Equal(
124ac9a064cSDimitry Andric               *new_context.line_entry.original_file_sp,
125ac9a064cSDimitry Andric               SupportFile::eEqualFileSpecAndChecksumIfSet)) {
12614f1b3e8SDimitry Andric         if (m_addr_context.line_entry.line == new_context.line_entry.line) {
127f034231aSEd Maste           m_addr_context = new_context;
1285f29bb8aSDimitry Andric           const bool include_inlined_functions =
1295f29bb8aSDimitry Andric               GetKind() == eKindStepOverRange;
1305f29bb8aSDimitry Andric           AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange(
1315f29bb8aSDimitry Andric               include_inlined_functions));
132f034231aSEd Maste           ret_value = true;
13314f1b3e8SDimitry Andric           if (log) {
134f034231aSEd Maste             StreamString s;
135cfca06d7SDimitry Andric             m_addr_context.line_entry.Dump(&s, &GetTarget(), true,
136cfca06d7SDimitry Andric                                            Address::DumpStyleLoadAddress,
13714f1b3e8SDimitry Andric                                            Address::DumpStyleLoadAddress, true);
138f034231aSEd Maste 
139ead24645SDimitry Andric             LLDB_LOGF(
140ead24645SDimitry Andric                 log,
14114f1b3e8SDimitry Andric                 "Step range plan stepped to another range of same line: %s",
14214f1b3e8SDimitry Andric                 s.GetData());
143f034231aSEd Maste           }
14414f1b3e8SDimitry Andric         } else if (new_context.line_entry.line == 0) {
145f21a844fSEd Maste           new_context.line_entry.line = m_addr_context.line_entry.line;
146f21a844fSEd Maste           m_addr_context = new_context;
1475f29bb8aSDimitry Andric           const bool include_inlined_functions =
1485f29bb8aSDimitry Andric               GetKind() == eKindStepOverRange;
1495f29bb8aSDimitry Andric           AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange(
1505f29bb8aSDimitry Andric               include_inlined_functions));
151f21a844fSEd Maste           ret_value = true;
15214f1b3e8SDimitry Andric           if (log) {
153f21a844fSEd Maste             StreamString s;
154cfca06d7SDimitry Andric             m_addr_context.line_entry.Dump(&s, &GetTarget(), true,
155cfca06d7SDimitry Andric                                            Address::DumpStyleLoadAddress,
15614f1b3e8SDimitry Andric                                            Address::DumpStyleLoadAddress, true);
157f21a844fSEd Maste 
158ead24645SDimitry Andric             LLDB_LOGF(log,
159ead24645SDimitry Andric                       "Step range plan stepped to a range at linenumber 0 "
16014f1b3e8SDimitry Andric                       "stepping through that range: %s",
16114f1b3e8SDimitry Andric                       s.GetData());
162f21a844fSEd Maste           }
16314f1b3e8SDimitry Andric         } else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(
164cfca06d7SDimitry Andric                        &GetTarget()) != pc_load_addr) {
16514f1b3e8SDimitry Andric           // Another thing that sometimes happens here is that we step out of
166f73363f1SDimitry Andric           // one line into the MIDDLE of another line.  So far I mostly see
167f73363f1SDimitry Andric           // this due to bugs in the debug information. But we probably don't
168f73363f1SDimitry Andric           // want to be in the middle of a line range, so in that case reset
169f73363f1SDimitry Andric           // the stepping range to the line we've stepped into the middle of
170f73363f1SDimitry Andric           // and continue.
171f034231aSEd Maste           m_addr_context = new_context;
172f034231aSEd Maste           m_address_ranges.clear();
173f034231aSEd Maste           AddRange(m_addr_context.line_entry.range);
174f034231aSEd Maste           ret_value = true;
17514f1b3e8SDimitry Andric           if (log) {
176f034231aSEd Maste             StreamString s;
177cfca06d7SDimitry Andric             m_addr_context.line_entry.Dump(&s, &GetTarget(), true,
178cfca06d7SDimitry Andric                                            Address::DumpStyleLoadAddress,
17914f1b3e8SDimitry Andric                                            Address::DumpStyleLoadAddress, true);
180f034231aSEd Maste 
181ead24645SDimitry Andric             LLDB_LOGF(log,
182ead24645SDimitry Andric                       "Step range plan stepped to the middle of new "
18314f1b3e8SDimitry Andric                       "line(%d): %s, continuing to clear this line.",
18414f1b3e8SDimitry Andric                       new_context.line_entry.line, s.GetData());
185f034231aSEd Maste           }
186f034231aSEd Maste         }
187f034231aSEd Maste       }
188f034231aSEd Maste     }
189f034231aSEd Maste   }
190f034231aSEd Maste 
191f034231aSEd Maste   if (!ret_value && log)
192ead24645SDimitry Andric     LLDB_LOGF(log, "Step range plan out of range to 0x%" PRIx64, pc_load_addr);
193f034231aSEd Maste 
194f034231aSEd Maste   return ret_value;
195f034231aSEd Maste }
196f034231aSEd Maste 
InSymbol()19714f1b3e8SDimitry Andric bool ThreadPlanStepRange::InSymbol() {
198cfca06d7SDimitry Andric   lldb::addr_t cur_pc = GetThread().GetRegisterContext()->GetPC();
19914f1b3e8SDimitry Andric   if (m_addr_context.function != nullptr) {
20014f1b3e8SDimitry Andric     return m_addr_context.function->GetAddressRange().ContainsLoadAddress(
201cfca06d7SDimitry Andric         cur_pc, &GetTarget());
20214f1b3e8SDimitry Andric   } else if (m_addr_context.symbol && m_addr_context.symbol->ValueIsAddress()) {
20314f1b3e8SDimitry Andric     AddressRange range(m_addr_context.symbol->GetAddressRef(),
20414f1b3e8SDimitry Andric                        m_addr_context.symbol->GetByteSize());
205cfca06d7SDimitry Andric     return range.ContainsLoadAddress(cur_pc, &GetTarget());
206f034231aSEd Maste   }
207f034231aSEd Maste   return false;
208f034231aSEd Maste }
209f034231aSEd Maste 
21014f1b3e8SDimitry Andric // FIXME: This should also handle inlining if we aren't going to do inlining in
21114f1b3e8SDimitry Andric // the
212f034231aSEd Maste // main stack.
213f034231aSEd Maste //
214f034231aSEd Maste // Ideally we should remember the whole stack frame list, and then compare that
215f034231aSEd Maste // to the current list.
216f034231aSEd Maste 
CompareCurrentFrameToStartFrame()21714f1b3e8SDimitry Andric lldb::FrameComparison ThreadPlanStepRange::CompareCurrentFrameToStartFrame() {
218f034231aSEd Maste   FrameComparison frame_order;
219cfca06d7SDimitry Andric   Thread &thread = GetThread();
220cfca06d7SDimitry Andric   StackID cur_frame_id = thread.GetStackFrameAtIndex(0)->GetStackID();
221f034231aSEd Maste 
22214f1b3e8SDimitry Andric   if (cur_frame_id == m_stack_id) {
223f034231aSEd Maste     frame_order = eFrameCompareEqual;
22414f1b3e8SDimitry Andric   } else if (cur_frame_id < m_stack_id) {
225f034231aSEd Maste     frame_order = eFrameCompareYounger;
22614f1b3e8SDimitry Andric   } else {
227cfca06d7SDimitry Andric     StackFrameSP cur_parent_frame = thread.GetStackFrameAtIndex(1);
2280cac4ca3SEd Maste     StackID cur_parent_id;
2290cac4ca3SEd Maste     if (cur_parent_frame)
2300cac4ca3SEd Maste       cur_parent_id = cur_parent_frame->GetStackID();
23114f1b3e8SDimitry Andric     if (m_parent_stack_id.IsValid() && cur_parent_id.IsValid() &&
23214f1b3e8SDimitry Andric         m_parent_stack_id == cur_parent_id)
2330cac4ca3SEd Maste       frame_order = eFrameCompareSameParent;
2340cac4ca3SEd Maste     else
235f034231aSEd Maste       frame_order = eFrameCompareOlder;
236f034231aSEd Maste   }
237f034231aSEd Maste   return frame_order;
238f034231aSEd Maste }
239f034231aSEd Maste 
StopOthers()24014f1b3e8SDimitry Andric bool ThreadPlanStepRange::StopOthers() {
241706b4fc4SDimitry Andric   switch (m_stop_others) {
242706b4fc4SDimitry Andric   case lldb::eOnlyThisThread:
243706b4fc4SDimitry Andric     return true;
244706b4fc4SDimitry Andric   case lldb::eOnlyDuringStepping:
245706b4fc4SDimitry Andric     // If there is a call in the range of the next branch breakpoint,
246706b4fc4SDimitry Andric     // then we should always run all threads, since a call can execute
247706b4fc4SDimitry Andric     // arbitrary code which might for instance take a lock that's held
248706b4fc4SDimitry Andric     // by another thread.
249706b4fc4SDimitry Andric     return !m_found_calls;
250706b4fc4SDimitry Andric   case lldb::eAllThreads:
251706b4fc4SDimitry Andric     return false;
252706b4fc4SDimitry Andric   }
253706b4fc4SDimitry Andric   llvm_unreachable("Unhandled run mode!");
254f034231aSEd Maste }
255f034231aSEd Maste 
GetInstructionsForAddress(lldb::addr_t addr,size_t & range_index,size_t & insn_offset)25614f1b3e8SDimitry Andric InstructionList *ThreadPlanStepRange::GetInstructionsForAddress(
25714f1b3e8SDimitry Andric     lldb::addr_t addr, size_t &range_index, size_t &insn_offset) {
258f034231aSEd Maste   size_t num_ranges = m_address_ranges.size();
25914f1b3e8SDimitry Andric   for (size_t i = 0; i < num_ranges; i++) {
26014f1b3e8SDimitry Andric     if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) {
261f034231aSEd Maste       // Some joker added a zero size range to the stepping range...
262f034231aSEd Maste       if (m_address_ranges[i].GetByteSize() == 0)
263e81d9d49SDimitry Andric         return nullptr;
264f034231aSEd Maste 
26514f1b3e8SDimitry Andric       if (!m_instruction_ranges[i]) {
266f034231aSEd Maste         // Disassemble the address range given:
267e81d9d49SDimitry Andric         const char *plugin_name = nullptr;
268e81d9d49SDimitry Andric         const char *flavor = nullptr;
26914f1b3e8SDimitry Andric         m_instruction_ranges[i] = Disassembler::DisassembleRange(
270cfca06d7SDimitry Andric             GetTarget().GetArchitecture(), plugin_name, flavor, GetTarget(),
271344a3780SDimitry Andric             m_address_ranges[i]);
272f034231aSEd Maste       }
273f034231aSEd Maste       if (!m_instruction_ranges[i])
274e81d9d49SDimitry Andric         return nullptr;
27514f1b3e8SDimitry Andric       else {
27614f1b3e8SDimitry Andric         // Find where we are in the instruction list as well.  If we aren't at
277f73363f1SDimitry Andric         // an instruction, return nullptr. In this case, we're probably lost,
278f73363f1SDimitry Andric         // and shouldn't try to do anything fancy.
279f034231aSEd Maste 
28014f1b3e8SDimitry Andric         insn_offset =
28114f1b3e8SDimitry Andric             m_instruction_ranges[i]
28214f1b3e8SDimitry Andric                 ->GetInstructionList()
28314f1b3e8SDimitry Andric                 .GetIndexOfInstructionAtLoadAddress(addr, GetTarget());
284f034231aSEd Maste         if (insn_offset == UINT32_MAX)
285e81d9d49SDimitry Andric           return nullptr;
28614f1b3e8SDimitry Andric         else {
287f034231aSEd Maste           range_index = i;
288f034231aSEd Maste           return &m_instruction_ranges[i]->GetInstructionList();
289f034231aSEd Maste         }
290f034231aSEd Maste       }
291f034231aSEd Maste     }
292f034231aSEd Maste   }
293e81d9d49SDimitry Andric   return nullptr;
294f034231aSEd Maste }
295f034231aSEd Maste 
ClearNextBranchBreakpoint()29614f1b3e8SDimitry Andric void ThreadPlanStepRange::ClearNextBranchBreakpoint() {
29714f1b3e8SDimitry Andric   if (m_next_branch_bp_sp) {
298145449b1SDimitry Andric     Log *log = GetLog(LLDBLog::Step);
299ead24645SDimitry Andric     LLDB_LOGF(log, "Removing next branch breakpoint: %d.",
30014f1b3e8SDimitry Andric               m_next_branch_bp_sp->GetID());
301f034231aSEd Maste     GetTarget().RemoveBreakpointByID(m_next_branch_bp_sp->GetID());
302f034231aSEd Maste     m_next_branch_bp_sp.reset();
30394994d37SDimitry Andric     m_could_not_resolve_hw_bp = false;
304706b4fc4SDimitry Andric     m_found_calls = false;
305f034231aSEd Maste   }
306f034231aSEd Maste }
307f034231aSEd Maste 
SetNextBranchBreakpoint()30814f1b3e8SDimitry Andric bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
309f034231aSEd Maste   if (m_next_branch_bp_sp)
310f034231aSEd Maste     return true;
311f034231aSEd Maste 
312145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
31314f1b3e8SDimitry Andric   // Stepping through ranges using breakpoints doesn't work yet, but with this
314f73363f1SDimitry Andric   // off we fall back to instruction single stepping.
315f034231aSEd Maste   if (!m_use_fast_step)
316f034231aSEd Maste     return false;
317f034231aSEd Maste 
318706b4fc4SDimitry Andric   // clear the m_found_calls, we'll rediscover it for this range.
319706b4fc4SDimitry Andric   m_found_calls = false;
320706b4fc4SDimitry Andric 
321f034231aSEd Maste   lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC();
32214f1b3e8SDimitry Andric   // Find the current address in our address ranges, and fetch the disassembly
32314f1b3e8SDimitry Andric   // if we haven't already:
324f034231aSEd Maste   size_t pc_index;
325f034231aSEd Maste   size_t range_index;
32614f1b3e8SDimitry Andric   InstructionList *instructions =
32714f1b3e8SDimitry Andric       GetInstructionsForAddress(cur_addr, range_index, pc_index);
328e81d9d49SDimitry Andric   if (instructions == nullptr)
329f034231aSEd Maste     return false;
33014f1b3e8SDimitry Andric   else {
3315f29bb8aSDimitry Andric     const bool ignore_calls = GetKind() == eKindStepOverRange;
332b60736ecSDimitry Andric     uint32_t branch_index = instructions->GetIndexOfNextBranchInstruction(
333b60736ecSDimitry Andric         pc_index, ignore_calls, &m_found_calls);
334f034231aSEd Maste     Address run_to_address;
335f034231aSEd Maste 
336f034231aSEd Maste     // If we didn't find a branch, run to the end of the range.
33714f1b3e8SDimitry Andric     if (branch_index == UINT32_MAX) {
338e81d9d49SDimitry Andric       uint32_t last_index = instructions->GetSize() - 1;
33914f1b3e8SDimitry Andric       if (last_index - pc_index > 1) {
34014f1b3e8SDimitry Andric         InstructionSP last_inst =
34114f1b3e8SDimitry Andric             instructions->GetInstructionAtIndex(last_index);
342e81d9d49SDimitry Andric         size_t last_inst_size = last_inst->GetOpcode().GetByteSize();
343e81d9d49SDimitry Andric         run_to_address = last_inst->GetAddress();
344e81d9d49SDimitry Andric         run_to_address.Slide(last_inst_size);
345e81d9d49SDimitry Andric       }
34614f1b3e8SDimitry Andric     } else if (branch_index - pc_index > 1) {
34714f1b3e8SDimitry Andric       run_to_address =
34814f1b3e8SDimitry Andric           instructions->GetInstructionAtIndex(branch_index)->GetAddress();
349f034231aSEd Maste     }
350f034231aSEd Maste 
35114f1b3e8SDimitry Andric     if (run_to_address.IsValid()) {
352f034231aSEd Maste       const bool is_internal = true;
35314f1b3e8SDimitry Andric       m_next_branch_bp_sp =
35414f1b3e8SDimitry Andric           GetTarget().CreateBreakpoint(run_to_address, is_internal, false);
35514f1b3e8SDimitry Andric       if (m_next_branch_bp_sp) {
35694994d37SDimitry Andric 
35794994d37SDimitry Andric         if (m_next_branch_bp_sp->IsHardware() &&
35894994d37SDimitry Andric             !m_next_branch_bp_sp->HasResolvedLocations())
35994994d37SDimitry Andric           m_could_not_resolve_hw_bp = true;
36094994d37SDimitry Andric 
36114f1b3e8SDimitry Andric         if (log) {
362f034231aSEd Maste           lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID;
36314f1b3e8SDimitry Andric           BreakpointLocationSP bp_loc =
36414f1b3e8SDimitry Andric               m_next_branch_bp_sp->GetLocationAtIndex(0);
36514f1b3e8SDimitry Andric           if (bp_loc) {
366f034231aSEd Maste             BreakpointSiteSP bp_site = bp_loc->GetBreakpointSite();
36714f1b3e8SDimitry Andric             if (bp_site) {
368f034231aSEd Maste               bp_site_id = bp_site->GetID();
369f034231aSEd Maste             }
370f034231aSEd Maste           }
371ead24645SDimitry Andric           LLDB_LOGF(log,
372ead24645SDimitry Andric                     "ThreadPlanStepRange::SetNextBranchBreakpoint - Setting "
37314f1b3e8SDimitry Andric                     "breakpoint %d (site %d) to run to address 0x%" PRIx64,
37414f1b3e8SDimitry Andric                     m_next_branch_bp_sp->GetID(), bp_site_id,
375cfca06d7SDimitry Andric                     run_to_address.GetLoadAddress(&m_process.GetTarget()));
376f034231aSEd Maste         }
37794994d37SDimitry Andric 
378cfca06d7SDimitry Andric         m_next_branch_bp_sp->SetThreadID(m_tid);
379f034231aSEd Maste         m_next_branch_bp_sp->SetBreakpointKind("next-branch-location");
38094994d37SDimitry Andric 
381f034231aSEd Maste         return true;
38214f1b3e8SDimitry Andric       } else
383f034231aSEd Maste         return false;
384f034231aSEd Maste     }
385f034231aSEd Maste   }
386f034231aSEd Maste   return false;
387f034231aSEd Maste }
388f034231aSEd Maste 
NextRangeBreakpointExplainsStop(lldb::StopInfoSP stop_info_sp)38914f1b3e8SDimitry Andric bool ThreadPlanStepRange::NextRangeBreakpointExplainsStop(
39014f1b3e8SDimitry Andric     lldb::StopInfoSP stop_info_sp) {
391145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
392f034231aSEd Maste   if (!m_next_branch_bp_sp)
393f034231aSEd Maste     return false;
394f034231aSEd Maste 
395f034231aSEd Maste   break_id_t bp_site_id = stop_info_sp->GetValue();
39614f1b3e8SDimitry Andric   BreakpointSiteSP bp_site_sp =
397cfca06d7SDimitry Andric       m_process.GetBreakpointSiteList().FindByID(bp_site_id);
398f034231aSEd Maste   if (!bp_site_sp)
399f034231aSEd Maste     return false;
400f034231aSEd Maste   else if (!bp_site_sp->IsBreakpointAtThisSite(m_next_branch_bp_sp->GetID()))
401f034231aSEd Maste     return false;
40214f1b3e8SDimitry Andric   else {
403f034231aSEd Maste     // If we've hit the next branch breakpoint, then clear it.
404b1c73532SDimitry Andric     size_t num_constituents = bp_site_sp->GetNumberOfConstituents();
405f034231aSEd Maste     bool explains_stop = true;
406b1c73532SDimitry Andric     // If all the constituents are internal, then we are probably just stepping
407b1c73532SDimitry Andric     // over this range from multiple threads, or multiple frames, so we want to
408f73363f1SDimitry Andric     // continue.  If one is not internal, then we should not explain the stop,
409f034231aSEd Maste     // and let the user breakpoint handle the stop.
410b1c73532SDimitry Andric     for (size_t i = 0; i < num_constituents; i++) {
411b1c73532SDimitry Andric       if (!bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint().IsInternal()) {
412f034231aSEd Maste         explains_stop = false;
413f034231aSEd Maste         break;
414f034231aSEd Maste       }
415f034231aSEd Maste     }
416ead24645SDimitry Andric     LLDB_LOGF(log,
417ead24645SDimitry Andric               "ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit "
41814f1b3e8SDimitry Andric               "next range breakpoint which has %" PRIu64
419b1c73532SDimitry Andric               " constituents - explains stop: %u.",
420b1c73532SDimitry Andric               (uint64_t)num_constituents, explains_stop);
421f034231aSEd Maste     ClearNextBranchBreakpoint();
422f034231aSEd Maste     return explains_stop;
423f034231aSEd Maste   }
424f034231aSEd Maste }
425f034231aSEd Maste 
WillStop()42614f1b3e8SDimitry Andric bool ThreadPlanStepRange::WillStop() { return true; }
427f034231aSEd Maste 
GetPlanRunState()42814f1b3e8SDimitry Andric StateType ThreadPlanStepRange::GetPlanRunState() {
429f034231aSEd Maste   if (m_next_branch_bp_sp)
430f034231aSEd Maste     return eStateRunning;
431f034231aSEd Maste   else
432f034231aSEd Maste     return eStateStepping;
433f034231aSEd Maste }
434f034231aSEd Maste 
MischiefManaged()43514f1b3e8SDimitry Andric bool ThreadPlanStepRange::MischiefManaged() {
43614f1b3e8SDimitry Andric   // If we have pushed some plans between ShouldStop & MischiefManaged, then
43714f1b3e8SDimitry Andric   // we're not done...
43814f1b3e8SDimitry Andric   // I do this check first because we might have stepped somewhere that will
43914f1b3e8SDimitry Andric   // fool InRange into
44014f1b3e8SDimitry Andric   // thinking it needs to step past the end of that line.  This happens, for
441f73363f1SDimitry Andric   // instance, when stepping over inlined code that is in the middle of the
442f73363f1SDimitry Andric   // current line.
443f034231aSEd Maste 
444f034231aSEd Maste   if (!m_no_more_plans)
445f034231aSEd Maste     return false;
446f034231aSEd Maste 
447f034231aSEd Maste   bool done = true;
44814f1b3e8SDimitry Andric   if (!IsPlanComplete()) {
44914f1b3e8SDimitry Andric     if (InRange()) {
450f034231aSEd Maste       done = false;
45114f1b3e8SDimitry Andric     } else {
452f034231aSEd Maste       FrameComparison frame_order = CompareCurrentFrameToStartFrame();
453e81d9d49SDimitry Andric       done = (frame_order != eFrameCompareOlder) ? m_no_more_plans : true;
454f034231aSEd Maste     }
455f034231aSEd Maste   }
456f034231aSEd Maste 
45714f1b3e8SDimitry Andric   if (done) {
458145449b1SDimitry Andric     Log *log = GetLog(LLDBLog::Step);
459ead24645SDimitry Andric     LLDB_LOGF(log, "Completed step through range plan.");
460f034231aSEd Maste     ClearNextBranchBreakpoint();
461f034231aSEd Maste     ThreadPlan::MischiefManaged();
462f034231aSEd Maste     return true;
46314f1b3e8SDimitry Andric   } else {
464f034231aSEd Maste     return false;
465f034231aSEd Maste   }
466f034231aSEd Maste }
467f034231aSEd Maste 
IsPlanStale()46814f1b3e8SDimitry Andric bool ThreadPlanStepRange::IsPlanStale() {
469145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
470f034231aSEd Maste   FrameComparison frame_order = CompareCurrentFrameToStartFrame();
471f034231aSEd Maste 
47214f1b3e8SDimitry Andric   if (frame_order == eFrameCompareOlder) {
47314f1b3e8SDimitry Andric     if (log) {
474ead24645SDimitry Andric       LLDB_LOGF(log, "ThreadPlanStepRange::IsPlanStale returning true, we've "
47514f1b3e8SDimitry Andric                      "stepped out.");
476f034231aSEd Maste     }
477f034231aSEd Maste     return true;
47814f1b3e8SDimitry Andric   } else if (frame_order == eFrameCompareEqual && InSymbol()) {
479f73363f1SDimitry Andric     // If we are not in a place we should step through, we've gotten stale. One
480f73363f1SDimitry Andric     // tricky bit here is that some stubs don't push a frame, so we should.
481f034231aSEd Maste     // check that we are in the same symbol.
48214f1b3e8SDimitry Andric     if (!InRange()) {
48374a628f7SDimitry Andric       // Set plan Complete when we reach next instruction just after the range
484cfca06d7SDimitry Andric       lldb::addr_t addr = GetThread().GetRegisterContext()->GetPC() - 1;
48574a628f7SDimitry Andric       size_t num_ranges = m_address_ranges.size();
48674a628f7SDimitry Andric       for (size_t i = 0; i < num_ranges; i++) {
487cfca06d7SDimitry Andric         bool in_range =
488cfca06d7SDimitry Andric             m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget());
48974a628f7SDimitry Andric         if (in_range) {
49074a628f7SDimitry Andric           SetPlanComplete();
49174a628f7SDimitry Andric         }
49274a628f7SDimitry Andric       }
493f034231aSEd Maste       return true;
494f034231aSEd Maste     }
495f034231aSEd Maste   }
496f034231aSEd Maste   return false;
497f034231aSEd Maste }
498