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