11f6a57c1SMed Ismail Bennani //===-- ScriptedProcessPythonInterface.cpp --------------------------------===// 21f6a57c1SMed Ismail Bennani // 31f6a57c1SMed Ismail Bennani // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41f6a57c1SMed Ismail Bennani // See https://llvm.org/LICENSE.txt for license information. 51f6a57c1SMed Ismail Bennani // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61f6a57c1SMed Ismail Bennani // 71f6a57c1SMed Ismail Bennani //===----------------------------------------------------------------------===// 81f6a57c1SMed Ismail Bennani 91f6a57c1SMed Ismail Bennani #include "lldb/Host/Config.h" 101f6a57c1SMed Ismail Bennani #include "lldb/lldb-enumerations.h" 111f6a57c1SMed Ismail Bennani 121f6a57c1SMed Ismail Bennani #if LLDB_ENABLE_PYTHON 131f6a57c1SMed Ismail Bennani 141f6a57c1SMed Ismail Bennani // LLDB Python header must be included first 151f6a57c1SMed Ismail Bennani #include "lldb-python.h" 161f6a57c1SMed Ismail Bennani 171f6a57c1SMed Ismail Bennani #include "SWIGPythonBridge.h" 181f6a57c1SMed Ismail Bennani #include "ScriptInterpreterPythonImpl.h" 191f6a57c1SMed Ismail Bennani #include "ScriptedProcessPythonInterface.h" 201f6a57c1SMed Ismail Bennani 211f6a57c1SMed Ismail Bennani using namespace lldb; 221f6a57c1SMed Ismail Bennani using namespace lldb_private; 231f6a57c1SMed Ismail Bennani using namespace lldb_private::python; 241f6a57c1SMed Ismail Bennani using Locker = ScriptInterpreterPythonImpl::Locker; 251f6a57c1SMed Ismail Bennani 261f6a57c1SMed Ismail Bennani StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( 271f6a57c1SMed Ismail Bennani const llvm::StringRef class_name, lldb::TargetSP target_sp, 281f6a57c1SMed Ismail Bennani StructuredData::DictionarySP args_sp) { 291f6a57c1SMed Ismail Bennani if (class_name.empty()) 301f6a57c1SMed Ismail Bennani return {}; 311f6a57c1SMed Ismail Bennani 321f6a57c1SMed Ismail Bennani std::string error_string; 331f6a57c1SMed Ismail Bennani StructuredDataImpl *args_impl = nullptr; 341f6a57c1SMed Ismail Bennani if (args_sp) { 351f6a57c1SMed Ismail Bennani args_impl = new StructuredDataImpl(); 361f6a57c1SMed Ismail Bennani args_impl->SetObjectSP(args_sp); 371f6a57c1SMed Ismail Bennani } 381f6a57c1SMed Ismail Bennani 391f6a57c1SMed Ismail Bennani void *ret_val; 401f6a57c1SMed Ismail Bennani 411f6a57c1SMed Ismail Bennani { 421f6a57c1SMed Ismail Bennani 431f6a57c1SMed Ismail Bennani Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 441f6a57c1SMed Ismail Bennani Locker::FreeLock); 451f6a57c1SMed Ismail Bennani 461f6a57c1SMed Ismail Bennani ret_val = LLDBSwigPythonCreateScriptedProcess( 471f6a57c1SMed Ismail Bennani class_name.str().c_str(), m_interpreter.GetDictionaryName(), target_sp, 481f6a57c1SMed Ismail Bennani args_impl, error_string); 491f6a57c1SMed Ismail Bennani } 501f6a57c1SMed Ismail Bennani 511f6a57c1SMed Ismail Bennani m_object_instance_sp = 521f6a57c1SMed Ismail Bennani StructuredData::GenericSP(new StructuredPythonObject(ret_val)); 531f6a57c1SMed Ismail Bennani 541f6a57c1SMed Ismail Bennani return m_object_instance_sp; 551f6a57c1SMed Ismail Bennani } 561f6a57c1SMed Ismail Bennani 571f6a57c1SMed Ismail Bennani Status ScriptedProcessPythonInterface::Launch() { 58312b43daSMed Ismail Bennani return GetStatusFromMethod("launch"); 591f6a57c1SMed Ismail Bennani } 601f6a57c1SMed Ismail Bennani 611f6a57c1SMed Ismail Bennani Status ScriptedProcessPythonInterface::Resume() { 62312b43daSMed Ismail Bennani return GetStatusFromMethod("resume"); 631f6a57c1SMed Ismail Bennani } 641f6a57c1SMed Ismail Bennani 65312b43daSMed Ismail Bennani bool ScriptedProcessPythonInterface::ShouldStop() { 66*3d4cadfbSMed Ismail Bennani llvm::Optional<unsigned long long> should_stop = 67*3d4cadfbSMed Ismail Bennani GetGenericInteger("should_stop"); 68*3d4cadfbSMed Ismail Bennani 69*3d4cadfbSMed Ismail Bennani if (!should_stop) 70*3d4cadfbSMed Ismail Bennani return false; 71*3d4cadfbSMed Ismail Bennani 72*3d4cadfbSMed Ismail Bennani return static_cast<bool>(*should_stop); 73312b43daSMed Ismail Bennani } 74312b43daSMed Ismail Bennani 75312b43daSMed Ismail Bennani Status ScriptedProcessPythonInterface::Stop() { 76312b43daSMed Ismail Bennani return GetStatusFromMethod("stop"); 77312b43daSMed Ismail Bennani } 78312b43daSMed Ismail Bennani 79312b43daSMed Ismail Bennani Status ScriptedProcessPythonInterface::GetStatusFromMethod( 80312b43daSMed Ismail Bennani llvm::StringRef method_name) { 811f6a57c1SMed Ismail Bennani Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 821f6a57c1SMed Ismail Bennani Locker::FreeLock); 831f6a57c1SMed Ismail Bennani 841f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 851f6a57c1SMed Ismail Bennani return Status("Python object ill-formed."); 861f6a57c1SMed Ismail Bennani 871f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 881f6a57c1SMed Ismail Bennani return Status("Cannot convert Python object to StructuredData::Generic."); 891f6a57c1SMed Ismail Bennani PythonObject implementor(PyRefType::Borrowed, 901f6a57c1SMed Ismail Bennani (PyObject *)m_object_instance_sp->GetValue()); 911f6a57c1SMed Ismail Bennani 921f6a57c1SMed Ismail Bennani if (!implementor.IsAllocated()) 931f6a57c1SMed Ismail Bennani return Status("Python implementor not allocated."); 941f6a57c1SMed Ismail Bennani 951f6a57c1SMed Ismail Bennani PythonObject pmeth( 961f6a57c1SMed Ismail Bennani PyRefType::Owned, 971f6a57c1SMed Ismail Bennani PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); 981f6a57c1SMed Ismail Bennani 991f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 1001f6a57c1SMed Ismail Bennani PyErr_Clear(); 1011f6a57c1SMed Ismail Bennani 1021f6a57c1SMed Ismail Bennani if (!pmeth.IsAllocated()) 1031f6a57c1SMed Ismail Bennani return Status("Python method not allocated."); 1041f6a57c1SMed Ismail Bennani 1051f6a57c1SMed Ismail Bennani if (PyCallable_Check(pmeth.get()) == 0) { 1061f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 1071f6a57c1SMed Ismail Bennani PyErr_Clear(); 1081f6a57c1SMed Ismail Bennani return Status("Python method not callable."); 1091f6a57c1SMed Ismail Bennani } 1101f6a57c1SMed Ismail Bennani 1111f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 1121f6a57c1SMed Ismail Bennani PyErr_Clear(); 1131f6a57c1SMed Ismail Bennani 1141f6a57c1SMed Ismail Bennani PythonObject py_return(PyRefType::Owned, 1151f6a57c1SMed Ismail Bennani PyObject_CallMethod(implementor.get(), 1161f6a57c1SMed Ismail Bennani method_name.str().c_str(), 1171f6a57c1SMed Ismail Bennani nullptr)); 1181f6a57c1SMed Ismail Bennani 1191f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) { 1201f6a57c1SMed Ismail Bennani PyErr_Print(); 1211f6a57c1SMed Ismail Bennani PyErr_Clear(); 1221f6a57c1SMed Ismail Bennani return Status("Python method could not be called."); 1231f6a57c1SMed Ismail Bennani } 1241f6a57c1SMed Ismail Bennani 1251f6a57c1SMed Ismail Bennani if (PyObject *py_ret_ptr = py_return.get()) { 1261f6a57c1SMed Ismail Bennani lldb::SBError *sb_error = 1271f6a57c1SMed Ismail Bennani (lldb::SBError *)LLDBSWIGPython_CastPyObjectToSBError(py_ret_ptr); 1281f6a57c1SMed Ismail Bennani 1291f6a57c1SMed Ismail Bennani if (!sb_error) 1301f6a57c1SMed Ismail Bennani return Status("Couldn't cast lldb::SBError to lldb::Status."); 1311f6a57c1SMed Ismail Bennani 1321f6a57c1SMed Ismail Bennani Status status = m_interpreter.GetStatusFromSBError(*sb_error); 1331f6a57c1SMed Ismail Bennani 1341f6a57c1SMed Ismail Bennani if (status.Fail()) 1351f6a57c1SMed Ismail Bennani return Status("error: %s", status.AsCString()); 1361f6a57c1SMed Ismail Bennani 1371f6a57c1SMed Ismail Bennani return status; 1381f6a57c1SMed Ismail Bennani } 1391f6a57c1SMed Ismail Bennani 1401f6a57c1SMed Ismail Bennani return Status("Returned object is null."); 1411f6a57c1SMed Ismail Bennani } 1421f6a57c1SMed Ismail Bennani 143*3d4cadfbSMed Ismail Bennani llvm::Optional<unsigned long long> 1441f6a57c1SMed Ismail Bennani ScriptedProcessPythonInterface::GetGenericInteger(llvm::StringRef method_name) { 1451f6a57c1SMed Ismail Bennani Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 1461f6a57c1SMed Ismail Bennani Locker::FreeLock); 1471f6a57c1SMed Ismail Bennani 1481f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 149*3d4cadfbSMed Ismail Bennani return llvm::None; 1501f6a57c1SMed Ismail Bennani 1511f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 152*3d4cadfbSMed Ismail Bennani return llvm::None; 1531f6a57c1SMed Ismail Bennani PythonObject implementor(PyRefType::Borrowed, 1541f6a57c1SMed Ismail Bennani (PyObject *)m_object_instance_sp->GetValue()); 1551f6a57c1SMed Ismail Bennani 1561f6a57c1SMed Ismail Bennani if (!implementor.IsAllocated()) 157*3d4cadfbSMed Ismail Bennani return llvm::None; 1581f6a57c1SMed Ismail Bennani 1591f6a57c1SMed Ismail Bennani PythonObject pmeth( 1601f6a57c1SMed Ismail Bennani PyRefType::Owned, 1611f6a57c1SMed Ismail Bennani PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); 1621f6a57c1SMed Ismail Bennani 1631f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 1641f6a57c1SMed Ismail Bennani PyErr_Clear(); 1651f6a57c1SMed Ismail Bennani 1661f6a57c1SMed Ismail Bennani if (!pmeth.IsAllocated()) 167*3d4cadfbSMed Ismail Bennani return llvm::None; 1681f6a57c1SMed Ismail Bennani 1691f6a57c1SMed Ismail Bennani if (PyCallable_Check(pmeth.get()) == 0) { 1701f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 1711f6a57c1SMed Ismail Bennani PyErr_Clear(); 172*3d4cadfbSMed Ismail Bennani return llvm::None; 1731f6a57c1SMed Ismail Bennani } 1741f6a57c1SMed Ismail Bennani 1751f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 1761f6a57c1SMed Ismail Bennani PyErr_Clear(); 1771f6a57c1SMed Ismail Bennani 1781f6a57c1SMed Ismail Bennani PythonObject py_return(PyRefType::Owned, 1791f6a57c1SMed Ismail Bennani PyObject_CallMethod(implementor.get(), 1801f6a57c1SMed Ismail Bennani method_name.str().c_str(), 1811f6a57c1SMed Ismail Bennani nullptr)); 1821f6a57c1SMed Ismail Bennani 1831f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) { 1841f6a57c1SMed Ismail Bennani PyErr_Print(); 1851f6a57c1SMed Ismail Bennani PyErr_Clear(); 1861f6a57c1SMed Ismail Bennani } 1871f6a57c1SMed Ismail Bennani 188*3d4cadfbSMed Ismail Bennani if (!py_return.get()) 189*3d4cadfbSMed Ismail Bennani return llvm::None; 190*3d4cadfbSMed Ismail Bennani 191*3d4cadfbSMed Ismail Bennani llvm::Expected<unsigned long long> size = py_return.AsUnsignedLongLong(); 192*3d4cadfbSMed Ismail Bennani // FIXME: Handle error. 193*3d4cadfbSMed Ismail Bennani if (!size) 194*3d4cadfbSMed Ismail Bennani return llvm::None; 195*3d4cadfbSMed Ismail Bennani 196*3d4cadfbSMed Ismail Bennani return *size; 1971f6a57c1SMed Ismail Bennani } 1981f6a57c1SMed Ismail Bennani 1991f6a57c1SMed Ismail Bennani lldb::MemoryRegionInfoSP 2001f6a57c1SMed Ismail Bennani ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( 2011f6a57c1SMed Ismail Bennani lldb::addr_t address) { 2021f6a57c1SMed Ismail Bennani // TODO: Implement 2031f6a57c1SMed Ismail Bennani return nullptr; 2041f6a57c1SMed Ismail Bennani } 2051f6a57c1SMed Ismail Bennani 2061f6a57c1SMed Ismail Bennani StructuredData::DictionarySP 2071f6a57c1SMed Ismail Bennani ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) { 2081f6a57c1SMed Ismail Bennani // TODO: Implement 2091f6a57c1SMed Ismail Bennani return nullptr; 2101f6a57c1SMed Ismail Bennani } 2111f6a57c1SMed Ismail Bennani 2121f6a57c1SMed Ismail Bennani StructuredData::DictionarySP 2131f6a57c1SMed Ismail Bennani ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) { 2141f6a57c1SMed Ismail Bennani // TODO: Implement 2151f6a57c1SMed Ismail Bennani return nullptr; 2161f6a57c1SMed Ismail Bennani } 2171f6a57c1SMed Ismail Bennani 2181f6a57c1SMed Ismail Bennani lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( 2191f6a57c1SMed Ismail Bennani lldb::addr_t address, size_t size, Status &error) { 2201f6a57c1SMed Ismail Bennani Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 2211f6a57c1SMed Ismail Bennani Locker::FreeLock); 2221f6a57c1SMed Ismail Bennani 2231f6a57c1SMed Ismail Bennani auto error_with_message = [&error](llvm::StringRef message) { 2241f6a57c1SMed Ismail Bennani error.SetErrorString(message); 2251f6a57c1SMed Ismail Bennani return nullptr; 2261f6a57c1SMed Ismail Bennani }; 2271f6a57c1SMed Ismail Bennani 2281f6a57c1SMed Ismail Bennani static char callee_name[] = "read_memory_at_address"; 2291f6a57c1SMed Ismail Bennani std::string param_format = GetPythonValueFormatString(address); 2301f6a57c1SMed Ismail Bennani param_format += GetPythonValueFormatString(size); 2311f6a57c1SMed Ismail Bennani 2321f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 2331f6a57c1SMed Ismail Bennani return error_with_message("Python object ill-formed."); 2341f6a57c1SMed Ismail Bennani 2351f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 2361f6a57c1SMed Ismail Bennani return error_with_message("Python method not callable."); 2371f6a57c1SMed Ismail Bennani 2381f6a57c1SMed Ismail Bennani PythonObject implementor(PyRefType::Borrowed, 2391f6a57c1SMed Ismail Bennani (PyObject *)m_object_instance_sp->GetValue()); 2401f6a57c1SMed Ismail Bennani 2411f6a57c1SMed Ismail Bennani if (!implementor.IsAllocated()) 2421f6a57c1SMed Ismail Bennani return error_with_message("Python implementor not allocated."); 2431f6a57c1SMed Ismail Bennani 2441f6a57c1SMed Ismail Bennani PythonObject pmeth(PyRefType::Owned, 2451f6a57c1SMed Ismail Bennani PyObject_GetAttrString(implementor.get(), callee_name)); 2461f6a57c1SMed Ismail Bennani 2471f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 2481f6a57c1SMed Ismail Bennani PyErr_Clear(); 2491f6a57c1SMed Ismail Bennani 2501f6a57c1SMed Ismail Bennani if (!pmeth.IsAllocated()) 2511f6a57c1SMed Ismail Bennani return error_with_message("Python method not allocated."); 2521f6a57c1SMed Ismail Bennani 2531f6a57c1SMed Ismail Bennani if (PyCallable_Check(pmeth.get()) == 0) { 2541f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 2551f6a57c1SMed Ismail Bennani PyErr_Clear(); 2561f6a57c1SMed Ismail Bennani return error_with_message("Python method not callable."); 2571f6a57c1SMed Ismail Bennani } 2581f6a57c1SMed Ismail Bennani 2591f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 2601f6a57c1SMed Ismail Bennani PyErr_Clear(); 2611f6a57c1SMed Ismail Bennani 2621f6a57c1SMed Ismail Bennani PythonObject py_return(PyRefType::Owned, 2631f6a57c1SMed Ismail Bennani PyObject_CallMethod(implementor.get(), callee_name, 2641f6a57c1SMed Ismail Bennani param_format.c_str(), address, 2651f6a57c1SMed Ismail Bennani size)); 2661f6a57c1SMed Ismail Bennani 2671f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) { 2681f6a57c1SMed Ismail Bennani PyErr_Print(); 2691f6a57c1SMed Ismail Bennani PyErr_Clear(); 2701f6a57c1SMed Ismail Bennani return error_with_message("Python method could not be called."); 2711f6a57c1SMed Ismail Bennani } 2721f6a57c1SMed Ismail Bennani 2731f6a57c1SMed Ismail Bennani if (PyObject *py_ret_ptr = py_return.get()) { 2741f6a57c1SMed Ismail Bennani lldb::SBData *sb_data = 2751f6a57c1SMed Ismail Bennani (lldb::SBData *)LLDBSWIGPython_CastPyObjectToSBData(py_ret_ptr); 2761f6a57c1SMed Ismail Bennani 2771f6a57c1SMed Ismail Bennani if (!sb_data) 2781f6a57c1SMed Ismail Bennani return error_with_message( 2791f6a57c1SMed Ismail Bennani "Couldn't cast lldb::SBData to lldb::DataExtractor."); 2801f6a57c1SMed Ismail Bennani 2811f6a57c1SMed Ismail Bennani return m_interpreter.GetDataExtractorFromSBData(*sb_data); 2821f6a57c1SMed Ismail Bennani } 2831f6a57c1SMed Ismail Bennani 2841f6a57c1SMed Ismail Bennani return error_with_message("Returned object is null."); 2851f6a57c1SMed Ismail Bennani } 2861f6a57c1SMed Ismail Bennani 2871f6a57c1SMed Ismail Bennani StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() { 2881f6a57c1SMed Ismail Bennani // TODO: Implement 2891f6a57c1SMed Ismail Bennani return nullptr; 2901f6a57c1SMed Ismail Bennani } 2911f6a57c1SMed Ismail Bennani 2921f6a57c1SMed Ismail Bennani lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() { 293*3d4cadfbSMed Ismail Bennani llvm::Optional<unsigned long long> pid = GetGenericInteger("get_process_id"); 294*3d4cadfbSMed Ismail Bennani return (!pid) ? LLDB_INVALID_PROCESS_ID : *pid; 2951f6a57c1SMed Ismail Bennani } 2961f6a57c1SMed Ismail Bennani 2971f6a57c1SMed Ismail Bennani bool ScriptedProcessPythonInterface::IsAlive() { 298*3d4cadfbSMed Ismail Bennani llvm::Optional<unsigned long long> is_alive = GetGenericInteger("is_alive"); 299*3d4cadfbSMed Ismail Bennani 300*3d4cadfbSMed Ismail Bennani if (!is_alive) 301*3d4cadfbSMed Ismail Bennani return false; 302*3d4cadfbSMed Ismail Bennani 303*3d4cadfbSMed Ismail Bennani return static_cast<bool>(*is_alive); 3041f6a57c1SMed Ismail Bennani } 3051f6a57c1SMed Ismail Bennani 3061f6a57c1SMed Ismail Bennani #endif 307