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