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