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