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