180814287SRaphael Isemann //===-- ThreadPlanPython.cpp ----------------------------------------------===//
22bdbfd50SJim Ingham //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62bdbfd50SJim Ingham //
72bdbfd50SJim Ingham //===----------------------------------------------------------------------===//
82bdbfd50SJim Ingham
92bdbfd50SJim Ingham #include "lldb/Target/ThreadPlan.h"
102bdbfd50SJim Ingham
112bdbfd50SJim Ingham #include "lldb/Core/Debugger.h"
122bdbfd50SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h"
132bdbfd50SJim Ingham #include "lldb/Interpreter/ScriptInterpreter.h"
14b9c1b51eSKate Stone #include "lldb/Target/Process.h"
152bdbfd50SJim Ingham #include "lldb/Target/RegisterContext.h"
16b9c1b51eSKate Stone #include "lldb/Target/Target.h"
172bdbfd50SJim Ingham #include "lldb/Target/Thread.h"
182bdbfd50SJim Ingham #include "lldb/Target/ThreadPlan.h"
192bdbfd50SJim Ingham #include "lldb/Target/ThreadPlanPython.h"
20*c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
216f9e6901SZachary Turner #include "lldb/Utility/Log.h"
22d821c997SPavel Labath #include "lldb/Utility/State.h"
232bdbfd50SJim Ingham
242bdbfd50SJim Ingham using namespace lldb;
252bdbfd50SJim Ingham using namespace lldb_private;
262bdbfd50SJim Ingham
272bdbfd50SJim Ingham // ThreadPlanPython
282bdbfd50SJim Ingham
ThreadPlanPython(Thread & thread,const char * class_name,const StructuredDataImpl & args_data)2927a14f19SJim Ingham ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name,
3082de8df2SPavel Labath const StructuredDataImpl &args_data)
31b9c1b51eSKate Stone : ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
32b9c1b51eSKate Stone eVoteNoOpinion, eVoteNoOpinion),
33d3dfd8ceSJim Ingham m_class_name(class_name), m_args_data(args_data), m_did_push(false),
34d3dfd8ceSJim Ingham m_stop_others(false) {
3504cbfa95SQuinn Pham SetIsControllingPlan(true);
362bdbfd50SJim Ingham SetOkayToDiscard(true);
372bdbfd50SJim Ingham SetPrivate(false);
382bdbfd50SJim Ingham }
392bdbfd50SJim Ingham
ValidatePlan(Stream * error)40b9c1b51eSKate Stone bool ThreadPlanPython::ValidatePlan(Stream *error) {
41e103ae92SJonas Devlieghere if (!m_did_push)
422bdbfd50SJim Ingham return true;
43e103ae92SJonas Devlieghere
44e103ae92SJonas Devlieghere if (!m_implementation_sp) {
45e103ae92SJonas Devlieghere if (error)
4693c98346SJim Ingham error->Printf("Error constructing Python ThreadPlan: %s",
4793c98346SJim Ingham m_error_str.empty() ? "<unknown error>"
4893c98346SJim Ingham : m_error_str.c_str());
492bdbfd50SJim Ingham return false;
502bdbfd50SJim Ingham }
512bdbfd50SJim Ingham
52e103ae92SJonas Devlieghere return true;
53e103ae92SJonas Devlieghere }
54e103ae92SJonas Devlieghere
GetScriptInterpreter()55e4598dc0SJim Ingham ScriptInterpreter *ThreadPlanPython::GetScriptInterpreter() {
56e4598dc0SJim Ingham return m_process.GetTarget().GetDebugger().GetScriptInterpreter();
57e4598dc0SJim Ingham }
58e4598dc0SJim Ingham
DidPush()59b9c1b51eSKate Stone void ThreadPlanPython::DidPush() {
60b9c1b51eSKate Stone // We set up the script side in DidPush, so that it can push other plans in
6105097246SAdrian Prantl // the constructor, and doesn't have to care about the details of DidPush.
62e103ae92SJonas Devlieghere m_did_push = true;
63b9c1b51eSKate Stone if (!m_class_name.empty()) {
64e4598dc0SJim Ingham ScriptInterpreter *script_interp = GetScriptInterpreter();
65b9c1b51eSKate Stone if (script_interp) {
66b9c1b51eSKate Stone m_implementation_sp = script_interp->CreateScriptedThreadPlan(
6727a14f19SJim Ingham m_class_name.c_str(), m_args_data, m_error_str,
6827a14f19SJim Ingham this->shared_from_this());
692bdbfd50SJim Ingham }
702bdbfd50SJim Ingham }
712bdbfd50SJim Ingham }
722bdbfd50SJim Ingham
ShouldStop(Event * event_ptr)73b9c1b51eSKate Stone bool ThreadPlanPython::ShouldStop(Event *event_ptr) {
74a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Thread);
7563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
76b9c1b51eSKate Stone m_class_name.c_str());
772bdbfd50SJim Ingham
782bdbfd50SJim Ingham bool should_stop = true;
79b9c1b51eSKate Stone if (m_implementation_sp) {
80e4598dc0SJim Ingham ScriptInterpreter *script_interp = GetScriptInterpreter();
81b9c1b51eSKate Stone if (script_interp) {
822bdbfd50SJim Ingham bool script_error;
83b9c1b51eSKate Stone should_stop = script_interp->ScriptedThreadPlanShouldStop(
84b9c1b51eSKate Stone m_implementation_sp, event_ptr, script_error);
852bdbfd50SJim Ingham if (script_error)
862bdbfd50SJim Ingham SetPlanComplete(false);
872bdbfd50SJim Ingham }
882bdbfd50SJim Ingham }
892bdbfd50SJim Ingham return should_stop;
902bdbfd50SJim Ingham }
912bdbfd50SJim Ingham
IsPlanStale()92b9c1b51eSKate Stone bool ThreadPlanPython::IsPlanStale() {
93a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Thread);
9463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
95b9c1b51eSKate Stone m_class_name.c_str());
96c915a7d2SJim Ingham
97c915a7d2SJim Ingham bool is_stale = true;
98b9c1b51eSKate Stone if (m_implementation_sp) {
99e4598dc0SJim Ingham ScriptInterpreter *script_interp = GetScriptInterpreter();
100b9c1b51eSKate Stone if (script_interp) {
101c915a7d2SJim Ingham bool script_error;
102b9c1b51eSKate Stone is_stale = script_interp->ScriptedThreadPlanIsStale(m_implementation_sp,
103b9c1b51eSKate Stone script_error);
104c915a7d2SJim Ingham if (script_error)
105c915a7d2SJim Ingham SetPlanComplete(false);
106c915a7d2SJim Ingham }
107c915a7d2SJim Ingham }
108c915a7d2SJim Ingham return is_stale;
109c915a7d2SJim Ingham }
110c915a7d2SJim Ingham
DoPlanExplainsStop(Event * event_ptr)111b9c1b51eSKate Stone bool ThreadPlanPython::DoPlanExplainsStop(Event *event_ptr) {
112a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Thread);
11363e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
114b9c1b51eSKate Stone m_class_name.c_str());
1152bdbfd50SJim Ingham
1162bdbfd50SJim Ingham bool explains_stop = true;
117b9c1b51eSKate Stone if (m_implementation_sp) {
118e4598dc0SJim Ingham ScriptInterpreter *script_interp = GetScriptInterpreter();
119b9c1b51eSKate Stone if (script_interp) {
1202bdbfd50SJim Ingham bool script_error;
121b9c1b51eSKate Stone explains_stop = script_interp->ScriptedThreadPlanExplainsStop(
122b9c1b51eSKate Stone m_implementation_sp, event_ptr, script_error);
1232bdbfd50SJim Ingham if (script_error)
1242bdbfd50SJim Ingham SetPlanComplete(false);
1252bdbfd50SJim Ingham }
1262bdbfd50SJim Ingham }
1272bdbfd50SJim Ingham return explains_stop;
1282bdbfd50SJim Ingham }
1292bdbfd50SJim Ingham
MischiefManaged()130b9c1b51eSKate Stone bool ThreadPlanPython::MischiefManaged() {
131a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Thread);
13263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
133b9c1b51eSKate Stone m_class_name.c_str());
1342bdbfd50SJim Ingham bool mischief_managed = true;
135b9c1b51eSKate Stone if (m_implementation_sp) {
136b9c1b51eSKate Stone // I don't really need mischief_managed, since it's simpler to just call
137b9c1b51eSKate Stone // SetPlanComplete in should_stop.
1382bdbfd50SJim Ingham mischief_managed = IsPlanComplete();
1392bdbfd50SJim Ingham if (mischief_managed)
1402bdbfd50SJim Ingham m_implementation_sp.reset();
1412bdbfd50SJim Ingham }
1422bdbfd50SJim Ingham return mischief_managed;
1432bdbfd50SJim Ingham }
1442bdbfd50SJim Ingham
GetPlanRunState()145b9c1b51eSKate Stone lldb::StateType ThreadPlanPython::GetPlanRunState() {
146a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Thread);
14763e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
1482bdbfd50SJim Ingham m_class_name.c_str());
1492bdbfd50SJim Ingham lldb::StateType run_state = eStateRunning;
150b9c1b51eSKate Stone if (m_implementation_sp) {
151e4598dc0SJim Ingham ScriptInterpreter *script_interp = GetScriptInterpreter();
152b9c1b51eSKate Stone if (script_interp) {
1532bdbfd50SJim Ingham bool script_error;
154b9c1b51eSKate Stone run_state = script_interp->ScriptedThreadPlanGetRunState(
155b9c1b51eSKate Stone m_implementation_sp, script_error);
1562bdbfd50SJim Ingham }
1572bdbfd50SJim Ingham }
1582bdbfd50SJim Ingham return run_state;
1592bdbfd50SJim Ingham }
1602bdbfd50SJim Ingham
1612bdbfd50SJim Ingham // The ones below are not currently exported to Python.
GetDescription(Stream * s,lldb::DescriptionLevel level)162b9c1b51eSKate Stone void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
163b9c1b51eSKate Stone s->Printf("Python thread plan implemented by class %s.",
164b9c1b51eSKate Stone m_class_name.c_str());
1652bdbfd50SJim Ingham }
1662bdbfd50SJim Ingham
WillStop()167b9c1b51eSKate Stone bool ThreadPlanPython::WillStop() {
168a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Thread);
16963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s called on Python Thread Plan: %s )", LLVM_PRETTY_FUNCTION,
170b9c1b51eSKate Stone m_class_name.c_str());
1712bdbfd50SJim Ingham return true;
1722bdbfd50SJim Ingham }
173