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