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             branch_index = instructions->GetSize() - 1;
393             InstructionSP last_inst = instructions->GetInstructionAtIndex(branch_index);
394             size_t last_inst_size = last_inst->GetOpcode().GetByteSize();
395             run_to_address = last_inst->GetAddress();
396             run_to_address.Slide(last_inst_size);
397         }
398         else if (branch_index - pc_index > 1)
399         {
400             run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress();
401         }
402 
403         if (run_to_address.IsValid())
404         {
405             const bool is_internal = true;
406             m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal, false);
407             if (m_next_branch_bp_sp)
408             {
409                 if (log)
410                 {
411                     lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID;
412                     BreakpointLocationSP bp_loc = m_next_branch_bp_sp->GetLocationAtIndex(0);
413                     if (bp_loc)
414                     {
415                         BreakpointSiteSP bp_site = bp_loc->GetBreakpointSite();
416                         if (bp_site)
417                         {
418                             bp_site_id = bp_site->GetID();
419                         }
420                     }
421                     log->Printf ("ThreadPlanStepRange::SetNextBranchBreakpoint - Setting breakpoint %d (site %d) to run to address 0x%" PRIx64,
422                                  m_next_branch_bp_sp->GetID(),
423                                  bp_site_id,
424                                  run_to_address.GetLoadAddress(&m_thread.GetProcess()->GetTarget()));
425                 }
426                 m_next_branch_bp_sp->SetThreadID(m_thread.GetID());
427                 m_next_branch_bp_sp->SetBreakpointKind ("next-branch-location");
428                 return true;
429             }
430             else
431                 return false;
432         }
433     }
434     return false;
435 }
436 
437 bool
438 ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp)
439 {
440     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
441     if (!m_next_branch_bp_sp)
442         return false;
443 
444     break_id_t bp_site_id = stop_info_sp->GetValue();
445     BreakpointSiteSP bp_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id);
446     if (!bp_site_sp)
447         return false;
448     else if (!bp_site_sp->IsBreakpointAtThisSite (m_next_branch_bp_sp->GetID()))
449         return false;
450     else
451     {
452         // If we've hit the next branch breakpoint, then clear it.
453         size_t num_owners = bp_site_sp->GetNumberOfOwners();
454         bool explains_stop = true;
455         // If all the owners are internal, then we are probably just stepping over this range from multiple threads,
456         // or multiple frames, so we want to continue.  If one is not internal, then we should not explain the stop,
457         // and let the user breakpoint handle the stop.
458         for (size_t i = 0; i < num_owners; i++)
459         {
460             if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
461             {
462                 explains_stop = false;
463                 break;
464             }
465         }
466         if (log)
467             log->Printf ("ThreadPlanStepRange::NextRangeBreakpointExplainsStop - Hit next range breakpoint which has %" PRIu64 " owners - explains stop: %u.",
468                         (uint64_t)num_owners,
469                         explains_stop);
470         ClearNextBranchBreakpoint();
471         return  explains_stop;
472     }
473 }
474 
475 bool
476 ThreadPlanStepRange::WillStop ()
477 {
478     return true;
479 }
480 
481 StateType
482 ThreadPlanStepRange::GetPlanRunState ()
483 {
484     if (m_next_branch_bp_sp)
485         return eStateRunning;
486     else
487         return eStateStepping;
488 }
489 
490 bool
491 ThreadPlanStepRange::MischiefManaged ()
492 {
493     // If we have pushed some plans between ShouldStop & MischiefManaged, then we're not done...
494     // I do this check first because we might have stepped somewhere that will fool InRange into
495     // thinking it needs to step past the end of that line.  This happens, for instance, when stepping
496     // over inlined code that is in the middle of the current line.
497 
498     if (!m_no_more_plans)
499         return false;
500 
501     bool done = true;
502     if (!IsPlanComplete())
503     {
504         if (InRange())
505         {
506             done = false;
507         }
508         else
509         {
510             FrameComparison frame_order = CompareCurrentFrameToStartFrame();
511             if (frame_order != eFrameCompareOlder)
512             {
513                 if (m_no_more_plans)
514                     done = true;
515                 else
516                     done = false;
517             }
518             else
519                 done = true;
520         }
521     }
522 
523     if (done)
524     {
525         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
526         if (log)
527             log->Printf("Completed step through range plan.");
528         ClearNextBranchBreakpoint();
529         ThreadPlan::MischiefManaged ();
530         return true;
531     }
532     else
533     {
534         return false;
535     }
536 
537 }
538 
539 bool
540 ThreadPlanStepRange::IsPlanStale ()
541 {
542     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
543     FrameComparison frame_order = CompareCurrentFrameToStartFrame();
544 
545     if (frame_order == eFrameCompareOlder)
546     {
547         if (log)
548         {
549             log->Printf("ThreadPlanStepRange::IsPlanStale returning true, we've stepped out.");
550         }
551         return true;
552     }
553     else if (frame_order == eFrameCompareEqual && InSymbol())
554     {
555         // If we are not in a place we should step through, we've gotten stale.
556         // One tricky bit here is that some stubs don't push a frame, so we should.
557         // check that we are in the same symbol.
558         if (!InRange())
559         {
560             return true;
561         }
562     }
563     return false;
564 }
565