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   return GetGenericInteger("shuold_stop");
67 }
68 
69 Status ScriptedProcessPythonInterface::Stop() {
70   return GetStatusFromMethod("stop");
71 }
72 
73 Status ScriptedProcessPythonInterface::GetStatusFromMethod(
74     llvm::StringRef method_name) {
75   Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
76                  Locker::FreeLock);
77 
78   if (!m_object_instance_sp)
79     return Status("Python object ill-formed.");
80 
81   if (!m_object_instance_sp)
82     return Status("Cannot convert Python object to StructuredData::Generic.");
83   PythonObject implementor(PyRefType::Borrowed,
84                            (PyObject *)m_object_instance_sp->GetValue());
85 
86   if (!implementor.IsAllocated())
87     return Status("Python implementor not allocated.");
88 
89   PythonObject pmeth(
90       PyRefType::Owned,
91       PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
92 
93   if (PyErr_Occurred())
94     PyErr_Clear();
95 
96   if (!pmeth.IsAllocated())
97     return Status("Python method not allocated.");
98 
99   if (PyCallable_Check(pmeth.get()) == 0) {
100     if (PyErr_Occurred())
101       PyErr_Clear();
102     return Status("Python method not callable.");
103   }
104 
105   if (PyErr_Occurred())
106     PyErr_Clear();
107 
108   PythonObject py_return(PyRefType::Owned,
109                          PyObject_CallMethod(implementor.get(),
110                                              method_name.str().c_str(),
111                                              nullptr));
112 
113   if (PyErr_Occurred()) {
114     PyErr_Print();
115     PyErr_Clear();
116     return Status("Python method could not be called.");
117   }
118 
119   if (PyObject *py_ret_ptr = py_return.get()) {
120     lldb::SBError *sb_error =
121         (lldb::SBError *)LLDBSWIGPython_CastPyObjectToSBError(py_ret_ptr);
122 
123     if (!sb_error)
124       return Status("Couldn't cast lldb::SBError to lldb::Status.");
125 
126     Status status = m_interpreter.GetStatusFromSBError(*sb_error);
127 
128     if (status.Fail())
129       return Status("error: %s", status.AsCString());
130 
131     return status;
132   }
133 
134   return Status("Returned object is null.");
135 }
136 
137 size_t
138 ScriptedProcessPythonInterface::GetGenericInteger(llvm::StringRef method_name) {
139   Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
140                  Locker::FreeLock);
141 
142   if (!m_object_instance_sp)
143     return LLDB_INVALID_ADDRESS;
144 
145   if (!m_object_instance_sp)
146     return LLDB_INVALID_ADDRESS;
147   PythonObject implementor(PyRefType::Borrowed,
148                            (PyObject *)m_object_instance_sp->GetValue());
149 
150   if (!implementor.IsAllocated())
151     return LLDB_INVALID_ADDRESS;
152 
153   PythonObject pmeth(
154       PyRefType::Owned,
155       PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
156 
157   if (PyErr_Occurred())
158     PyErr_Clear();
159 
160   if (!pmeth.IsAllocated())
161     return LLDB_INVALID_ADDRESS;
162 
163   if (PyCallable_Check(pmeth.get()) == 0) {
164     if (PyErr_Occurred())
165       PyErr_Clear();
166     return LLDB_INVALID_ADDRESS;
167   }
168 
169   if (PyErr_Occurred())
170     PyErr_Clear();
171 
172   PythonObject py_return(PyRefType::Owned,
173                          PyObject_CallMethod(implementor.get(),
174                                              method_name.str().c_str(),
175                                              nullptr));
176 
177   if (PyErr_Occurred()) {
178     PyErr_Print();
179     PyErr_Clear();
180   }
181 
182   if (py_return.get()) {
183     auto size = py_return.AsUnsignedLongLong();
184     return (size) ? *size : LLDB_INVALID_ADDRESS;
185   }
186   return LLDB_INVALID_ADDRESS;
187 }
188 
189 lldb::MemoryRegionInfoSP
190 ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
191     lldb::addr_t address) {
192   // TODO: Implement
193   return nullptr;
194 }
195 
196 StructuredData::DictionarySP
197 ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) {
198   // TODO: Implement
199   return nullptr;
200 }
201 
202 StructuredData::DictionarySP
203 ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) {
204   // TODO: Implement
205   return nullptr;
206 }
207 
208 lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress(
209     lldb::addr_t address, size_t size, Status &error) {
210   Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
211                  Locker::FreeLock);
212 
213   auto error_with_message = [&error](llvm::StringRef message) {
214     error.SetErrorString(message);
215     return nullptr;
216   };
217 
218   static char callee_name[] = "read_memory_at_address";
219   std::string param_format = GetPythonValueFormatString(address);
220   param_format += GetPythonValueFormatString(size);
221 
222   if (!m_object_instance_sp)
223     return error_with_message("Python object ill-formed.");
224 
225   if (!m_object_instance_sp)
226     return error_with_message("Python method not callable.");
227 
228   PythonObject implementor(PyRefType::Borrowed,
229                            (PyObject *)m_object_instance_sp->GetValue());
230 
231   if (!implementor.IsAllocated())
232     return error_with_message("Python implementor not allocated.");
233 
234   PythonObject pmeth(PyRefType::Owned,
235                      PyObject_GetAttrString(implementor.get(), callee_name));
236 
237   if (PyErr_Occurred())
238     PyErr_Clear();
239 
240   if (!pmeth.IsAllocated())
241     return error_with_message("Python method not allocated.");
242 
243   if (PyCallable_Check(pmeth.get()) == 0) {
244     if (PyErr_Occurred())
245       PyErr_Clear();
246     return error_with_message("Python method not callable.");
247   }
248 
249   if (PyErr_Occurred())
250     PyErr_Clear();
251 
252   PythonObject py_return(PyRefType::Owned,
253                          PyObject_CallMethod(implementor.get(), callee_name,
254                                              param_format.c_str(), address,
255                                              size));
256 
257   if (PyErr_Occurred()) {
258     PyErr_Print();
259     PyErr_Clear();
260     return error_with_message("Python method could not be called.");
261   }
262 
263   if (PyObject *py_ret_ptr = py_return.get()) {
264     lldb::SBData *sb_data =
265         (lldb::SBData *)LLDBSWIGPython_CastPyObjectToSBData(py_ret_ptr);
266 
267     if (!sb_data)
268       return error_with_message(
269           "Couldn't cast lldb::SBData to lldb::DataExtractor.");
270 
271     return m_interpreter.GetDataExtractorFromSBData(*sb_data);
272   }
273 
274   return error_with_message("Returned object is null.");
275 }
276 
277 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() {
278   // TODO: Implement
279   return nullptr;
280 }
281 
282 lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() {
283   size_t pid = GetGenericInteger("get_process_id");
284 
285   return (pid >= std::numeric_limits<lldb::pid_t>::max())
286              ? LLDB_INVALID_PROCESS_ID
287              : pid;
288 }
289 
290 bool ScriptedProcessPythonInterface::IsAlive() {
291   return GetGenericInteger("is_alive");
292 }
293 
294 #endif
295