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