1 //===-- ScriptedThreadPlanPythonInterface.cpp -----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Core/PluginManager.h"
10 #include "lldb/Host/Config.h"
11 #include "lldb/Utility/Log.h"
12 #include "lldb/lldb-enumerations.h"
13 
14 #if LLDB_ENABLE_PYTHON
15 
16 // clang-format off
17 // LLDB Python header must be included first
18 #include "../lldb-python.h"
19 //clang-format on
20 
21 #include "../SWIGPythonBridge.h"
22 #include "../ScriptInterpreterPythonImpl.h"
23 #include "ScriptedThreadPlanPythonInterface.h"
24 
25 using namespace lldb;
26 using namespace lldb_private;
27 using namespace lldb_private::python;
28 
29 ScriptedThreadPlanPythonInterface::ScriptedThreadPlanPythonInterface(
30     ScriptInterpreterPythonImpl &interpreter)
31     : ScriptedThreadPlanInterface(), ScriptedPythonInterface(interpreter) {}
32 
33 llvm::Expected<StructuredData::GenericSP>
34 ScriptedThreadPlanPythonInterface::CreatePluginObject(
35     const llvm::StringRef class_name, lldb::ThreadPlanSP thread_plan_sp,
36     const StructuredDataImpl &args_sp) {
37   return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr,
38                                                      thread_plan_sp, args_sp);
39 }
40 
41 llvm::Expected<bool>
42 ScriptedThreadPlanPythonInterface::ExplainsStop(Event *event) {
43   Status error;
44   StructuredData::ObjectSP obj = Dispatch("explains_stop", error, event);
45 
46   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
47                                                     error)) {
48     if (!obj)
49       return false;
50     return error.ToError();
51   }
52 
53   return obj->GetBooleanValue();
54 }
55 
56 llvm::Expected<bool>
57 ScriptedThreadPlanPythonInterface::ShouldStop(Event *event) {
58   Status error;
59   StructuredData::ObjectSP obj = Dispatch("should_stop", error, event);
60 
61   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
62                                                     error)) {
63     if (!obj)
64       return false;
65     return error.ToError();
66   }
67 
68   return obj->GetBooleanValue();
69 }
70 
71 llvm::Expected<bool> ScriptedThreadPlanPythonInterface::IsStale() {
72   Status error;
73   StructuredData::ObjectSP obj = Dispatch("is_stale", error);
74 
75   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
76                                                     error)) {
77     if (!obj)
78       return false;
79     return error.ToError();
80   }
81 
82   return obj->GetBooleanValue();
83 }
84 
85 lldb::StateType ScriptedThreadPlanPythonInterface::GetRunState() {
86   Status error;
87   StructuredData::ObjectSP obj = Dispatch("should_step", error);
88 
89   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
90                                                     error))
91     return lldb::eStateStepping;
92 
93   return static_cast<lldb::StateType>(obj->GetUnsignedIntegerValue(
94       static_cast<uint32_t>(lldb::eStateStepping)));
95 }
96 
97 llvm::Error
98 ScriptedThreadPlanPythonInterface::GetStopDescription(lldb::StreamSP &stream) {
99   Status error;
100   Dispatch("stop_description", error, stream);
101 
102   if (error.Fail())
103     return error.ToError();
104 
105   return llvm::Error::success();
106 }
107 
108 void ScriptedThreadPlanPythonInterface::Initialize() {
109   const std::vector<llvm::StringRef> ci_usages = {
110       "thread step-scripted -C <script-name> [-k key -v value ...]"};
111   const std::vector<llvm::StringRef> api_usages = {
112       "SBThread.StepUsingScriptedThreadPlan"};
113   PluginManager::RegisterPlugin(
114       GetPluginNameStatic(),
115       llvm::StringRef("Alter thread stepping logic and stop reason"),
116       CreateInstance, eScriptLanguagePython, {ci_usages, api_usages});
117 }
118 
119 void ScriptedThreadPlanPythonInterface::Terminate() {
120   PluginManager::UnregisterPlugin(CreateInstance);
121 }
122 
123 #endif
124