xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp (revision eac174f2741a08d8deb8aae59a7f778ef9b5d770)
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 
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 
57 Status ScriptedProcessPythonInterface::Launch() {
58   return GetStatusFromMethod("launch");
59 }
60 
61 Status ScriptedProcessPythonInterface::Resume() {
62   return GetStatusFromMethod("resume");
63 }
64 
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 
75 Status ScriptedProcessPythonInterface::Stop() {
76   return GetStatusFromMethod("stop");
77 }
78 
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>
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
200 ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
201     lldb::addr_t address) {
202   // TODO: Implement
203   return nullptr;
204 }
205 
206 StructuredData::DictionarySP
207 ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) {
208   // TODO: Implement
209   return nullptr;
210 }
211 
212 StructuredData::DictionarySP
213 ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) {
214   // TODO: Implement
215   return nullptr;
216 }
217 
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 
287 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() {
288   // TODO: Implement
289   return nullptr;
290 }
291 
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 
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