1 //===-- ScriptedProcessPythonInterface.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/lldb-enumerations.h"
11
12 #if LLDB_ENABLE_PYTHON
13
14 // LLDB Python header must be included first
15 #include "lldb-python.h"
16
17 #include "SWIGPythonBridge.h"
18 #include "ScriptInterpreterPythonImpl.h"
19 #include "ScriptedProcessPythonInterface.h"
20
21 using namespace lldb;
22 using namespace lldb_private;
23 using namespace lldb_private::python;
24 using Locker = ScriptInterpreterPythonImpl::Locker;
25
CreatePluginObject(const llvm::StringRef class_name,lldb::TargetSP target_sp,StructuredData::DictionarySP args_sp)26 StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject(
27 const llvm::StringRef class_name, lldb::TargetSP target_sp,
28 StructuredData::DictionarySP args_sp) {
29 if (class_name.empty())
30 return {};
31
32 std::string error_string;
33 StructuredDataImpl *args_impl = nullptr;
34 if (args_sp) {
35 args_impl = new StructuredDataImpl();
36 args_impl->SetObjectSP(args_sp);
37 }
38
39 void *ret_val;
40
41 {
42
43 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
44 Locker::FreeLock);
45
46 ret_val = LLDBSwigPythonCreateScriptedProcess(
47 class_name.str().c_str(), m_interpreter.GetDictionaryName(), target_sp,
48 args_impl, error_string);
49 }
50
51 m_object_instance_sp =
52 StructuredData::GenericSP(new StructuredPythonObject(ret_val));
53
54 return m_object_instance_sp;
55 }
56
Launch()57 Status ScriptedProcessPythonInterface::Launch() {
58 return GetStatusFromMethod("launch");
59 }
60
Resume()61 Status ScriptedProcessPythonInterface::Resume() {
62 return GetStatusFromMethod("resume");
63 }
64
ShouldStop()65 bool ScriptedProcessPythonInterface::ShouldStop() {
66 llvm::Optional<unsigned long long> should_stop =
67 GetGenericInteger("should_stop");
68
69 if (!should_stop)
70 return false;
71
72 return static_cast<bool>(*should_stop);
73 }
74
Stop()75 Status ScriptedProcessPythonInterface::Stop() {
76 return GetStatusFromMethod("stop");
77 }
78
GetStatusFromMethod(llvm::StringRef method_name)79 Status ScriptedProcessPythonInterface::GetStatusFromMethod(
80 llvm::StringRef method_name) {
81 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
82 Locker::FreeLock);
83
84 if (!m_object_instance_sp)
85 return Status("Python object ill-formed.");
86
87 if (!m_object_instance_sp)
88 return Status("Cannot convert Python object to StructuredData::Generic.");
89 PythonObject implementor(PyRefType::Borrowed,
90 (PyObject *)m_object_instance_sp->GetValue());
91
92 if (!implementor.IsAllocated())
93 return Status("Python implementor not allocated.");
94
95 PythonObject pmeth(
96 PyRefType::Owned,
97 PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
98
99 if (PyErr_Occurred())
100 PyErr_Clear();
101
102 if (!pmeth.IsAllocated())
103 return Status("Python method not allocated.");
104
105 if (PyCallable_Check(pmeth.get()) == 0) {
106 if (PyErr_Occurred())
107 PyErr_Clear();
108 return Status("Python method not callable.");
109 }
110
111 if (PyErr_Occurred())
112 PyErr_Clear();
113
114 PythonObject py_return(PyRefType::Owned,
115 PyObject_CallMethod(implementor.get(),
116 method_name.str().c_str(),
117 nullptr));
118
119 if (PyErr_Occurred()) {
120 PyErr_Print();
121 PyErr_Clear();
122 return Status("Python method could not be called.");
123 }
124
125 if (PyObject *py_ret_ptr = py_return.get()) {
126 lldb::SBError *sb_error =
127 (lldb::SBError *)LLDBSWIGPython_CastPyObjectToSBError(py_ret_ptr);
128
129 if (!sb_error)
130 return Status("Couldn't cast lldb::SBError to lldb::Status.");
131
132 Status status = m_interpreter.GetStatusFromSBError(*sb_error);
133
134 if (status.Fail())
135 return Status("error: %s", status.AsCString());
136
137 return status;
138 }
139
140 return Status("Returned object is null.");
141 }
142
143 llvm::Optional<unsigned long long>
GetGenericInteger(llvm::StringRef method_name)144 ScriptedProcessPythonInterface::GetGenericInteger(llvm::StringRef method_name) {
145 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
146 Locker::FreeLock);
147
148 if (!m_object_instance_sp)
149 return llvm::None;
150
151 if (!m_object_instance_sp)
152 return llvm::None;
153 PythonObject implementor(PyRefType::Borrowed,
154 (PyObject *)m_object_instance_sp->GetValue());
155
156 if (!implementor.IsAllocated())
157 return llvm::None;
158
159 PythonObject pmeth(
160 PyRefType::Owned,
161 PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
162
163 if (PyErr_Occurred())
164 PyErr_Clear();
165
166 if (!pmeth.IsAllocated())
167 return llvm::None;
168
169 if (PyCallable_Check(pmeth.get()) == 0) {
170 if (PyErr_Occurred())
171 PyErr_Clear();
172 return llvm::None;
173 }
174
175 if (PyErr_Occurred())
176 PyErr_Clear();
177
178 PythonObject py_return(PyRefType::Owned,
179 PyObject_CallMethod(implementor.get(),
180 method_name.str().c_str(),
181 nullptr));
182
183 if (PyErr_Occurred()) {
184 PyErr_Print();
185 PyErr_Clear();
186 }
187
188 if (!py_return.get())
189 return llvm::None;
190
191 llvm::Expected<unsigned long long> size = py_return.AsUnsignedLongLong();
192 // FIXME: Handle error.
193 if (!size)
194 return llvm::None;
195
196 return *size;
197 }
198
199 lldb::MemoryRegionInfoSP
GetMemoryRegionContainingAddress(lldb::addr_t address)200 ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
201 lldb::addr_t address) {
202 // TODO: Implement
203 return nullptr;
204 }
205
206 StructuredData::DictionarySP
GetThreadWithID(lldb::tid_t tid)207 ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) {
208 // TODO: Implement
209 return nullptr;
210 }
211
212 StructuredData::DictionarySP
GetRegistersForThread(lldb::tid_t tid)213 ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) {
214 // TODO: Implement
215 return nullptr;
216 }
217
ReadMemoryAtAddress(lldb::addr_t address,size_t size,Status & error)218 lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress(
219 lldb::addr_t address, size_t size, Status &error) {
220 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
221 Locker::FreeLock);
222
223 auto error_with_message = [&error](llvm::StringRef message) {
224 error.SetErrorString(message);
225 return nullptr;
226 };
227
228 static char callee_name[] = "read_memory_at_address";
229 std::string param_format = GetPythonValueFormatString(address);
230 param_format += GetPythonValueFormatString(size);
231
232 if (!m_object_instance_sp)
233 return error_with_message("Python object ill-formed.");
234
235 if (!m_object_instance_sp)
236 return error_with_message("Python method not callable.");
237
238 PythonObject implementor(PyRefType::Borrowed,
239 (PyObject *)m_object_instance_sp->GetValue());
240
241 if (!implementor.IsAllocated())
242 return error_with_message("Python implementor not allocated.");
243
244 PythonObject pmeth(PyRefType::Owned,
245 PyObject_GetAttrString(implementor.get(), callee_name));
246
247 if (PyErr_Occurred())
248 PyErr_Clear();
249
250 if (!pmeth.IsAllocated())
251 return error_with_message("Python method not allocated.");
252
253 if (PyCallable_Check(pmeth.get()) == 0) {
254 if (PyErr_Occurred())
255 PyErr_Clear();
256 return error_with_message("Python method not callable.");
257 }
258
259 if (PyErr_Occurred())
260 PyErr_Clear();
261
262 PythonObject py_return(PyRefType::Owned,
263 PyObject_CallMethod(implementor.get(), callee_name,
264 param_format.c_str(), address,
265 size));
266
267 if (PyErr_Occurred()) {
268 PyErr_Print();
269 PyErr_Clear();
270 return error_with_message("Python method could not be called.");
271 }
272
273 if (PyObject *py_ret_ptr = py_return.get()) {
274 lldb::SBData *sb_data =
275 (lldb::SBData *)LLDBSWIGPython_CastPyObjectToSBData(py_ret_ptr);
276
277 if (!sb_data)
278 return error_with_message(
279 "Couldn't cast lldb::SBData to lldb::DataExtractor.");
280
281 return m_interpreter.GetDataExtractorFromSBData(*sb_data);
282 }
283
284 return error_with_message("Returned object is null.");
285 }
286
GetLoadedImages()287 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() {
288 // TODO: Implement
289 return nullptr;
290 }
291
GetProcessID()292 lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() {
293 llvm::Optional<unsigned long long> pid = GetGenericInteger("get_process_id");
294 return (!pid) ? LLDB_INVALID_PROCESS_ID : *pid;
295 }
296
IsAlive()297 bool ScriptedProcessPythonInterface::IsAlive() {
298 llvm::Optional<unsigned long long> is_alive = GetGenericInteger("is_alive");
299
300 if (!is_alive)
301 return false;
302
303 return static_cast<bool>(*is_alive);
304 }
305
306 #endif
307