1696bd635SAlexander Shaposhnikov //===-- ThreadPlanPython.cpp ------------------------------------*- C++ -*-===//
22bdbfd50SJim Ingham //
32bdbfd50SJim Ingham //                     The LLVM Compiler Infrastructure
42bdbfd50SJim Ingham //
52bdbfd50SJim Ingham // This file is distributed under the University of Illinois Open Source
62bdbfd50SJim Ingham // License. See LICENSE.TXT for details.
72bdbfd50SJim Ingham //
82bdbfd50SJim Ingham //===----------------------------------------------------------------------===//
92bdbfd50SJim Ingham 
102bdbfd50SJim Ingham #include "lldb/Target/ThreadPlan.h"
112bdbfd50SJim Ingham 
122bdbfd50SJim Ingham // C Includes
132bdbfd50SJim Ingham // C++ Includes
142bdbfd50SJim Ingham // Other libraries and framework includes
152bdbfd50SJim Ingham // Project includes
162bdbfd50SJim Ingham #include "lldb/Core/Debugger.h"
172bdbfd50SJim Ingham #include "lldb/Core/State.h"
182bdbfd50SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h"
192bdbfd50SJim Ingham #include "lldb/Interpreter/ScriptInterpreter.h"
20b9c1b51eSKate Stone #include "lldb/Target/Process.h"
212bdbfd50SJim Ingham #include "lldb/Target/RegisterContext.h"
22b9c1b51eSKate Stone #include "lldb/Target/Target.h"
232bdbfd50SJim Ingham #include "lldb/Target/Thread.h"
242bdbfd50SJim Ingham #include "lldb/Target/ThreadPlan.h"
252bdbfd50SJim Ingham #include "lldb/Target/ThreadPlanPython.h"
26*6f9e6901SZachary Turner #include "lldb/Utility/Log.h"
272bdbfd50SJim Ingham 
282bdbfd50SJim Ingham using namespace lldb;
292bdbfd50SJim Ingham using namespace lldb_private;
302bdbfd50SJim Ingham 
312bdbfd50SJim Ingham //----------------------------------------------------------------------
322bdbfd50SJim Ingham // ThreadPlanPython
332bdbfd50SJim Ingham //----------------------------------------------------------------------
342bdbfd50SJim Ingham 
35b9c1b51eSKate Stone ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name)
36b9c1b51eSKate Stone     : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
37b9c1b51eSKate Stone                  eVoteNoOpinion, eVoteNoOpinion),
38b9c1b51eSKate Stone       m_class_name(class_name) {
392bdbfd50SJim Ingham   SetIsMasterPlan(true);
402bdbfd50SJim Ingham   SetOkayToDiscard(true);
412bdbfd50SJim Ingham   SetPrivate(false);
422bdbfd50SJim Ingham }
432bdbfd50SJim Ingham 
44b9c1b51eSKate Stone ThreadPlanPython::~ThreadPlanPython() {
45b9c1b51eSKate Stone   // FIXME, do I need to decrement the ref count on this implementation object
46b9c1b51eSKate Stone   // to make it go away?
472bdbfd50SJim Ingham }
482bdbfd50SJim Ingham 
49b9c1b51eSKate Stone bool ThreadPlanPython::ValidatePlan(Stream *error) {
50b9c1b51eSKate Stone   // I have to postpone setting up the implementation till after the constructor
51b9c1b51eSKate Stone   // because I need to call
52b9c1b51eSKate Stone   // shared_from_this, which you can't do in the constructor.  So I'll do it
53b9c1b51eSKate Stone   // here.
542bdbfd50SJim Ingham   if (m_implementation_sp)
552bdbfd50SJim Ingham     return true;
562bdbfd50SJim Ingham   else
572bdbfd50SJim Ingham     return false;
582bdbfd50SJim Ingham }
592bdbfd50SJim Ingham 
60b9c1b51eSKate Stone void ThreadPlanPython::DidPush() {
61b9c1b51eSKate Stone   // We set up the script side in DidPush, so that it can push other plans in
62b9c1b51eSKate Stone   // the constructor,
632bdbfd50SJim Ingham   // and doesn't have to care about the details of DidPush.
642bdbfd50SJim Ingham 
65b9c1b51eSKate Stone   if (!m_class_name.empty()) {
66b9c1b51eSKate Stone     ScriptInterpreter *script_interp = m_thread.GetProcess()
67b9c1b51eSKate Stone                                            ->GetTarget()
68b9c1b51eSKate Stone                                            .GetDebugger()
69b9c1b51eSKate Stone                                            .GetCommandInterpreter()
70b9c1b51eSKate Stone                                            .GetScriptInterpreter();
71b9c1b51eSKate Stone     if (script_interp) {
72b9c1b51eSKate Stone       m_implementation_sp = script_interp->CreateScriptedThreadPlan(
73b9c1b51eSKate Stone           m_class_name.c_str(), this->shared_from_this());
742bdbfd50SJim Ingham     }
752bdbfd50SJim Ingham   }
762bdbfd50SJim Ingham }
772bdbfd50SJim Ingham 
78b9c1b51eSKate Stone bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
792bdbfd50SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
802bdbfd50SJim Ingham   if (log)
81b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
82b9c1b51eSKate Stone                 m_class_name.c_str());
832bdbfd50SJim Ingham 
842bdbfd50SJim Ingham   bool should_stop = true;
85b9c1b51eSKate Stone   if (m_implementation_sp) {
86b9c1b51eSKate Stone     ScriptInterpreter *script_interp = m_thread.GetProcess()
87b9c1b51eSKate Stone                                            ->GetTarget()
88b9c1b51eSKate Stone                                            .GetDebugger()
89b9c1b51eSKate Stone                                            .GetCommandInterpreter()
90b9c1b51eSKate Stone                                            .GetScriptInterpreter();
91b9c1b51eSKate Stone     if (script_interp) {
922bdbfd50SJim Ingham       bool script_error;
93b9c1b51eSKate Stone       should_stop = script_interp->ScriptedThreadPlanShouldStop(
94b9c1b51eSKate Stone           m_implementation_sp, event_ptr, script_error);
952bdbfd50SJim Ingham       if (script_error)
962bdbfd50SJim Ingham         SetPlanComplete(false);
972bdbfd50SJim Ingham     }
982bdbfd50SJim Ingham   }
992bdbfd50SJim Ingham   return should_stop;
1002bdbfd50SJim Ingham }
1012bdbfd50SJim Ingham 
102b9c1b51eSKate Stone bool ThreadPlanPython::IsPlanStale() {
103c915a7d2SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
104c915a7d2SJim Ingham   if (log)
105b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
106b9c1b51eSKate Stone                 m_class_name.c_str());
107c915a7d2SJim Ingham 
108c915a7d2SJim Ingham   bool is_stale = true;
109b9c1b51eSKate Stone   if (m_implementation_sp) {
110b9c1b51eSKate Stone     ScriptInterpreter *script_interp = m_thread.GetProcess()
111b9c1b51eSKate Stone                                            ->GetTarget()
112b9c1b51eSKate Stone                                            .GetDebugger()
113b9c1b51eSKate Stone                                            .GetCommandInterpreter()
114b9c1b51eSKate Stone                                            .GetScriptInterpreter();
115b9c1b51eSKate Stone     if (script_interp) {
116c915a7d2SJim Ingham       bool script_error;
117b9c1b51eSKate Stone       is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp,
118b9c1b51eSKate Stone                                                           script_error);
119c915a7d2SJim Ingham       if (script_error)
120c915a7d2SJim Ingham         SetPlanComplete(false);
121c915a7d2SJim Ingham     }
122c915a7d2SJim Ingham   }
123c915a7d2SJim Ingham   return is_stale;
124c915a7d2SJim Ingham }
125c915a7d2SJim Ingham 
126b9c1b51eSKate Stone bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) {
1272bdbfd50SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1282bdbfd50SJim Ingham   if (log)
129b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
130b9c1b51eSKate Stone                 m_class_name.c_str());
1312bdbfd50SJim Ingham 
1322bdbfd50SJim Ingham   bool explains_stop = true;
133b9c1b51eSKate Stone   if (m_implementation_sp) {
134b9c1b51eSKate Stone     ScriptInterpreter *script_interp = m_thread.GetProcess()
135b9c1b51eSKate Stone                                            ->GetTarget()
136b9c1b51eSKate Stone                                            .GetDebugger()
137b9c1b51eSKate Stone                                            .GetCommandInterpreter()
138b9c1b51eSKate Stone                                            .GetScriptInterpreter();
139b9c1b51eSKate Stone     if (script_interp) {
1402bdbfd50SJim Ingham       bool script_error;
141b9c1b51eSKate Stone       explains_stop = script_interp->ScriptedThreadPlanExplainsStop(
142b9c1b51eSKate Stone           m_implementation_sp, event_ptr, script_error);
1432bdbfd50SJim Ingham       if (script_error)
1442bdbfd50SJim Ingham         SetPlanComplete(false);
1452bdbfd50SJim Ingham     }
1462bdbfd50SJim Ingham   }
1472bdbfd50SJim Ingham   return explains_stop;
1482bdbfd50SJim Ingham }
1492bdbfd50SJim Ingham 
150b9c1b51eSKate Stone bool ThreadPlanPython::MischiefManaged() {
1512bdbfd50SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1522bdbfd50SJim Ingham   if (log)
153b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
154b9c1b51eSKate Stone                 m_class_name.c_str());
1552bdbfd50SJim Ingham   bool mischief_managed = true;
156b9c1b51eSKate Stone   if (m_implementation_sp) {
157b9c1b51eSKate Stone     // I don't really need mischief_managed, since it's simpler to just call
158b9c1b51eSKate Stone     // SetPlanComplete in should_stop.
1592bdbfd50SJim Ingham     mischief_managed = IsPlanComplete();
1602bdbfd50SJim Ingham     if (mischief_managed)
1612bdbfd50SJim Ingham       m_implementation_sp.reset();
1622bdbfd50SJim Ingham   }
1632bdbfd50SJim Ingham   return mischief_managed;
1642bdbfd50SJim Ingham }
1652bdbfd50SJim Ingham 
166b9c1b51eSKate Stone lldb::StateType ThreadPlanPython::GetPlanRunState() {
1672bdbfd50SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
1682bdbfd50SJim Ingham   if (log)
169b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
1702bdbfd50SJim Ingham                 m_class_name.c_str());
1712bdbfd50SJim Ingham   lldb::StateType run_state = eStateRunning;
172b9c1b51eSKate Stone   if (m_implementation_sp) {
173b9c1b51eSKate Stone     ScriptInterpreter *script_interp = m_thread.GetProcess()
174b9c1b51eSKate Stone                                            ->GetTarget()
175b9c1b51eSKate Stone                                            .GetDebugger()
176b9c1b51eSKate Stone                                            .GetCommandInterpreter()
177b9c1b51eSKate Stone                                            .GetScriptInterpreter();
178b9c1b51eSKate Stone     if (script_interp) {
1792bdbfd50SJim Ingham       bool script_error;
180b9c1b51eSKate Stone       run_state = script_interp->ScriptedThreadPlanGetRunState(
181b9c1b51eSKate Stone           m_implementation_sp, script_error);
1822bdbfd50SJim Ingham     }
1832bdbfd50SJim Ingham   }
1842bdbfd50SJim Ingham   return run_state;
1852bdbfd50SJim Ingham }
1862bdbfd50SJim Ingham 
1872bdbfd50SJim Ingham // The ones below are not currently exported to Python.
1882bdbfd50SJim Ingham 
189b9c1b51eSKate Stone bool ThreadPlanPython::StopOthers() {
190b9c1b51eSKate Stone   // For now Python plans run all threads, but we should add some controls for
191b9c1b51eSKate Stone   // this.
1922bdbfd50SJim Ingham   return false;
1932bdbfd50SJim Ingham }
1942bdbfd50SJim Ingham 
195b9c1b51eSKate Stone void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
196b9c1b51eSKate Stone   s->Printf("Python thread plan implemented by class %s.",
197b9c1b51eSKate Stone             m_class_name.c_str());
1982bdbfd50SJim Ingham }
1992bdbfd50SJim Ingham 
200b9c1b51eSKate Stone bool ThreadPlanPython::WillStop() {
2012bdbfd50SJim Ingham   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
2022bdbfd50SJim Ingham   if (log)
203b9c1b51eSKate Stone     log->Printf("%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
204b9c1b51eSKate Stone                 m_class_name.c_str());
2052bdbfd50SJim Ingham   return true;
2062bdbfd50SJim Ingham }
207