1 //===-- ThreadPlanStepRange.cpp ---------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Target/ThreadPlanStepRange.h"
15 #include "lldb/Breakpoint/BreakpointLocation.h"
16 #include "lldb/Breakpoint/BreakpointSite.h"
17 #include "lldb/Core/Disassembler.h"
18 #include "lldb/Core/Log.h"
19 #include "lldb/Core/Stream.h"
20 #include "lldb/Symbol/Function.h"
21 #include "lldb/Symbol/Symbol.h"
22 #include "lldb/Target/ExecutionContext.h"
23 #include "lldb/Target/Process.h"
24 #include "lldb/Target/RegisterContext.h"
25 #include "lldb/Target/StopInfo.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Target/Thread.h"
28 #include "lldb/Target/ThreadPlanRunToAddress.h"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 //----------------------------------------------------------------------
34 // ThreadPlanStepRange: Step through a stack range, either stepping over or into
35 // based on the value of \a type.
36 //----------------------------------------------------------------------
37 
38 ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind,
39                                           const char *name,
40                                           Thread &thread,
41                                           const AddressRange &range,
42                                           const SymbolContext &addr_context,
43                                           lldb::RunMode stop_others,
44                                           bool given_ranges_only) :
45     ThreadPlan (kind, name, thread, eVoteNoOpinion, eVoteNoOpinion),
46     m_addr_context (addr_context),
47     m_address_ranges (),
48     m_stop_others (stop_others),
49     m_stack_id (),
50     m_parent_stack_id(),
51     m_no_more_plans (false),
52     m_first_run_event (true),
53     m_use_fast_step(false),
54     m_given_ranges_only (given_ranges_only)
55 {
56     m_use_fast_step = GetTarget().GetUseFastStepping();
57     AddRange(range);
58     m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
59     StackFrameSP parent_stack = m_thread.GetStackFrameAtIndex(1);
60     if (parent_stack)
61       m_parent_stack_id = parent_stack->GetStackID();
62 }
63 
64 ThreadPlanStepRange::~ThreadPlanStepRange ()
65 {
66     ClearNextBranchBreakpoint();
67 }
68 
69 void
70 ThreadPlanStepRange::DidPush ()
71 {
72     // See if we can find a "next range" breakpoint:
73     SetNextBranchBreakpoint();
74 }
75 
76 bool
77 ThreadPlanStepRange::ValidatePlan (Stream *error)
78 {
79     return true;
80 }
81 
82 Vote
83 ThreadPlanStepRange::ShouldReportStop (Event *event_ptr)
84 {
85     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
86 
87     const Vote vote = IsPlanComplete() ? eVoteYes : eVoteNo;
88     if (log)
89         log->Printf ("ThreadPlanStepRange::ShouldReportStop() returning vote %i\n", vote);
90     return vote;
91 }
92 
93 void
94 ThreadPlanStepRange::AddRange(const AddressRange &new_range)
95 {
96     // For now I'm just adding the ranges.  At some point we may want to
97     // condense the ranges if they overlap, though I don't think it is likely
98     // to be very important.
99     m_address_ranges.push_back (new_range);
100 
101     // Fill the slot for this address range with an empty DisassemblerSP in the instruction ranges. I want the
102     // indices to match, but I don't want to do the work to disassemble this range if I don't step into it.
103     m_instruction_ranges.push_back (DisassemblerSP());
104 }
105 
106 void
107 ThreadPlanStepRange::DumpRanges(Stream *s)
108 {
109     size_t num_ranges = m_address_ranges.size();
110     if (num_ranges == 1)
111     {
112         m_address_ranges[0].Dump (s, m_thread.CalculateTarget().get(), Address::DumpStyleLoadAddress);
113     }
114     else
115     {
116         for (size_t i = 0; i < num_ranges; i++)
117         {
118             s->Printf(" %" PRIu64 ": ", uint64_t(i));
119             m_address_ranges[i].Dump (s, m_thread.CalculateTarget().get(), Address::DumpStyleLoadAddress);
120         }
121     }
122 }
123 
124 bool
125 ThreadPlanStepRange::InRange ()
126 {
127     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
128     bool ret_value = false;
129 
130     lldb::addr_t pc_load_addr = m_thread.GetRegisterContext()->GetPC();
131 
132     size_t num_ranges = m_address_ranges.size();
133     for (size_t i = 0; i < num_ranges; i++)
134     {
135         ret_value = m_address_ranges[i].ContainsLoadAddress(pc_load_addr, m_thread.CalculateTarget().get());
136         if (ret_value)
137             break;
138     }
139 
140     if (!ret_value && !m_given_ranges_only)
141     {
142         // See if we've just stepped to another part of the same line number...
143         StackFrame *frame = m_thread.GetStackFrameAtIndex(0).get();
144 
145         SymbolContext new_context(frame->GetSymbolContext(eSymbolContextEverything));
146         if (m_addr_context.line_entry.IsValid() && new_context.line_entry.IsValid())
147         {
148             if (m_addr_context.line_entry.original_file == new_context.line_entry.original_file)
149             {
150                 if (m_addr_context.line_entry.line == new_context.line_entry.line)
151                 {
152                     m_addr_context = new_context;
153                     AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange());
154                     ret_value = true;
155                     if (log)
156                     {
157                         StreamString s;
158                         m_addr_context.line_entry.Dump (&s,
159                                                         m_thread.CalculateTarget().get(),
160                                                         true,
161                                                         Address::DumpStyleLoadAddress,
162                                                         Address::DumpStyleLoadAddress,
163                                                         true);
164 
165                         log->Printf ("Step range plan stepped to another range of same line: %s", s.GetData());
166                     }
167                 }
168                 else if (new_context.line_entry.line == 0)
169                 {
170                     new_context.line_entry.line = m_addr_context.line_entry.line;
171                     m_addr_context = new_context;
172                     AddRange(m_addr_context.line_entry.GetSameLineContiguousAddressRange());
173                     ret_value = true;
174                     if (log)
175                     {
176                         StreamString s;
177                         m_addr_context.line_entry.Dump (&s,
178                                                         m_thread.CalculateTarget().get(),
179                                                         true,
180                                                         Address::DumpStyleLoadAddress,
181                                                         Address::DumpStyleLoadAddress,
182                                                         true);
183 
184                         log->Printf ("Step range plan stepped to a range at linenumber 0 stepping through that range: %s", s.GetData());
185                     }
186                 }
187                 else if (new_context.line_entry.range.GetBaseAddress().GetLoadAddress(m_thread.CalculateTarget().get())
188                          != pc_load_addr)
189                 {
190                     // Another thing that sometimes happens here is that we step out of one line into the MIDDLE of another
191                     // line.  So far I mostly see this due to bugs in the debug information.
192                     // But we probably don't want to be in the middle of a line range, so in that case reset the stepping
193                     // range to the line we've stepped into the middle of and continue.
194                     m_addr_context = new_context;
195                     m_address_ranges.clear();
196                     AddRange(m_addr_context.line_entry.range);
197                     ret_value = true;
198                     if (log)
199                     {
200                         StreamString s;
201                         m_addr_context.line_entry.Dump (&s,
202                                                         m_thread.CalculateTarget().get(),
203                                                         true,
204                                                         Address::DumpStyleLoadAddress,
205                                                         Address::DumpStyleLoadAddress,
206                                                         true);
207 
208                         log->Printf ("Step range plan stepped to the middle of new line(%d): %s, continuing to clear this line.",
209                                      new_context.line_entry.line,
210                                      s.GetData());
211                     }
212                 }
213             }
214         }
215     }
216 
217     if (!ret_value && log)
218         log->Printf ("Step range plan out of range to 0x%" PRIx64, pc_load_addr);
219 
220     return ret_value;
221 }
222 
223 bool
224 ThreadPlanStepRange::InSymbol()
225 {
226     lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC();
227     if (m_addr_context.function != nullptr)
228     {
229         return m_addr_context.function->GetAddressRange().ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get());
230     }
231     else if (m_addr_context.symbol && m_addr_context.symbol->ValueIsAddress())
232     {
233         AddressRange range(m_addr_context.symbol->GetAddressRef(), m_addr_context.symbol->GetByteSize());
234         return range.ContainsLoadAddress (cur_pc, m_thread.CalculateTarget().get());
235     }
236     return false;
237 }
238 
239 // FIXME: This should also handle inlining if we aren't going to do inlining in the
240 // main stack.
241 //
242 // Ideally we should remember the whole stack frame list, and then compare that
243 // to the current list.
244 
245 lldb::FrameComparison
246 ThreadPlanStepRange::CompareCurrentFrameToStartFrame()
247 {
248     FrameComparison frame_order;
249 
250     StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
251 
252     if (cur_frame_id == m_stack_id)
253     {
254         frame_order = eFrameCompareEqual;
255     }
256     else if (cur_frame_id < m_stack_id)
257     {
258         frame_order = eFrameCompareYounger;
259     }
260     else
261     {
262         StackFrameSP cur_parent_frame = m_thread.GetStackFrameAtIndex(1);
263         StackID cur_parent_id;
264         if (cur_parent_frame)
265           cur_parent_id = cur_parent_frame->GetStackID();
266         if (m_parent_stack_id.IsValid()
267             && cur_parent_id.IsValid()
268             && m_parent_stack_id == cur_parent_id)
269            frame_order = eFrameCompareSameParent;
270         else
271             frame_order = eFrameCompareOlder;
272     }
273     return frame_order;
274 }
275 
276 bool
277 ThreadPlanStepRange::StopOthers ()
278 {
279     return (m_stop_others == lldb::eOnlyThisThread || m_stop_others == lldb::eOnlyDuringStepping);
280 }
281 
282 InstructionList *
283 ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_index, size_t &insn_offset)
284 {
285     size_t num_ranges = m_address_ranges.size();
286     for (size_t i = 0; i < num_ranges; i++)
287     {
288         if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget()))
289         {
290             // Some joker added a zero size range to the stepping range...
291             if (m_address_ranges[i].GetByteSize() == 0)
292                 return nullptr;
293 
294             if (!m_instruction_ranges[i])
295             {
296                 //Disassemble the address range given:
297                 ExecutionContext exe_ctx (m_thread.GetProcess());
298                 const char *plugin_name = nullptr;
299                 const char *flavor = nullptr;
300                 const bool prefer_file_cache = true;
301                 m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(),
302                                                                          plugin_name,
303                                                                          flavor,
304                                                                          exe_ctx,
305                                                                          m_address_ranges[i],
306                                                                          prefer_file_cache);
307             }
308             if (!m_instruction_ranges[i])
309                 return nullptr;
310             else
311             {
312                 // Find where we are in the instruction list as well.  If we aren't at an instruction,
313                 // return nullptr. In this case, we're probably lost, and shouldn't try to do anything fancy.
314 
315                 insn_offset = m_instruction_ranges[i]->GetInstructionList().GetIndexOfInstructionAtLoadAddress(addr, GetTarget());
316                 if (insn_offset == UINT32_MAX)
317                     return nullptr;
318                 else
319                 {
320                     range_index = i;
321                     return &m_instruction_ranges[i]->GetInstructionList();
322                 }
323             }
324         }
325     }
326     return nullptr;
327 }
328 
329 void
330 ThreadPlanStepRange::ClearNextBranchBreakpoint()
331 {
332     if (m_next_branch_bp_sp)
333     {
334         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
335         if (log)
336             log->Printf ("Removing next branch breakpoint: %d.", m_next_branch_bp_sp->GetID());
337         GetTarget().RemoveBreakpointByID (m_next_branch_bp_sp->GetID());
338         m_next_branch_bp_sp.reset();
339     }
340 }
341 
342 bool
343 ThreadPlanStepRange::SetNextBranchBreakpoint ()
344 {
345     if (m_next_branch_bp_sp)
346         return true;
347 
348     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
349     // Stepping through ranges using breakpoints doesn't work yet, but with this off we fall back to instruction
350     // single stepping.
351     if (!m_use_fast_step)
352          return false;
353 
354     lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC();
355     // Find the current address in our address ranges, and fetch the disassembly if we haven't already:
356     size_t pc_index;
357     size_t range_index;
358     InstructionList *instructions = GetInstructionsForAddress (cur_addr, range_index, pc_index);
359     if (instructions == nullptr)
360         return false;
361     else
362     {
363         Target &target = GetThread().GetProcess()->GetTarget();
364         uint32_t branch_index;
365         branch_index = instructions->GetIndexOfNextBranchInstruction (pc_index, target);
366 
367         Address run_to_address;
368 
369         // If we didn't find a branch, run to the end of the range.
370         if (branch_index == UINT32_MAX)
371         {
372             uint32_t last_index = instructions->GetSize() - 1;
373             if (last_index - pc_index > 1)
374             {
375                 InstructionSP last_inst = instructions->GetInstructionAtIndex(last_index);
376                 size_t last_inst_size = last_inst->GetOpcode().GetByteSize();
377                 run_to_address = last_inst->GetAddress();
378                 run_to_address.Slide(last_inst_size);
379             }
380         }
381         else if (branch_index - pc_index > 1)
382         {
383             run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress();
384         }
385 
386         if (run_to_address.IsValid())
387         {
388             const bool is_internal = true;
389             m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal, false);
390             if (m_next_branch_bp_sp)
391             {
392                 if (log)
393                 {
394                     lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID;
395                     BreakpointLocationSP bp_loc = m_next_branch_bp_sp->GetLocationAtIndex(0);
396                     if (bp_loc)
397                     {
398                         BreakpointSiteSP bp_site = bp_loc->GetBreakpointSite();
399                         if (bp_site)
400                         {
401                             bp_site_id = bp_site->GetID();
402                         }
403                     }
404                     log->Printf ("ThreadPlanStepRange::SetNextBranchBreakpoint - Setting breakpoint %d (site %d) to run to address 0x%" PRIx64,
405                                  m_next_branch_bp_sp->GetID(),
406                                  bp_site_id,
407                                  run_to_address.GetLoadAddress(&m_thread.GetProcess()->GetTarget()));
408                 }
409                 m_next_branch_bp_sp->SetThreadID(m_thread.GetID());
410                 m_next_branch_bp_sp->SetBreakpointKind ("next-branch-location");
411                 return true;
412             }
413             else
414                 return false;
415         }
416     }
417     return false;
418 }
419 
420 bool
421 ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp)
422 {
423     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
424     if (!m_next_branch_bp_sp)
425         return false;
426 
427     break_id_t bp_site_id = stop_info_sp->GetValue();
428     BreakpointSiteSP bp_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id);
429     if (!bp_site_sp)
430         return false;
431     else if (!bp_site_sp->IsBreakpointAtThisSite (m_next_branch_bp_sp->GetID()))
432         return false;
433     else
434     {
435         // If we've hit the next branch breakpoint, then clear it.
436         size_t num_owners = bp_site_sp->GetNumberOfOwners();
437         bool explains_stop = true;
438         // If all the owners are internal, then we are probably just stepping over this range from multiple threads,
439         // or multiple frames, so we want to continue.  If one is not internal, then we should not explain the stop,
440         // and let the user breakpoint handle the stop.
441         for (size_t i = 0; i < num_owners; i++)
442         {
443             if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
444             {
445                 explains_stop = false;
446                 break;
447             }
448         }
449         if (log)
450             log->Printf ("ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit next range breakpoint which has %" PRIu64 " owners - explains stop: %u.",
451                         (uint64_t)num_owners,
452                         explains_stop);
453         ClearNextBranchBreakpoint();
454         return  explains_stop;
455     }
456 }
457 
458 bool
459 ThreadPlanStepRange::WillStop ()
460 {
461     return true;
462 }
463 
464 StateType
465 ThreadPlanStepRange::GetPlanRunState ()
466 {
467     if (m_next_branch_bp_sp)
468         return eStateRunning;
469     else
470         return eStateStepping;
471 }
472 
473 bool
474 ThreadPlanStepRange::MischiefManaged ()
475 {
476     // If we have pushed some plans between ShouldStop & MischiefManaged, then we're not done...
477     // I do this check first because we might have stepped somewhere that will fool InRange into
478     // thinking it needs to step past the end of that line.  This happens, for instance, when stepping
479     // over inlined code that is in the middle of the current line.
480 
481     if (!m_no_more_plans)
482         return false;
483 
484     bool done = true;
485     if (!IsPlanComplete())
486     {
487         if (InRange())
488         {
489             done = false;
490         }
491         else
492         {
493             FrameComparison frame_order = CompareCurrentFrameToStartFrame();
494             done = (frame_order != eFrameCompareOlder) ? m_no_more_plans : true;
495         }
496     }
497 
498     if (done)
499     {
500         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
501         if (log)
502             log->Printf("Completed step through range plan.");
503         ClearNextBranchBreakpoint();
504         ThreadPlan::MischiefManaged ();
505         return true;
506     }
507     else
508     {
509         return false;
510     }
511 }
512 
513 bool
514 ThreadPlanStepRange::IsPlanStale ()
515 {
516     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
517     FrameComparison frame_order = CompareCurrentFrameToStartFrame();
518 
519     if (frame_order == eFrameCompareOlder)
520     {
521         if (log)
522         {
523             log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've stepped out.");
524         }
525         return true;
526     }
527     else if (frame_order == eFrameCompareEqual && InSymbol())
528     {
529         // If we are not in a place we should step through, we've gotten stale.
530         // One tricky bit here is that some stubs don't push a frame, so we should.
531         // check that we are in the same symbol.
532         if (!InRange())
533         {
534             return true;
535         }
536     }
537     return false;
538 }
539