1ac7ddfbfSEd Maste //===-- ThreadPlanStepRange.cpp ---------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
109f2f44ceSEd Maste #include "lldb/Target/ThreadPlanStepRange.h"
11ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
12ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointSite.h"
13ac7ddfbfSEd Maste #include "lldb/Core/Disassembler.h"
14ac7ddfbfSEd Maste #include "lldb/Symbol/Function.h"
15ac7ddfbfSEd Maste #include "lldb/Symbol/Symbol.h"
16ac7ddfbfSEd Maste #include "lldb/Target/ExecutionContext.h"
17ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
18ac7ddfbfSEd Maste #include "lldb/Target/RegisterContext.h"
19ac7ddfbfSEd Maste #include "lldb/Target/StopInfo.h"
20ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
21ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
22ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanRunToAddress.h"
23f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
24f678e45dSDimitry Andric #include "lldb/Utility/Stream.h"
25ac7ddfbfSEd Maste
26ac7ddfbfSEd Maste using namespace lldb;
27ac7ddfbfSEd Maste using namespace lldb_private;
28ac7ddfbfSEd Maste
29ac7ddfbfSEd Maste //----------------------------------------------------------------------
304ba319b5SDimitry Andric // ThreadPlanStepRange: Step through a stack range, either stepping over or
314ba319b5SDimitry Andric // into based on the value of \a type.
32ac7ddfbfSEd Maste //----------------------------------------------------------------------
33ac7ddfbfSEd Maste
ThreadPlanStepRange(ThreadPlanKind kind,const char * name,Thread & thread,const AddressRange & range,const SymbolContext & addr_context,lldb::RunMode stop_others,bool given_ranges_only)34435933ddSDimitry Andric ThreadPlanStepRange::ThreadPlanStepRange(ThreadPlanKind kind, const char *name,
35ac7ddfbfSEd Maste Thread &thread,
36ac7ddfbfSEd Maste const AddressRange &range,
37ac7ddfbfSEd Maste const SymbolContext &addr_context,
387aa51b79SEd Maste lldb::RunMode stop_others,
39435933ddSDimitry Andric bool given_ranges_only)
40435933ddSDimitry Andric : ThreadPlan(kind, name, thread, eVoteNoOpinion, eVoteNoOpinion),
41435933ddSDimitry Andric m_addr_context(addr_context), m_address_ranges(),
42435933ddSDimitry Andric m_stop_others(stop_others), m_stack_id(), m_parent_stack_id(),
43435933ddSDimitry Andric m_no_more_plans(false), m_first_run_event(true), m_use_fast_step(false),
44435933ddSDimitry Andric m_given_ranges_only(given_ranges_only) {
45ac7ddfbfSEd Maste m_use_fast_step = GetTarget().GetUseFastStepping();
46ac7ddfbfSEd Maste AddRange(range);
47ac7ddfbfSEd Maste m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
480127ef0fSEd Maste StackFrameSP parent_stack = m_thread.GetStackFrameAtIndex(1);
490127ef0fSEd Maste if (parent_stack)
500127ef0fSEd Maste m_parent_stack_id = parent_stack->GetStackID();
51ac7ddfbfSEd Maste }
52ac7ddfbfSEd Maste
~ThreadPlanStepRange()53435933ddSDimitry Andric ThreadPlanStepRange::~ThreadPlanStepRange() { ClearNextBranchBreakpoint(); }
54ac7ddfbfSEd Maste
DidPush()55435933ddSDimitry Andric void ThreadPlanStepRange::DidPush() {
56ac7ddfbfSEd Maste // See if we can find a "next range" breakpoint:
57ac7ddfbfSEd Maste SetNextBranchBreakpoint();
58ac7ddfbfSEd Maste }
59ac7ddfbfSEd Maste
ValidatePlan(Stream * error)60*b5893f02SDimitry Andric bool ThreadPlanStepRange::ValidatePlan(Stream *error) {
61*b5893f02SDimitry Andric if (m_could_not_resolve_hw_bp) {
62*b5893f02SDimitry Andric if (error)
63*b5893f02SDimitry Andric error->PutCString(
64*b5893f02SDimitry Andric "Could not create hardware breakpoint for thread plan.");
65*b5893f02SDimitry Andric return false;
66*b5893f02SDimitry Andric }
67*b5893f02SDimitry Andric return true;
68*b5893f02SDimitry Andric }
69ac7ddfbfSEd Maste
ShouldReportStop(Event * event_ptr)70435933ddSDimitry Andric Vote ThreadPlanStepRange::ShouldReportStop(Event *event_ptr) {
71ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
72ac7ddfbfSEd Maste
73ac7ddfbfSEd Maste const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo;
74ac7ddfbfSEd Maste if (log)
75435933ddSDimitry Andric log->Printf("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n",
76435933ddSDimitry Andric vote);
77ac7ddfbfSEd Maste return vote;
78ac7ddfbfSEd Maste }
79ac7ddfbfSEd Maste
AddRange(const AddressRange & new_range)80435933ddSDimitry Andric void ThreadPlanStepRange::AddRange(const AddressRange &new_range) {
814ba319b5SDimitry Andric // For now I'm just adding the ranges. At some point we may want to condense
824ba319b5SDimitry Andric // the ranges if they overlap, though I don't think it is likely to be very
834ba319b5SDimitry Andric // important.
84ac7ddfbfSEd Maste m_address_ranges.push_back(new_range);
85ac7ddfbfSEd Maste
86435933ddSDimitry Andric // Fill the slot for this address range with an empty DisassemblerSP in the
874ba319b5SDimitry Andric // instruction ranges. I want the indices to match, but I don't want to do
884ba319b5SDimitry Andric // the work to disassemble this range if I don't step into it.
89ac7ddfbfSEd Maste m_instruction_ranges.push_back(DisassemblerSP());
90ac7ddfbfSEd Maste }
91ac7ddfbfSEd Maste
DumpRanges(Stream * s)92435933ddSDimitry Andric void ThreadPlanStepRange::DumpRanges(Stream *s) {
93ac7ddfbfSEd Maste size_t num_ranges = m_address_ranges.size();
94435933ddSDimitry Andric if (num_ranges == 1) {
95435933ddSDimitry Andric m_address_ranges[0].Dump(s, m_thread.CalculateTarget().get(),
96435933ddSDimitry Andric Address::DumpStyleLoadAddress);
97435933ddSDimitry Andric } else {
98435933ddSDimitry Andric for (size_t i = 0; i < num_ranges; i++) {
999f2f44ceSEd Maste s->Printf(" %" PRIu64 ": ", uint64_t(i));
100435933ddSDimitry Andric m_address_ranges[i].Dump(s, m_thread.CalculateTarget().get(),
101435933ddSDimitry Andric Address::DumpStyleLoadAddress);
102ac7ddfbfSEd Maste }
103ac7ddfbfSEd Maste }
104ac7ddfbfSEd Maste }
105ac7ddfbfSEd Maste
InRange()106435933ddSDimitry Andric bool ThreadPlanStepRange::InRange() {
107ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
108ac7ddfbfSEd Maste bool ret_value = false;
109ac7ddfbfSEd Maste
110ac7ddfbfSEd Maste lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC();
111ac7ddfbfSEd Maste
112ac7ddfbfSEd Maste size_t num_ranges = m_address_ranges.size();
113435933ddSDimitry Andric for (size_t i = 0; i < num_ranges; i++) {
114435933ddSDimitry Andric ret_value = m_address_ranges[i].ContainsLoadAddress(
115435933ddSDimitry Andric pc_load_addr, m_thread.CalculateTarget().get());
116ac7ddfbfSEd Maste if (ret_value)
117ac7ddfbfSEd Maste break;
118ac7ddfbfSEd Maste }
119ac7ddfbfSEd Maste
120435933ddSDimitry Andric if (!ret_value && !m_given_ranges_only) {
121ac7ddfbfSEd Maste // See if we've just stepped to another part of the same line number...
122ac7ddfbfSEd Maste StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();
123ac7ddfbfSEd Maste
124435933ddSDimitry Andric SymbolContext new_context(
125435933ddSDimitry Andric frame->GetSymbolContext(eSymbolContextEverything));
126435933ddSDimitry Andric if (m_addr_context.line_entry.IsValid() &&
127435933ddSDimitry Andric new_context.line_entry.IsValid()) {
128435933ddSDimitry Andric if (m_addr_context.line_entry.original_file ==
129435933ddSDimitry Andric new_context.line_entry.original_file) {
130435933ddSDimitry Andric if (m_addr_context.line_entry.line == new_context.line_entry.line) {
131ac7ddfbfSEd Maste m_addr_context = new_context;
132435933ddSDimitry Andric AddRange(
133435933ddSDimitry Andric m_addr_context.line_entry.GetSameLineContiguousAddressRange());
134ac7ddfbfSEd Maste ret_value = true;
135435933ddSDimitry Andric if (log) {
136ac7ddfbfSEd Maste StreamString s;
137435933ddSDimitry Andric m_addr_context.line_entry.Dump(&s, m_thread.CalculateTarget().get(),
138435933ddSDimitry Andric true, Address::DumpStyleLoadAddress,
139435933ddSDimitry Andric Address::DumpStyleLoadAddress, true);
140ac7ddfbfSEd Maste
141435933ddSDimitry Andric log->Printf(
142435933ddSDimitry Andric "Step range plan stepped to another range of same line: %s",
143435933ddSDimitry Andric s.GetData());
144ac7ddfbfSEd Maste }
145435933ddSDimitry Andric } else if (new_context.line_entry.line == 0) {
14635617911SEd Maste new_context.line_entry.line = m_addr_context.line_entry.line;
14735617911SEd Maste m_addr_context = new_context;
148435933ddSDimitry Andric AddRange(
149435933ddSDimitry Andric m_addr_context.line_entry.GetSameLineContiguousAddressRange());
15035617911SEd Maste ret_value = true;
151435933ddSDimitry Andric if (log) {
15235617911SEd Maste StreamString s;
153435933ddSDimitry Andric m_addr_context.line_entry.Dump(&s, m_thread.CalculateTarget().get(),
154435933ddSDimitry Andric true, Address::DumpStyleLoadAddress,
155435933ddSDimitry Andric Address::DumpStyleLoadAddress, true);
15635617911SEd Maste
157435933ddSDimitry Andric log->Printf("Step range plan stepped to a range at linenumber 0 "
158435933ddSDimitry Andric "stepping through that range: %s",
159435933ddSDimitry Andric s.GetData());
16035617911SEd Maste }
161435933ddSDimitry Andric } else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(
162435933ddSDimitry Andric m_thread.CalculateTarget().get()) != pc_load_addr) {
163435933ddSDimitry Andric // Another thing that sometimes happens here is that we step out of
1644ba319b5SDimitry Andric // one line into the MIDDLE of another line. So far I mostly see
1654ba319b5SDimitry Andric // this due to bugs in the debug information. But we probably don't
1664ba319b5SDimitry Andric // want to be in the middle of a line range, so in that case reset
1674ba319b5SDimitry Andric // the stepping range to the line we've stepped into the middle of
1684ba319b5SDimitry Andric // and continue.
169ac7ddfbfSEd Maste m_addr_context = new_context;
170ac7ddfbfSEd Maste m_address_ranges.clear();
171ac7ddfbfSEd Maste AddRange(m_addr_context.line_entry.range);
172ac7ddfbfSEd Maste ret_value = true;
173435933ddSDimitry Andric if (log) {
174ac7ddfbfSEd Maste StreamString s;
175435933ddSDimitry Andric m_addr_context.line_entry.Dump(&s, m_thread.CalculateTarget().get(),
176435933ddSDimitry Andric true, Address::DumpStyleLoadAddress,
177435933ddSDimitry Andric Address::DumpStyleLoadAddress, true);
178ac7ddfbfSEd Maste
179435933ddSDimitry Andric log->Printf("Step range plan stepped to the middle of new "
180435933ddSDimitry Andric "line(%d): %s, continuing to clear this line.",
181435933ddSDimitry Andric new_context.line_entry.line, s.GetData());
182ac7ddfbfSEd Maste }
183ac7ddfbfSEd Maste }
184ac7ddfbfSEd Maste }
185ac7ddfbfSEd Maste }
186ac7ddfbfSEd Maste }
187ac7ddfbfSEd Maste
188ac7ddfbfSEd Maste if (!ret_value && log)
189ac7ddfbfSEd Maste log->Printf("Step range plan out of range to 0x%" PRIx64, pc_load_addr);
190ac7ddfbfSEd Maste
191ac7ddfbfSEd Maste return ret_value;
192ac7ddfbfSEd Maste }
193ac7ddfbfSEd Maste
InSymbol()194435933ddSDimitry Andric bool ThreadPlanStepRange::InSymbol() {
195ac7ddfbfSEd Maste lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
196435933ddSDimitry Andric if (m_addr_context.function != nullptr) {
197435933ddSDimitry Andric return m_addr_context.function->GetAddressRange().ContainsLoadAddress(
198435933ddSDimitry Andric cur_pc, m_thread.CalculateTarget().get());
199435933ddSDimitry Andric } else if (m_addr_context.symbol && m_addr_context.symbol->ValueIsAddress()) {
200435933ddSDimitry Andric AddressRange range(m_addr_context.symbol->GetAddressRef(),
201435933ddSDimitry Andric m_addr_context.symbol->GetByteSize());
202ac7ddfbfSEd Maste return range.ContainsLoadAddress(cur_pc, m_thread.CalculateTarget().get());
203ac7ddfbfSEd Maste }
204ac7ddfbfSEd Maste return false;
205ac7ddfbfSEd Maste }
206ac7ddfbfSEd Maste
207435933ddSDimitry Andric // FIXME: This should also handle inlining if we aren't going to do inlining in
208435933ddSDimitry Andric // the
209ac7ddfbfSEd Maste // main stack.
210ac7ddfbfSEd Maste //
211ac7ddfbfSEd Maste // Ideally we should remember the whole stack frame list, and then compare that
212ac7ddfbfSEd Maste // to the current list.
213ac7ddfbfSEd Maste
CompareCurrentFrameToStartFrame()214435933ddSDimitry Andric lldb::FrameComparison ThreadPlanStepRange::CompareCurrentFrameToStartFrame() {
215ac7ddfbfSEd Maste FrameComparison frame_order;
216ac7ddfbfSEd Maste
217ac7ddfbfSEd Maste StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
218ac7ddfbfSEd Maste
219435933ddSDimitry Andric if (cur_frame_id == m_stack_id) {
220ac7ddfbfSEd Maste frame_order = eFrameCompareEqual;
221435933ddSDimitry Andric } else if (cur_frame_id < m_stack_id) {
222ac7ddfbfSEd Maste frame_order = eFrameCompareYounger;
223435933ddSDimitry Andric } else {
2240127ef0fSEd Maste StackFrameSP cur_parent_frame = m_thread.GetStackFrameAtIndex(1);
2250127ef0fSEd Maste StackID cur_parent_id;
2260127ef0fSEd Maste if (cur_parent_frame)
2270127ef0fSEd Maste cur_parent_id = cur_parent_frame->GetStackID();
228435933ddSDimitry Andric if (m_parent_stack_id.IsValid() && cur_parent_id.IsValid() &&
229435933ddSDimitry Andric m_parent_stack_id == cur_parent_id)
2300127ef0fSEd Maste frame_order = eFrameCompareSameParent;
2310127ef0fSEd Maste else
232ac7ddfbfSEd Maste frame_order = eFrameCompareOlder;
233ac7ddfbfSEd Maste }
234ac7ddfbfSEd Maste return frame_order;
235ac7ddfbfSEd Maste }
236ac7ddfbfSEd Maste
StopOthers()237435933ddSDimitry Andric bool ThreadPlanStepRange::StopOthers() {
238435933ddSDimitry Andric return (m_stop_others == lldb::eOnlyThisThread ||
239435933ddSDimitry Andric m_stop_others == lldb::eOnlyDuringStepping);
240ac7ddfbfSEd Maste }
241ac7ddfbfSEd Maste
GetInstructionsForAddress(lldb::addr_t addr,size_t & range_index,size_t & insn_offset)242435933ddSDimitry Andric InstructionList *ThreadPlanStepRange::GetInstructionsForAddress(
243435933ddSDimitry Andric lldb::addr_t addr, size_t &range_index, size_t &insn_offset) {
244ac7ddfbfSEd Maste size_t num_ranges = m_address_ranges.size();
245435933ddSDimitry Andric for (size_t i = 0; i < num_ranges; i++) {
246435933ddSDimitry Andric if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) {
247ac7ddfbfSEd Maste // Some joker added a zero size range to the stepping range...
248ac7ddfbfSEd Maste if (m_address_ranges[i].GetByteSize() == 0)
2499f2f44ceSEd Maste return nullptr;
250ac7ddfbfSEd Maste
251435933ddSDimitry Andric if (!m_instruction_ranges[i]) {
252ac7ddfbfSEd Maste // Disassemble the address range given:
253ac7ddfbfSEd Maste ExecutionContext exe_ctx(m_thread.GetProcess());
2549f2f44ceSEd Maste const char *plugin_name = nullptr;
2559f2f44ceSEd Maste const char *flavor = nullptr;
25635617911SEd Maste const bool prefer_file_cache = true;
257435933ddSDimitry Andric m_instruction_ranges[i] = Disassembler::DisassembleRange(
258435933ddSDimitry Andric GetTarget().GetArchitecture(), plugin_name, flavor, exe_ctx,
259435933ddSDimitry Andric m_address_ranges[i], prefer_file_cache);
260ac7ddfbfSEd Maste }
261ac7ddfbfSEd Maste if (!m_instruction_ranges[i])
2629f2f44ceSEd Maste return nullptr;
263435933ddSDimitry Andric else {
264435933ddSDimitry Andric // Find where we are in the instruction list as well. If we aren't at
2654ba319b5SDimitry Andric // an instruction, return nullptr. In this case, we're probably lost,
2664ba319b5SDimitry Andric // and shouldn't try to do anything fancy.
267ac7ddfbfSEd Maste
268435933ddSDimitry Andric insn_offset =
269435933ddSDimitry Andric m_instruction_ranges[i]
270435933ddSDimitry Andric ->GetInstructionList()
271435933ddSDimitry Andric .GetIndexOfInstructionAtLoadAddress(addr, GetTarget());
272ac7ddfbfSEd Maste if (insn_offset == UINT32_MAX)
2739f2f44ceSEd Maste return nullptr;
274435933ddSDimitry Andric else {
275ac7ddfbfSEd Maste range_index = i;
276ac7ddfbfSEd Maste return &m_instruction_ranges[i]->GetInstructionList();
277ac7ddfbfSEd Maste }
278ac7ddfbfSEd Maste }
279ac7ddfbfSEd Maste }
280ac7ddfbfSEd Maste }
2819f2f44ceSEd Maste return nullptr;
282ac7ddfbfSEd Maste }
283ac7ddfbfSEd Maste
ClearNextBranchBreakpoint()284435933ddSDimitry Andric void ThreadPlanStepRange::ClearNextBranchBreakpoint() {
285435933ddSDimitry Andric if (m_next_branch_bp_sp) {
286ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
287ac7ddfbfSEd Maste if (log)
288435933ddSDimitry Andric log->Printf("Removing next branch breakpoint: %d.",
289435933ddSDimitry Andric m_next_branch_bp_sp->GetID());
290ac7ddfbfSEd Maste GetTarget().RemoveBreakpointByID(m_next_branch_bp_sp->GetID());
291ac7ddfbfSEd Maste m_next_branch_bp_sp.reset();
292*b5893f02SDimitry Andric m_could_not_resolve_hw_bp = false;
293ac7ddfbfSEd Maste }
294ac7ddfbfSEd Maste }
295ac7ddfbfSEd Maste
SetNextBranchBreakpoint()296435933ddSDimitry Andric bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
297ac7ddfbfSEd Maste if (m_next_branch_bp_sp)
298ac7ddfbfSEd Maste return true;
299ac7ddfbfSEd Maste
300ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
301435933ddSDimitry Andric // Stepping through ranges using breakpoints doesn't work yet, but with this
3024ba319b5SDimitry Andric // off we fall back to instruction single stepping.
303ac7ddfbfSEd Maste if (!m_use_fast_step)
304ac7ddfbfSEd Maste return false;
305ac7ddfbfSEd Maste
306ac7ddfbfSEd Maste lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC();
307435933ddSDimitry Andric // Find the current address in our address ranges, and fetch the disassembly
308435933ddSDimitry Andric // if we haven't already:
309ac7ddfbfSEd Maste size_t pc_index;
310ac7ddfbfSEd Maste size_t range_index;
311435933ddSDimitry Andric InstructionList *instructions =
312435933ddSDimitry Andric GetInstructionsForAddress(cur_addr, range_index, pc_index);
3139f2f44ceSEd Maste if (instructions == nullptr)
314ac7ddfbfSEd Maste return false;
315435933ddSDimitry Andric else {
3161c3bbb01SEd Maste Target &target = GetThread().GetProcess()->GetTarget();
317ac7ddfbfSEd Maste uint32_t branch_index;
318435933ddSDimitry Andric branch_index =
319435933ddSDimitry Andric instructions->GetIndexOfNextBranchInstruction(pc_index, target);
320ac7ddfbfSEd Maste
321ac7ddfbfSEd Maste Address run_to_address;
322ac7ddfbfSEd Maste
323ac7ddfbfSEd Maste // If we didn't find a branch, run to the end of the range.
324435933ddSDimitry Andric if (branch_index == UINT32_MAX) {
3259f2f44ceSEd Maste uint32_t last_index = instructions->GetSize() - 1;
326435933ddSDimitry Andric if (last_index - pc_index > 1) {
327435933ddSDimitry Andric InstructionSP last_inst =
328435933ddSDimitry Andric instructions->GetInstructionAtIndex(last_index);
3299f2f44ceSEd Maste size_t last_inst_size = last_inst->GetOpcode().GetByteSize();
3309f2f44ceSEd Maste run_to_address = last_inst->GetAddress();
3319f2f44ceSEd Maste run_to_address.Slide(last_inst_size);
3329f2f44ceSEd Maste }
333435933ddSDimitry Andric } else if (branch_index - pc_index > 1) {
334435933ddSDimitry Andric run_to_address =
335435933ddSDimitry Andric instructions->GetInstructionAtIndex(branch_index)->GetAddress();
336ac7ddfbfSEd Maste }
337ac7ddfbfSEd Maste
338435933ddSDimitry Andric if (run_to_address.IsValid()) {
339ac7ddfbfSEd Maste const bool is_internal = true;
340435933ddSDimitry Andric m_next_branch_bp_sp =
341435933ddSDimitry Andric GetTarget().CreateBreakpoint(run_to_address, is_internal, false);
342435933ddSDimitry Andric if (m_next_branch_bp_sp) {
343*b5893f02SDimitry Andric
344*b5893f02SDimitry Andric if (m_next_branch_bp_sp->IsHardware() &&
345*b5893f02SDimitry Andric !m_next_branch_bp_sp->HasResolvedLocations())
346*b5893f02SDimitry Andric m_could_not_resolve_hw_bp = true;
347*b5893f02SDimitry Andric
348435933ddSDimitry Andric if (log) {
349ac7ddfbfSEd Maste lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID;
350435933ddSDimitry Andric BreakpointLocationSP bp_loc =
351435933ddSDimitry Andric m_next_branch_bp_sp->GetLocationAtIndex(0);
352435933ddSDimitry Andric if (bp_loc) {
353ac7ddfbfSEd Maste BreakpointSiteSP bp_site = bp_loc->GetBreakpointSite();
354435933ddSDimitry Andric if (bp_site) {
355ac7ddfbfSEd Maste bp_site_id = bp_site->GetID();
356ac7ddfbfSEd Maste }
357ac7ddfbfSEd Maste }
358435933ddSDimitry Andric log->Printf("ThreadPlanStepRange::SetNextBranchBreakpoint - Setting "
359435933ddSDimitry Andric "breakpoint %d (site %d) to run to address 0x%" PRIx64,
360435933ddSDimitry Andric m_next_branch_bp_sp->GetID(), bp_site_id,
361435933ddSDimitry Andric run_to_address.GetLoadAddress(
362435933ddSDimitry Andric &m_thread.GetProcess()->GetTarget()));
363ac7ddfbfSEd Maste }
364*b5893f02SDimitry Andric
365ac7ddfbfSEd Maste m_next_branch_bp_sp->SetThreadID(m_thread.GetID());
366ac7ddfbfSEd Maste m_next_branch_bp_sp->SetBreakpointKind("next-branch-location");
367*b5893f02SDimitry Andric
368ac7ddfbfSEd Maste return true;
369435933ddSDimitry Andric } else
370ac7ddfbfSEd Maste return false;
371ac7ddfbfSEd Maste }
372ac7ddfbfSEd Maste }
373ac7ddfbfSEd Maste return false;
374ac7ddfbfSEd Maste }
375ac7ddfbfSEd Maste
NextRangeBreakpointExplainsStop(lldb::StopInfoSP stop_info_sp)376435933ddSDimitry Andric bool ThreadPlanStepRange::NextRangeBreakpointExplainsStop(
377435933ddSDimitry Andric lldb::StopInfoSP stop_info_sp) {
378ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
379ac7ddfbfSEd Maste if (!m_next_branch_bp_sp)
380ac7ddfbfSEd Maste return false;
381ac7ddfbfSEd Maste
382ac7ddfbfSEd Maste break_id_t bp_site_id = stop_info_sp->GetValue();
383435933ddSDimitry Andric BreakpointSiteSP bp_site_sp =
384435933ddSDimitry Andric m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id);
385ac7ddfbfSEd Maste if (!bp_site_sp)
386ac7ddfbfSEd Maste return false;
387ac7ddfbfSEd Maste else if (!bp_site_sp->IsBreakpointAtThisSite(m_next_branch_bp_sp->GetID()))
388ac7ddfbfSEd Maste return false;
389435933ddSDimitry Andric else {
390ac7ddfbfSEd Maste // If we've hit the next branch breakpoint, then clear it.
391ac7ddfbfSEd Maste size_t num_owners = bp_site_sp->GetNumberOfOwners();
392ac7ddfbfSEd Maste bool explains_stop = true;
393435933ddSDimitry Andric // If all the owners are internal, then we are probably just stepping over
3944ba319b5SDimitry Andric // this range from multiple threads, or multiple frames, so we want to
3954ba319b5SDimitry Andric // continue. If one is not internal, then we should not explain the stop,
396ac7ddfbfSEd Maste // and let the user breakpoint handle the stop.
397435933ddSDimitry Andric for (size_t i = 0; i < num_owners; i++) {
398435933ddSDimitry Andric if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) {
399ac7ddfbfSEd Maste explains_stop = false;
400ac7ddfbfSEd Maste break;
401ac7ddfbfSEd Maste }
402ac7ddfbfSEd Maste }
403ac7ddfbfSEd Maste if (log)
404435933ddSDimitry Andric log->Printf("ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit "
405435933ddSDimitry Andric "next range breakpoint which has %" PRIu64
406435933ddSDimitry Andric " owners - explains stop: %u.",
407435933ddSDimitry Andric (uint64_t)num_owners, explains_stop);
408ac7ddfbfSEd Maste ClearNextBranchBreakpoint();
409ac7ddfbfSEd Maste return explains_stop;
410ac7ddfbfSEd Maste }
411ac7ddfbfSEd Maste }
412ac7ddfbfSEd Maste
WillStop()413435933ddSDimitry Andric bool ThreadPlanStepRange::WillStop() { return true; }
414ac7ddfbfSEd Maste
GetPlanRunState()415435933ddSDimitry Andric StateType ThreadPlanStepRange::GetPlanRunState() {
416ac7ddfbfSEd Maste if (m_next_branch_bp_sp)
417ac7ddfbfSEd Maste return eStateRunning;
418ac7ddfbfSEd Maste else
419ac7ddfbfSEd Maste return eStateStepping;
420ac7ddfbfSEd Maste }
421ac7ddfbfSEd Maste
MischiefManaged()422435933ddSDimitry Andric bool ThreadPlanStepRange::MischiefManaged() {
423435933ddSDimitry Andric // If we have pushed some plans between ShouldStop & MischiefManaged, then
424435933ddSDimitry Andric // we're not done...
425435933ddSDimitry Andric // I do this check first because we might have stepped somewhere that will
426435933ddSDimitry Andric // fool InRange into
427435933ddSDimitry Andric // thinking it needs to step past the end of that line. This happens, for
4284ba319b5SDimitry Andric // instance, when stepping over inlined code that is in the middle of the
4294ba319b5SDimitry Andric // current line.
430ac7ddfbfSEd Maste
431ac7ddfbfSEd Maste if (!m_no_more_plans)
432ac7ddfbfSEd Maste return false;
433ac7ddfbfSEd Maste
434ac7ddfbfSEd Maste bool done = true;
435435933ddSDimitry Andric if (!IsPlanComplete()) {
436435933ddSDimitry Andric if (InRange()) {
437ac7ddfbfSEd Maste done = false;
438435933ddSDimitry Andric } else {
439ac7ddfbfSEd Maste FrameComparison frame_order = CompareCurrentFrameToStartFrame();
4409f2f44ceSEd Maste done = (frame_order != eFrameCompareOlder) ? m_no_more_plans : true;
441ac7ddfbfSEd Maste }
442ac7ddfbfSEd Maste }
443ac7ddfbfSEd Maste
444435933ddSDimitry Andric if (done) {
445ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
446ac7ddfbfSEd Maste if (log)
447ac7ddfbfSEd Maste log->Printf("Completed step through range plan.");
448ac7ddfbfSEd Maste ClearNextBranchBreakpoint();
449ac7ddfbfSEd Maste ThreadPlan::MischiefManaged();
450ac7ddfbfSEd Maste return true;
451435933ddSDimitry Andric } else {
452ac7ddfbfSEd Maste return false;
453ac7ddfbfSEd Maste }
454ac7ddfbfSEd Maste }
455ac7ddfbfSEd Maste
IsPlanStale()456435933ddSDimitry Andric bool ThreadPlanStepRange::IsPlanStale() {
457ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
458ac7ddfbfSEd Maste FrameComparison frame_order = CompareCurrentFrameToStartFrame();
459ac7ddfbfSEd Maste
460435933ddSDimitry Andric if (frame_order == eFrameCompareOlder) {
461435933ddSDimitry Andric if (log) {
462435933ddSDimitry Andric log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've "
463435933ddSDimitry Andric "stepped out.");
464ac7ddfbfSEd Maste }
465ac7ddfbfSEd Maste return true;
466435933ddSDimitry Andric } else if (frame_order == eFrameCompareEqual && InSymbol()) {
4674ba319b5SDimitry Andric // If we are not in a place we should step through, we've gotten stale. One
4684ba319b5SDimitry Andric // tricky bit here is that some stubs don't push a frame, so we should.
469ac7ddfbfSEd Maste // check that we are in the same symbol.
470435933ddSDimitry Andric if (!InRange()) {
471f678e45dSDimitry Andric // Set plan Complete when we reach next instruction just after the range
472f678e45dSDimitry Andric lldb::addr_t addr = m_thread.GetRegisterContext()->GetPC() - 1;
473f678e45dSDimitry Andric size_t num_ranges = m_address_ranges.size();
474f678e45dSDimitry Andric for (size_t i = 0; i < num_ranges; i++) {
475f678e45dSDimitry Andric bool in_range = m_address_ranges[i].ContainsLoadAddress(
476f678e45dSDimitry Andric addr, m_thread.CalculateTarget().get());
477f678e45dSDimitry Andric if (in_range) {
478f678e45dSDimitry Andric SetPlanComplete();
479f678e45dSDimitry Andric }
480f678e45dSDimitry Andric }
481ac7ddfbfSEd Maste return true;
482ac7ddfbfSEd Maste }
483ac7ddfbfSEd Maste }
484ac7ddfbfSEd Maste return false;
485ac7ddfbfSEd Maste }
486