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() { 58*312b43daSMed Ismail Bennani return GetStatusFromMethod("launch"); 591f6a57c1SMed Ismail Bennani } 601f6a57c1SMed Ismail Bennani 611f6a57c1SMed Ismail Bennani Status ScriptedProcessPythonInterface::Resume() { 62*312b43daSMed Ismail Bennani return GetStatusFromMethod("resume"); 631f6a57c1SMed Ismail Bennani } 641f6a57c1SMed Ismail Bennani 65*312b43daSMed Ismail Bennani bool ScriptedProcessPythonInterface::ShouldStop() { 66*312b43daSMed Ismail Bennani return GetGenericInteger("shuold_stop"); 67*312b43daSMed Ismail Bennani } 68*312b43daSMed Ismail Bennani 69*312b43daSMed Ismail Bennani Status ScriptedProcessPythonInterface::Stop() { 70*312b43daSMed Ismail Bennani return GetStatusFromMethod("stop"); 71*312b43daSMed Ismail Bennani } 72*312b43daSMed Ismail Bennani 73*312b43daSMed Ismail Bennani Status ScriptedProcessPythonInterface::GetStatusFromMethod( 74*312b43daSMed Ismail Bennani llvm::StringRef method_name) { 751f6a57c1SMed Ismail Bennani Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 761f6a57c1SMed Ismail Bennani Locker::FreeLock); 771f6a57c1SMed Ismail Bennani 781f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 791f6a57c1SMed Ismail Bennani return Status("Python object ill-formed."); 801f6a57c1SMed Ismail Bennani 811f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 821f6a57c1SMed Ismail Bennani return Status("Cannot convert Python object to StructuredData::Generic."); 831f6a57c1SMed Ismail Bennani PythonObject implementor(PyRefType::Borrowed, 841f6a57c1SMed Ismail Bennani (PyObject *)m_object_instance_sp->GetValue()); 851f6a57c1SMed Ismail Bennani 861f6a57c1SMed Ismail Bennani if (!implementor.IsAllocated()) 871f6a57c1SMed Ismail Bennani return Status("Python implementor not allocated."); 881f6a57c1SMed Ismail Bennani 891f6a57c1SMed Ismail Bennani PythonObject pmeth( 901f6a57c1SMed Ismail Bennani PyRefType::Owned, 911f6a57c1SMed Ismail Bennani PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); 921f6a57c1SMed Ismail Bennani 931f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 941f6a57c1SMed Ismail Bennani PyErr_Clear(); 951f6a57c1SMed Ismail Bennani 961f6a57c1SMed Ismail Bennani if (!pmeth.IsAllocated()) 971f6a57c1SMed Ismail Bennani return Status("Python method not allocated."); 981f6a57c1SMed Ismail Bennani 991f6a57c1SMed Ismail Bennani if (PyCallable_Check(pmeth.get()) == 0) { 1001f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 1011f6a57c1SMed Ismail Bennani PyErr_Clear(); 1021f6a57c1SMed Ismail Bennani return Status("Python method not callable."); 1031f6a57c1SMed Ismail Bennani } 1041f6a57c1SMed Ismail Bennani 1051f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 1061f6a57c1SMed Ismail Bennani PyErr_Clear(); 1071f6a57c1SMed Ismail Bennani 1081f6a57c1SMed Ismail Bennani PythonObject py_return(PyRefType::Owned, 1091f6a57c1SMed Ismail Bennani PyObject_CallMethod(implementor.get(), 1101f6a57c1SMed Ismail Bennani method_name.str().c_str(), 1111f6a57c1SMed Ismail Bennani nullptr)); 1121f6a57c1SMed Ismail Bennani 1131f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) { 1141f6a57c1SMed Ismail Bennani PyErr_Print(); 1151f6a57c1SMed Ismail Bennani PyErr_Clear(); 1161f6a57c1SMed Ismail Bennani return Status("Python method could not be called."); 1171f6a57c1SMed Ismail Bennani } 1181f6a57c1SMed Ismail Bennani 1191f6a57c1SMed Ismail Bennani if (PyObject *py_ret_ptr = py_return.get()) { 1201f6a57c1SMed Ismail Bennani lldb::SBError *sb_error = 1211f6a57c1SMed Ismail Bennani (lldb::SBError *)LLDBSWIGPython_CastPyObjectToSBError(py_ret_ptr); 1221f6a57c1SMed Ismail Bennani 1231f6a57c1SMed Ismail Bennani if (!sb_error) 1241f6a57c1SMed Ismail Bennani return Status("Couldn't cast lldb::SBError to lldb::Status."); 1251f6a57c1SMed Ismail Bennani 1261f6a57c1SMed Ismail Bennani Status status = m_interpreter.GetStatusFromSBError(*sb_error); 1271f6a57c1SMed Ismail Bennani 1281f6a57c1SMed Ismail Bennani if (status.Fail()) 1291f6a57c1SMed Ismail Bennani return Status("error: %s", status.AsCString()); 1301f6a57c1SMed Ismail Bennani 1311f6a57c1SMed Ismail Bennani return status; 1321f6a57c1SMed Ismail Bennani } 1331f6a57c1SMed Ismail Bennani 1341f6a57c1SMed Ismail Bennani return Status("Returned object is null."); 1351f6a57c1SMed Ismail Bennani } 1361f6a57c1SMed Ismail Bennani 1371f6a57c1SMed Ismail Bennani size_t 1381f6a57c1SMed Ismail Bennani ScriptedProcessPythonInterface::GetGenericInteger(llvm::StringRef method_name) { 1391f6a57c1SMed Ismail Bennani Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 1401f6a57c1SMed Ismail Bennani Locker::FreeLock); 1411f6a57c1SMed Ismail Bennani 1421f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 1431f6a57c1SMed Ismail Bennani return LLDB_INVALID_ADDRESS; 1441f6a57c1SMed Ismail Bennani 1451f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 1461f6a57c1SMed Ismail Bennani return LLDB_INVALID_ADDRESS; 1471f6a57c1SMed Ismail Bennani PythonObject implementor(PyRefType::Borrowed, 1481f6a57c1SMed Ismail Bennani (PyObject *)m_object_instance_sp->GetValue()); 1491f6a57c1SMed Ismail Bennani 1501f6a57c1SMed Ismail Bennani if (!implementor.IsAllocated()) 1511f6a57c1SMed Ismail Bennani return LLDB_INVALID_ADDRESS; 1521f6a57c1SMed Ismail Bennani 1531f6a57c1SMed Ismail Bennani PythonObject pmeth( 1541f6a57c1SMed Ismail Bennani PyRefType::Owned, 1551f6a57c1SMed Ismail Bennani PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); 1561f6a57c1SMed Ismail Bennani 1571f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 1581f6a57c1SMed Ismail Bennani PyErr_Clear(); 1591f6a57c1SMed Ismail Bennani 1601f6a57c1SMed Ismail Bennani if (!pmeth.IsAllocated()) 1611f6a57c1SMed Ismail Bennani return LLDB_INVALID_ADDRESS; 1621f6a57c1SMed Ismail Bennani 1631f6a57c1SMed Ismail Bennani if (PyCallable_Check(pmeth.get()) == 0) { 1641f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 1651f6a57c1SMed Ismail Bennani PyErr_Clear(); 1661f6a57c1SMed Ismail Bennani return LLDB_INVALID_ADDRESS; 1671f6a57c1SMed Ismail Bennani } 1681f6a57c1SMed Ismail Bennani 1691f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 1701f6a57c1SMed Ismail Bennani PyErr_Clear(); 1711f6a57c1SMed Ismail Bennani 1721f6a57c1SMed Ismail Bennani PythonObject py_return(PyRefType::Owned, 1731f6a57c1SMed Ismail Bennani PyObject_CallMethod(implementor.get(), 1741f6a57c1SMed Ismail Bennani method_name.str().c_str(), 1751f6a57c1SMed Ismail Bennani nullptr)); 1761f6a57c1SMed Ismail Bennani 1771f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) { 1781f6a57c1SMed Ismail Bennani PyErr_Print(); 1791f6a57c1SMed Ismail Bennani PyErr_Clear(); 1801f6a57c1SMed Ismail Bennani } 1811f6a57c1SMed Ismail Bennani 1821f6a57c1SMed Ismail Bennani if (py_return.get()) { 1831f6a57c1SMed Ismail Bennani auto size = py_return.AsUnsignedLongLong(); 1841f6a57c1SMed Ismail Bennani return (size) ? *size : LLDB_INVALID_ADDRESS; 1851f6a57c1SMed Ismail Bennani } 1861f6a57c1SMed Ismail Bennani return LLDB_INVALID_ADDRESS; 1871f6a57c1SMed Ismail Bennani } 1881f6a57c1SMed Ismail Bennani 1891f6a57c1SMed Ismail Bennani lldb::MemoryRegionInfoSP 1901f6a57c1SMed Ismail Bennani ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( 1911f6a57c1SMed Ismail Bennani lldb::addr_t address) { 1921f6a57c1SMed Ismail Bennani // TODO: Implement 1931f6a57c1SMed Ismail Bennani return nullptr; 1941f6a57c1SMed Ismail Bennani } 1951f6a57c1SMed Ismail Bennani 1961f6a57c1SMed Ismail Bennani StructuredData::DictionarySP 1971f6a57c1SMed Ismail Bennani ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) { 1981f6a57c1SMed Ismail Bennani // TODO: Implement 1991f6a57c1SMed Ismail Bennani return nullptr; 2001f6a57c1SMed Ismail Bennani } 2011f6a57c1SMed Ismail Bennani 2021f6a57c1SMed Ismail Bennani StructuredData::DictionarySP 2031f6a57c1SMed Ismail Bennani ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) { 2041f6a57c1SMed Ismail Bennani // TODO: Implement 2051f6a57c1SMed Ismail Bennani return nullptr; 2061f6a57c1SMed Ismail Bennani } 2071f6a57c1SMed Ismail Bennani 2081f6a57c1SMed Ismail Bennani lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( 2091f6a57c1SMed Ismail Bennani lldb::addr_t address, size_t size, Status &error) { 2101f6a57c1SMed Ismail Bennani Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 2111f6a57c1SMed Ismail Bennani Locker::FreeLock); 2121f6a57c1SMed Ismail Bennani 2131f6a57c1SMed Ismail Bennani auto error_with_message = [&error](llvm::StringRef message) { 2141f6a57c1SMed Ismail Bennani error.SetErrorString(message); 2151f6a57c1SMed Ismail Bennani return nullptr; 2161f6a57c1SMed Ismail Bennani }; 2171f6a57c1SMed Ismail Bennani 2181f6a57c1SMed Ismail Bennani static char callee_name[] = "read_memory_at_address"; 2191f6a57c1SMed Ismail Bennani std::string param_format = GetPythonValueFormatString(address); 2201f6a57c1SMed Ismail Bennani param_format += GetPythonValueFormatString(size); 2211f6a57c1SMed Ismail Bennani 2221f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 2231f6a57c1SMed Ismail Bennani return error_with_message("Python object ill-formed."); 2241f6a57c1SMed Ismail Bennani 2251f6a57c1SMed Ismail Bennani if (!m_object_instance_sp) 2261f6a57c1SMed Ismail Bennani return error_with_message("Python method not callable."); 2271f6a57c1SMed Ismail Bennani 2281f6a57c1SMed Ismail Bennani PythonObject implementor(PyRefType::Borrowed, 2291f6a57c1SMed Ismail Bennani (PyObject *)m_object_instance_sp->GetValue()); 2301f6a57c1SMed Ismail Bennani 2311f6a57c1SMed Ismail Bennani if (!implementor.IsAllocated()) 2321f6a57c1SMed Ismail Bennani return error_with_message("Python implementor not allocated."); 2331f6a57c1SMed Ismail Bennani 2341f6a57c1SMed Ismail Bennani PythonObject pmeth(PyRefType::Owned, 2351f6a57c1SMed Ismail Bennani PyObject_GetAttrString(implementor.get(), callee_name)); 2361f6a57c1SMed Ismail Bennani 2371f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 2381f6a57c1SMed Ismail Bennani PyErr_Clear(); 2391f6a57c1SMed Ismail Bennani 2401f6a57c1SMed Ismail Bennani if (!pmeth.IsAllocated()) 2411f6a57c1SMed Ismail Bennani return error_with_message("Python method not allocated."); 2421f6a57c1SMed Ismail Bennani 2431f6a57c1SMed Ismail Bennani if (PyCallable_Check(pmeth.get()) == 0) { 2441f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 2451f6a57c1SMed Ismail Bennani PyErr_Clear(); 2461f6a57c1SMed Ismail Bennani return error_with_message("Python method not callable."); 2471f6a57c1SMed Ismail Bennani } 2481f6a57c1SMed Ismail Bennani 2491f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) 2501f6a57c1SMed Ismail Bennani PyErr_Clear(); 2511f6a57c1SMed Ismail Bennani 2521f6a57c1SMed Ismail Bennani PythonObject py_return(PyRefType::Owned, 2531f6a57c1SMed Ismail Bennani PyObject_CallMethod(implementor.get(), callee_name, 2541f6a57c1SMed Ismail Bennani param_format.c_str(), address, 2551f6a57c1SMed Ismail Bennani size)); 2561f6a57c1SMed Ismail Bennani 2571f6a57c1SMed Ismail Bennani if (PyErr_Occurred()) { 2581f6a57c1SMed Ismail Bennani PyErr_Print(); 2591f6a57c1SMed Ismail Bennani PyErr_Clear(); 2601f6a57c1SMed Ismail Bennani return error_with_message("Python method could not be called."); 2611f6a57c1SMed Ismail Bennani } 2621f6a57c1SMed Ismail Bennani 2631f6a57c1SMed Ismail Bennani if (PyObject *py_ret_ptr = py_return.get()) { 2641f6a57c1SMed Ismail Bennani lldb::SBData *sb_data = 2651f6a57c1SMed Ismail Bennani (lldb::SBData *)LLDBSWIGPython_CastPyObjectToSBData(py_ret_ptr); 2661f6a57c1SMed Ismail Bennani 2671f6a57c1SMed Ismail Bennani if (!sb_data) 2681f6a57c1SMed Ismail Bennani return error_with_message( 2691f6a57c1SMed Ismail Bennani "Couldn't cast lldb::SBData to lldb::DataExtractor."); 2701f6a57c1SMed Ismail Bennani 2711f6a57c1SMed Ismail Bennani return m_interpreter.GetDataExtractorFromSBData(*sb_data); 2721f6a57c1SMed Ismail Bennani } 2731f6a57c1SMed Ismail Bennani 2741f6a57c1SMed Ismail Bennani return error_with_message("Returned object is null."); 2751f6a57c1SMed Ismail Bennani } 2761f6a57c1SMed Ismail Bennani 2771f6a57c1SMed Ismail Bennani StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() { 2781f6a57c1SMed Ismail Bennani // TODO: Implement 2791f6a57c1SMed Ismail Bennani return nullptr; 2801f6a57c1SMed Ismail Bennani } 2811f6a57c1SMed Ismail Bennani 2821f6a57c1SMed Ismail Bennani lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() { 2831f6a57c1SMed Ismail Bennani size_t pid = GetGenericInteger("get_process_id"); 2841f6a57c1SMed Ismail Bennani 2851f6a57c1SMed Ismail Bennani return (pid >= std::numeric_limits<lldb::pid_t>::max()) 2861f6a57c1SMed Ismail Bennani ? LLDB_INVALID_PROCESS_ID 2871f6a57c1SMed Ismail Bennani : pid; 2881f6a57c1SMed Ismail Bennani } 2891f6a57c1SMed Ismail Bennani 2901f6a57c1SMed Ismail Bennani bool ScriptedProcessPythonInterface::IsAlive() { 2911f6a57c1SMed Ismail Bennani return GetGenericInteger("is_alive"); 2921f6a57c1SMed Ismail Bennani } 2931f6a57c1SMed Ismail Bennani 2941f6a57c1SMed Ismail Bennani #endif 295