1 //===-- ThreadPlan.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/lldb-python.h"
11 
12 #include "lldb/Target/ThreadPlan.h"
13 
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/Core/Debugger.h"
19 #include "lldb/Core/Log.h"
20 #include "lldb/Core/State.h"
21 #include "lldb/Target/RegisterContext.h"
22 #include "lldb/Target/Thread.h"
23 #include "lldb/Target/Process.h"
24 #include "lldb/Target/Target.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 //----------------------------------------------------------------------
30 // ThreadPlan constructor
31 //----------------------------------------------------------------------
32 ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vote stop_vote, Vote run_vote) :
33     m_thread (thread),
34     m_stop_vote (stop_vote),
35     m_run_vote (run_vote),
36     m_kind (kind),
37     m_name (name),
38     m_plan_complete_mutex (Mutex::eMutexTypeRecursive),
39     m_plan_complete (false),
40     m_plan_private (false),
41     m_okay_to_discard (true),
42     m_is_master_plan (false),
43     m_plan_succeeded(true)
44 {
45     SetID (GetNextID());
46 }
47 
48 //----------------------------------------------------------------------
49 // Destructor
50 //----------------------------------------------------------------------
51 ThreadPlan::~ThreadPlan()
52 {
53 }
54 
55 bool
56 ThreadPlan::IsPlanComplete ()
57 {
58     Mutex::Locker locker(m_plan_complete_mutex);
59     return m_plan_complete;
60 }
61 
62 void
63 ThreadPlan::SetPlanComplete (bool success)
64 {
65     Mutex::Locker locker(m_plan_complete_mutex);
66     m_plan_complete = true;
67     m_plan_succeeded = success;
68 }
69 
70 bool
71 ThreadPlan::MischiefManaged ()
72 {
73     Mutex::Locker locker(m_plan_complete_mutex);
74     // Mark the plan is complete, but don't override the success flag.
75     m_plan_complete = true;
76     return true;
77 }
78 
79 Vote
80 ThreadPlan::ShouldReportStop (Event *event_ptr)
81 {
82     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
83 
84     if (m_stop_vote == eVoteNoOpinion)
85     {
86         ThreadPlan *prev_plan = GetPreviousPlan ();
87         if (prev_plan)
88         {
89             Vote prev_vote = prev_plan->ShouldReportStop (event_ptr);
90             if (log)
91                 log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s",
92                              GetVoteAsCString (prev_vote));
93             return prev_vote;
94         }
95     }
96     if (log)
97         log->Printf ("ThreadPlan::ShouldReportStop() returning vote: %s", GetVoteAsCString (m_stop_vote));
98     return m_stop_vote;
99 }
100 
101 Vote
102 ThreadPlan::ShouldReportRun (Event *event_ptr)
103 {
104     if (m_run_vote == eVoteNoOpinion)
105     {
106         ThreadPlan *prev_plan = GetPreviousPlan ();
107         if (prev_plan)
108             return prev_plan->ShouldReportRun (event_ptr);
109     }
110     return m_run_vote;
111 }
112 
113 bool
114 ThreadPlan::StopOthers ()
115 {
116     ThreadPlan *prev_plan;
117     prev_plan = GetPreviousPlan ();
118     if (prev_plan == NULL)
119         return false;
120     else
121         return prev_plan->StopOthers();
122 }
123 
124 void
125 ThreadPlan::SetStopOthers (bool new_value)
126 {
127 	// SetStopOthers doesn't work up the hierarchy.  You have to set the
128     // explicit ThreadPlan you want to affect.
129 }
130 
131 bool
132 ThreadPlan::WillResume (StateType resume_state, bool current_plan)
133 {
134     if (current_plan)
135     {
136         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
137 
138         if (log)
139         {
140             RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
141             addr_t pc = reg_ctx->GetPC();
142             addr_t sp = reg_ctx->GetSP();
143             addr_t fp = reg_ctx->GetFP();
144             log->Printf("%s Thread #%u: tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64 ", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", "
145                         "plan = '%s', state = %s, stop others = %d",
146                         __FUNCTION__,
147                         m_thread.GetIndexID(),
148                         m_thread.GetID(),
149                         (uint64_t)pc,
150                         (uint64_t)sp,
151                         (uint64_t)fp,
152                         m_name.c_str(),
153                         StateAsCString(resume_state),
154                         StopOthers());
155         }
156     }
157     return true;
158 }
159 
160 lldb::user_id_t
161 ThreadPlan::GetNextID()
162 {
163     static uint32_t g_nextPlanID = 0;
164     return ++g_nextPlanID;
165 }
166 
167 void
168 ThreadPlan::DidPush()
169 {
170 }
171 
172 void
173 ThreadPlan::WillPop()
174 {
175 }
176 
177 bool
178 ThreadPlan::OkayToDiscard()
179 {
180     if (!IsMasterPlan())
181         return true;
182     else
183         return m_okay_to_discard;
184 }
185 
186 lldb::StateType
187 ThreadPlan::RunState ()
188 {
189     if (m_tracer_sp && m_tracer_sp->TracingEnabled() && m_tracer_sp->SingleStepEnabled())
190         return eStateStepping;
191     else
192         return GetPlanRunState();
193 }
194