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