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