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/Core/PluginManager.h" 10 #include "lldb/Host/Config.h" 11 #include "lldb/Utility/Log.h" 12 #include "lldb/Utility/Status.h" 13 #include "lldb/lldb-enumerations.h" 14 15 #if LLDB_ENABLE_PYTHON 16 17 // clang-format off 18 // LLDB Python header must be included first 19 #include "../lldb-python.h" 20 21 #include "../SWIGPythonBridge.h" 22 #include "../ScriptInterpreterPythonImpl.h" 23 #include "ScriptedThreadPythonInterface.h" 24 #include "ScriptedProcessPythonInterface.h" 25 26 // Included in this position to prevent redefinition of pid_t on Windows. 27 #include "lldb/Target/Process.h" 28 //clang-format off 29 30 #include <optional> 31 32 using namespace lldb; 33 using namespace lldb_private; 34 using namespace lldb_private::python; 35 using Locker = ScriptInterpreterPythonImpl::Locker; 36 37 ScriptedProcessPythonInterface::ScriptedProcessPythonInterface( 38 ScriptInterpreterPythonImpl &interpreter) 39 : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {} 40 41 llvm::Expected<StructuredData::GenericSP> 42 ScriptedProcessPythonInterface::CreatePluginObject( 43 llvm::StringRef class_name, ExecutionContext &exe_ctx, 44 StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { 45 ExecutionContextRefSP exe_ctx_ref_sp = 46 std::make_shared<ExecutionContextRef>(exe_ctx); 47 StructuredDataImpl sd_impl(args_sp); 48 return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj, 49 exe_ctx_ref_sp, sd_impl); 50 } 51 52 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() { 53 Status error; 54 StructuredData::DictionarySP dict = 55 Dispatch<StructuredData::DictionarySP>("get_capabilities", error); 56 57 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, 58 error)) 59 return {}; 60 61 return dict; 62 } 63 64 Status 65 ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) { 66 lldb::ProcessAttachInfoSP attach_info_sp = 67 std::make_shared<ProcessAttachInfo>(attach_info); 68 return GetStatusFromMethod("attach", attach_info_sp); 69 } 70 71 Status ScriptedProcessPythonInterface::Launch() { 72 return GetStatusFromMethod("launch"); 73 } 74 75 Status ScriptedProcessPythonInterface::Resume() { 76 // When calling ScriptedProcess.Resume from lldb we should always stop. 77 return GetStatusFromMethod("resume", /*should_stop=*/true); 78 } 79 80 std::optional<MemoryRegionInfo> 81 ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( 82 lldb::addr_t address, Status &error) { 83 auto mem_region = Dispatch<std::optional<MemoryRegionInfo>>( 84 "get_memory_region_containing_address", error, address); 85 86 if (error.Fail()) { 87 return ErrorWithMessage<MemoryRegionInfo>(LLVM_PRETTY_FUNCTION, 88 error.AsCString(), error); 89 } 90 91 return mem_region; 92 } 93 94 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() { 95 Status error; 96 StructuredData::DictionarySP dict = 97 Dispatch<StructuredData::DictionarySP>("get_threads_info", error); 98 99 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, 100 error)) 101 return {}; 102 103 return dict; 104 } 105 106 bool ScriptedProcessPythonInterface::CreateBreakpoint(lldb::addr_t addr, 107 Status &error) { 108 Status py_error; 109 StructuredData::ObjectSP obj = 110 Dispatch("create_breakpoint", py_error, addr, error); 111 112 // If there was an error on the python call, surface it to the user. 113 if (py_error.Fail()) 114 error = std::move(py_error); 115 116 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, 117 error)) 118 return {}; 119 120 return obj->GetBooleanValue(); 121 } 122 123 lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( 124 lldb::addr_t address, size_t size, Status &error) { 125 Status py_error; 126 lldb::DataExtractorSP data_sp = Dispatch<lldb::DataExtractorSP>( 127 "read_memory_at_address", py_error, address, size, error); 128 129 // If there was an error on the python call, surface it to the user. 130 if (py_error.Fail()) 131 error = std::move(py_error); 132 133 return data_sp; 134 } 135 136 lldb::offset_t ScriptedProcessPythonInterface::WriteMemoryAtAddress( 137 lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) { 138 Status py_error; 139 StructuredData::ObjectSP obj = 140 Dispatch("write_memory_at_address", py_error, addr, data_sp, error); 141 142 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, 143 error)) 144 return LLDB_INVALID_OFFSET; 145 146 // If there was an error on the python call, surface it to the user. 147 if (py_error.Fail()) 148 error = std::move(py_error); 149 150 return obj->GetUnsignedIntegerValue(LLDB_INVALID_OFFSET); 151 } 152 153 StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() { 154 Status error; 155 StructuredData::ArraySP array = 156 Dispatch<StructuredData::ArraySP>("get_loaded_images", error); 157 158 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, array, 159 error)) 160 return {}; 161 162 return array; 163 } 164 165 lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() { 166 Status error; 167 StructuredData::ObjectSP obj = Dispatch("get_process_id", error); 168 169 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, 170 error)) 171 return LLDB_INVALID_PROCESS_ID; 172 173 return obj->GetUnsignedIntegerValue(LLDB_INVALID_PROCESS_ID); 174 } 175 176 bool ScriptedProcessPythonInterface::IsAlive() { 177 Status error; 178 StructuredData::ObjectSP obj = Dispatch("is_alive", error); 179 180 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, 181 error)) 182 return {}; 183 184 return obj->GetBooleanValue(); 185 } 186 187 std::optional<std::string> 188 ScriptedProcessPythonInterface::GetScriptedThreadPluginName() { 189 Status error; 190 StructuredData::ObjectSP obj = Dispatch("get_scripted_thread_plugin", error); 191 192 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, 193 error)) 194 return {}; 195 196 return obj->GetStringValue().str(); 197 } 198 199 lldb::ScriptedThreadInterfaceSP 200 ScriptedProcessPythonInterface::CreateScriptedThreadInterface() { 201 return m_interpreter.CreateScriptedThreadInterface(); 202 } 203 204 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() { 205 Status error; 206 StructuredData::DictionarySP dict = 207 Dispatch<StructuredData::DictionarySP>("get_process_metadata", error); 208 209 if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, 210 error)) 211 return {}; 212 213 return dict; 214 } 215 216 void ScriptedProcessPythonInterface::Initialize() { 217 const std::vector<llvm::StringRef> ci_usages = { 218 "process attach -C <script-name> [-k key -v value ...]", 219 "process launch -C <script-name> [-k key -v value ...]"}; 220 const std::vector<llvm::StringRef> api_usages = { 221 "SBAttachInfo.SetScriptedProcessClassName", 222 "SBAttachInfo.SetScriptedProcessDictionary", 223 "SBTarget.Attach", 224 "SBLaunchInfo.SetScriptedProcessClassName", 225 "SBLaunchInfo.SetScriptedProcessDictionary", 226 "SBTarget.Launch"}; 227 PluginManager::RegisterPlugin( 228 GetPluginNameStatic(), llvm::StringRef("Mock process state"), 229 CreateInstance, eScriptLanguagePython, {ci_usages, api_usages}); 230 } 231 232 void ScriptedProcessPythonInterface::Terminate() { 233 PluginManager::UnregisterPlugin(CreateInstance); 234 } 235 236 #endif 237