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 GetStatusFromMethod("launch"); 59 } 60 61 Status ScriptedProcessPythonInterface::Resume() { 62 return GetStatusFromMethod("resume"); 63 } 64 65 bool ScriptedProcessPythonInterface::ShouldStop() { 66 llvm::Optional<unsigned long long> should_stop = 67 GetGenericInteger("should_stop"); 68 69 if (!should_stop) 70 return false; 71 72 return static_cast<bool>(*should_stop); 73 } 74 75 Status ScriptedProcessPythonInterface::Stop() { 76 return GetStatusFromMethod("stop"); 77 } 78 79 Status ScriptedProcessPythonInterface::GetStatusFromMethod( 80 llvm::StringRef method_name) { 81 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 82 Locker::FreeLock); 83 84 if (!m_object_instance_sp) 85 return Status("Python object ill-formed."); 86 87 if (!m_object_instance_sp) 88 return Status("Cannot convert Python object to StructuredData::Generic."); 89 PythonObject implementor(PyRefType::Borrowed, 90 (PyObject *)m_object_instance_sp->GetValue()); 91 92 if (!implementor.IsAllocated()) 93 return Status("Python implementor not allocated."); 94 95 PythonObject pmeth( 96 PyRefType::Owned, 97 PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); 98 99 if (PyErr_Occurred()) 100 PyErr_Clear(); 101 102 if (!pmeth.IsAllocated()) 103 return Status("Python method not allocated."); 104 105 if (PyCallable_Check(pmeth.get()) == 0) { 106 if (PyErr_Occurred()) 107 PyErr_Clear(); 108 return Status("Python method not callable."); 109 } 110 111 if (PyErr_Occurred()) 112 PyErr_Clear(); 113 114 PythonObject py_return(PyRefType::Owned, 115 PyObject_CallMethod(implementor.get(), 116 method_name.str().c_str(), 117 nullptr)); 118 119 if (PyErr_Occurred()) { 120 PyErr_Print(); 121 PyErr_Clear(); 122 return Status("Python method could not be called."); 123 } 124 125 if (PyObject *py_ret_ptr = py_return.get()) { 126 lldb::SBError *sb_error = 127 (lldb::SBError *)LLDBSWIGPython_CastPyObjectToSBError(py_ret_ptr); 128 129 if (!sb_error) 130 return Status("Couldn't cast lldb::SBError to lldb::Status."); 131 132 Status status = m_interpreter.GetStatusFromSBError(*sb_error); 133 134 if (status.Fail()) 135 return Status("error: %s", status.AsCString()); 136 137 return status; 138 } 139 140 return Status("Returned object is null."); 141 } 142 143 llvm::Optional<unsigned long long> 144 ScriptedProcessPythonInterface::GetGenericInteger(llvm::StringRef method_name) { 145 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 146 Locker::FreeLock); 147 148 if (!m_object_instance_sp) 149 return llvm::None; 150 151 if (!m_object_instance_sp) 152 return llvm::None; 153 PythonObject implementor(PyRefType::Borrowed, 154 (PyObject *)m_object_instance_sp->GetValue()); 155 156 if (!implementor.IsAllocated()) 157 return llvm::None; 158 159 PythonObject pmeth( 160 PyRefType::Owned, 161 PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); 162 163 if (PyErr_Occurred()) 164 PyErr_Clear(); 165 166 if (!pmeth.IsAllocated()) 167 return llvm::None; 168 169 if (PyCallable_Check(pmeth.get()) == 0) { 170 if (PyErr_Occurred()) 171 PyErr_Clear(); 172 return llvm::None; 173 } 174 175 if (PyErr_Occurred()) 176 PyErr_Clear(); 177 178 PythonObject py_return(PyRefType::Owned, 179 PyObject_CallMethod(implementor.get(), 180 method_name.str().c_str(), 181 nullptr)); 182 183 if (PyErr_Occurred()) { 184 PyErr_Print(); 185 PyErr_Clear(); 186 } 187 188 if (!py_return.get()) 189 return llvm::None; 190 191 llvm::Expected<unsigned long long> size = py_return.AsUnsignedLongLong(); 192 // FIXME: Handle error. 193 if (!size) 194 return llvm::None; 195 196 return *size; 197 } 198 199 lldb::MemoryRegionInfoSP 200 ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( 201 lldb::addr_t address) { 202 // TODO: Implement 203 return nullptr; 204 } 205 206 StructuredData::DictionarySP 207 ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) { 208 // TODO: Implement 209 return nullptr; 210 } 211 212 StructuredData::DictionarySP 213 ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) { 214 // TODO: Implement 215 return nullptr; 216 } 217 218 lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( 219 lldb::addr_t address, size_t size, Status &error) { 220 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 221 Locker::FreeLock); 222 223 auto error_with_message = [&error](llvm::StringRef message) { 224 error.SetErrorString(message); 225 return nullptr; 226 }; 227 228 static char callee_name[] = "read_memory_at_address"; 229 std::string param_format = GetPythonValueFormatString(address); 230 param_format += GetPythonValueFormatString(size); 231 232 if (!m_object_instance_sp) 233 return error_with_message("Python object ill-formed."); 234 235 if (!m_object_instance_sp) 236 return error_with_message("Python method not callable."); 237 238 PythonObject implementor(PyRefType::Borrowed, 239 (PyObject *)m_object_instance_sp->GetValue()); 240 241 if (!implementor.IsAllocated()) 242 return error_with_message("Python implementor not allocated."); 243 244 PythonObject pmeth(PyRefType::Owned, 245 PyObject_GetAttrString(implementor.get(), callee_name)); 246 247 if (PyErr_Occurred()) 248 PyErr_Clear(); 249 250 if (!pmeth.IsAllocated()) 251 return error_with_message("Python method not allocated."); 252 253 if (PyCallable_Check(pmeth.get()) == 0) { 254 if (PyErr_Occurred()) 255 PyErr_Clear(); 256 return error_with_message("Python method not callable."); 257 } 258 259 if (PyErr_Occurred()) 260 PyErr_Clear(); 261 262 PythonObject py_return(PyRefType::Owned, 263 PyObject_CallMethod(implementor.get(), callee_name, 264 param_format.c_str(), address, 265 size)); 266 267 if (PyErr_Occurred()) { 268 PyErr_Print(); 269 PyErr_Clear(); 270 return error_with_message("Python method could not be called."); 271 } 272 273 if (PyObject *py_ret_ptr = py_return.get()) { 274 lldb::SBData *sb_data = 275 (lldb::SBData *)LLDBSWIGPython_CastPyObjectToSBData(py_ret_ptr); 276 277 if (!sb_data) 278 return error_with_message( 279 "Couldn't cast lldb::SBData to lldb::DataExtractor."); 280 281 return m_interpreter.GetDataExtractorFromSBData(*sb_data); 282 } 283 284 return error_with_message("Returned object is null."); 285 } 286 287 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() { 288 // TODO: Implement 289 return nullptr; 290 } 291 292 lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() { 293 llvm::Optional<unsigned long long> pid = GetGenericInteger("get_process_id"); 294 return (!pid) ? LLDB_INVALID_PROCESS_ID : *pid; 295 } 296 297 bool ScriptedProcessPythonInterface::IsAlive() { 298 llvm::Optional<unsigned long long> is_alive = GetGenericInteger("is_alive"); 299 300 if (!is_alive) 301 return false; 302 303 return static_cast<bool>(*is_alive); 304 } 305 306 #endif 307