1 //===-- ScriptedThreadPythonInterface.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/Host/Config.h"
10 #include "lldb/Utility/Log.h"
11 #include "lldb/lldb-enumerations.h"
12 
13 #if LLDB_ENABLE_PYTHON
14 
15 // LLDB Python header must be included first
16 #include "../lldb-python.h"
17 
18 #include "../SWIGPythonBridge.h"
19 #include "../ScriptInterpreterPythonImpl.h"
20 #include "ScriptedThreadPythonInterface.h"
21 #include <optional>
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 using namespace lldb_private::python;
26 using Locker = ScriptInterpreterPythonImpl::Locker;
27 
28 ScriptedThreadPythonInterface::ScriptedThreadPythonInterface(
29     ScriptInterpreterPythonImpl &interpreter)
30     : ScriptedThreadInterface(), ScriptedPythonInterface(interpreter) {}
31 
32 StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject(
33     const llvm::StringRef class_name, ExecutionContext &exe_ctx,
34     StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
35   if (class_name.empty() && !script_obj)
36     return {};
37 
38   StructuredDataImpl args_impl(args_sp);
39   std::string error_string;
40 
41   Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
42                  Locker::FreeLock);
43 
44   PythonObject ret_val;
45 
46   if (!script_obj) {
47     lldb::ExecutionContextRefSP exe_ctx_ref_sp =
48         std::make_shared<ExecutionContextRef>(exe_ctx);
49     ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject(
50         class_name.str().c_str(), m_interpreter.GetDictionaryName(),
51         exe_ctx_ref_sp, args_impl, error_string);
52   } else
53     ret_val = PythonObject(PyRefType::Borrowed,
54                            static_cast<PyObject *>(script_obj->GetValue()));
55 
56   if (!ret_val)
57     return {};
58 
59   m_object_instance_sp =
60       StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val)));
61 
62   return m_object_instance_sp;
63 }
64 
65 lldb::tid_t ScriptedThreadPythonInterface::GetThreadID() {
66   Status error;
67   StructuredData::ObjectSP obj = Dispatch("get_thread_id", error);
68 
69   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
70     return LLDB_INVALID_THREAD_ID;
71 
72   return obj->GetUnsignedIntegerValue(LLDB_INVALID_THREAD_ID);
73 }
74 
75 std::optional<std::string> ScriptedThreadPythonInterface::GetName() {
76   Status error;
77   StructuredData::ObjectSP obj = Dispatch("get_name", error);
78 
79   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
80     return {};
81 
82   return obj->GetStringValue().str();
83 }
84 
85 lldb::StateType ScriptedThreadPythonInterface::GetState() {
86   Status error;
87   StructuredData::ObjectSP obj = Dispatch("get_state", error);
88 
89   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
90     return eStateInvalid;
91 
92   return static_cast<StateType>(obj->GetUnsignedIntegerValue(eStateInvalid));
93 }
94 
95 std::optional<std::string> ScriptedThreadPythonInterface::GetQueue() {
96   Status error;
97   StructuredData::ObjectSP obj = Dispatch("get_queue", error);
98 
99   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
100     return {};
101 
102   return obj->GetStringValue().str();
103 }
104 
105 StructuredData::DictionarySP ScriptedThreadPythonInterface::GetStopReason() {
106   Status error;
107   StructuredData::DictionarySP dict =
108       Dispatch<StructuredData::DictionarySP>("get_stop_reason", error);
109 
110   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error))
111     return {};
112 
113   return dict;
114 }
115 
116 StructuredData::ArraySP ScriptedThreadPythonInterface::GetStackFrames() {
117   Status error;
118   StructuredData::ArraySP arr =
119       Dispatch<StructuredData::ArraySP>("get_stackframes", error);
120 
121   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error))
122     return {};
123 
124   return arr;
125 }
126 
127 StructuredData::DictionarySP ScriptedThreadPythonInterface::GetRegisterInfo() {
128   Status error;
129   StructuredData::DictionarySP dict =
130       Dispatch<StructuredData::DictionarySP>("get_register_info", error);
131 
132   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error))
133     return {};
134 
135   return dict;
136 }
137 
138 std::optional<std::string> ScriptedThreadPythonInterface::GetRegisterContext() {
139   Status error;
140   StructuredData::ObjectSP obj = Dispatch("get_register_context", error);
141 
142   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
143     return {};
144 
145   return obj->GetAsString()->GetValue().str();
146 }
147 
148 StructuredData::ArraySP ScriptedThreadPythonInterface::GetExtendedInfo() {
149   Status error;
150   StructuredData::ArraySP arr =
151       Dispatch<StructuredData::ArraySP>("get_extended_info", error);
152 
153   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error))
154     return {};
155 
156   return arr;
157 }
158 
159 #endif
160