1 //===-- ThreadPlanShouldStopHere.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/RegisterContext.h"
11 #include "lldb/Target/Thread.h"
12 #include "lldb/Target/ThreadPlanShouldStopHere.h"
13 #include "lldb/Core/Log.h"
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 
18 // C Includes
19 // C++ Includes
20 // Other libraries and framework includes
21 // Project includes
22 
23 //----------------------------------------------------------------------
24 // ThreadPlanShouldStopHere constructor
25 //----------------------------------------------------------------------
26 ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner) :
27     m_callbacks (),
28     m_baton (NULL),
29     m_owner (owner),
30     m_flags (ThreadPlanShouldStopHere::eNone)
31 {
32     m_callbacks.should_stop_here_callback = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback;
33     m_callbacks.step_from_here_callback = ThreadPlanShouldStopHere::DefaultStepFromHereCallback;
34 }
35 
36 ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner, const ThreadPlanShouldStopHereCallbacks *callbacks, void *baton) :
37     m_callbacks (),
38     m_baton (),
39     m_owner (owner),
40     m_flags (ThreadPlanShouldStopHere::eNone)
41 {
42     SetShouldStopHereCallbacks(callbacks, baton);
43 }
44 
45 //----------------------------------------------------------------------
46 // Destructor
47 //----------------------------------------------------------------------
48 ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere()
49 {
50 }
51 
52 bool
53 ThreadPlanShouldStopHere::InvokeShouldStopHereCallback (FrameComparison operation)
54 {
55     bool should_stop_here = true;
56     if (m_callbacks.should_stop_here_callback)
57     {
58         should_stop_here = m_callbacks.should_stop_here_callback (m_owner, m_flags, operation, m_baton);
59         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
60         if (log)
61         {
62             lldb::addr_t current_addr = m_owner->GetThread().GetRegisterContext()->GetPC(0);
63 
64             log->Printf ("ShouldStopHere callback returned %u from 0x%" PRIx64 ".", should_stop_here, current_addr);
65         }
66     }
67 
68     return should_stop_here;
69 }
70 
71 bool
72 ThreadPlanShouldStopHere::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
73                                                          Flags &flags,
74                                                          FrameComparison operation,
75                                                          void *baton)
76 {
77     bool should_stop_here = true;
78     StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
79     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
80 
81     if ((operation == eFrameCompareOlder && flags.Test(eStepOutAvoidNoDebug))
82         || (operation == eFrameCompareYounger && flags.Test(eStepInAvoidNoDebug)))
83     {
84         if (!frame->HasDebugInformation())
85         {
86             if (log)
87                 log->Printf ("Stepping out of frame with no debug info");
88 
89             should_stop_here = false;
90         }
91     }
92 
93     return should_stop_here;
94 }
95 
96 ThreadPlanSP
97 ThreadPlanShouldStopHere::DefaultStepFromHereCallback (ThreadPlan *current_plan,
98                                                          Flags &flags,
99                                                          FrameComparison operation,
100                                                          void *baton)
101 {
102         const bool stop_others = false;
103         const size_t frame_index = 0;
104         ThreadPlanSP return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop (false,
105                                                                                                   NULL,
106                                                                                                   true,
107                                                                                                   stop_others,
108                                                                                                   eVoteNo,
109                                                                                                   eVoteNoOpinion,
110                                                                                                   frame_index);
111         return return_plan_sp;
112 }
113 
114 ThreadPlanSP
115 ThreadPlanShouldStopHere::QueueStepOutFromHerePlan(lldb_private::Flags &flags, lldb::FrameComparison operation)
116 {
117     ThreadPlanSP return_plan_sp;
118     if (m_callbacks.step_from_here_callback)
119     {
120          return_plan_sp = m_callbacks.step_from_here_callback (m_owner, flags, operation, m_baton);
121     }
122     return return_plan_sp;
123 
124 }
125 
126 lldb::ThreadPlanSP
127 ThreadPlanShouldStopHere::CheckShouldStopHereAndQueueStepOut (lldb::FrameComparison operation)
128 {
129     if (!InvokeShouldStopHereCallback(operation))
130         return QueueStepOutFromHerePlan(m_flags, operation);
131     else
132         return ThreadPlanSP();
133 }
134 
135