//===-- ScriptedProcessPythonInterface.cpp --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "lldb/Host/Config.h" #if LLDB_ENABLE_PYTHON // LLDB Python header must be included first #include "../lldb-python.h" #endif #include "lldb/Target/Process.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-enumerations.h" #if LLDB_ENABLE_PYTHON #include "../SWIGPythonBridge.h" #include "../ScriptInterpreterPythonImpl.h" #include "ScriptedProcessPythonInterface.h" #include "ScriptedThreadPythonInterface.h" #include using namespace lldb; using namespace lldb_private; using namespace lldb_private::python; using Locker = ScriptInterpreterPythonImpl::Locker; ScriptedProcessPythonInterface::ScriptedProcessPythonInterface( ScriptInterpreterPythonImpl &interpreter) : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {} llvm::Expected ScriptedProcessPythonInterface::CreatePluginObject( llvm::StringRef class_name, ExecutionContext &exe_ctx, StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { ExecutionContextRefSP exe_ctx_ref_sp = std::make_shared(exe_ctx); StructuredDataImpl sd_impl(args_sp); return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj, exe_ctx_ref_sp, sd_impl); } StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() { Status error; StructuredData::DictionarySP dict = Dispatch("get_capabilities", error); if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) return {}; return dict; } Status ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) { lldb::ProcessAttachInfoSP attach_info_sp = std::make_shared(attach_info); return GetStatusFromMethod("attach", attach_info_sp); } Status ScriptedProcessPythonInterface::Launch() { return GetStatusFromMethod("launch"); } Status ScriptedProcessPythonInterface::Resume() { // When calling ScriptedProcess.Resume from lldb we should always stop. return GetStatusFromMethod("resume", /*should_stop=*/true); } std::optional ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( lldb::addr_t address, Status &error) { auto mem_region = Dispatch>( "get_memory_region_containing_address", error, address); if (error.Fail()) { return ErrorWithMessage(LLVM_PRETTY_FUNCTION, error.AsCString(), error); } return mem_region; } StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() { Status error; StructuredData::DictionarySP dict = Dispatch("get_threads_info", error); if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) return {}; return dict; } bool ScriptedProcessPythonInterface::CreateBreakpoint(lldb::addr_t addr, Status &error) { Status py_error; StructuredData::ObjectSP obj = Dispatch("create_breakpoint", py_error, addr, error); // If there was an error on the python call, surface it to the user. if (py_error.Fail()) error = py_error; if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return {}; return obj->GetBooleanValue(); } lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( lldb::addr_t address, size_t size, Status &error) { Status py_error; lldb::DataExtractorSP data_sp = Dispatch( "read_memory_at_address", py_error, address, size, error); // If there was an error on the python call, surface it to the user. if (py_error.Fail()) error = py_error; return data_sp; } lldb::offset_t ScriptedProcessPythonInterface::WriteMemoryAtAddress( lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) { Status py_error; StructuredData::ObjectSP obj = Dispatch("write_memory_at_address", py_error, addr, data_sp, error); if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return LLDB_INVALID_OFFSET; // If there was an error on the python call, surface it to the user. if (py_error.Fail()) error = py_error; return obj->GetUnsignedIntegerValue(LLDB_INVALID_OFFSET); } StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() { Status error; StructuredData::ArraySP array = Dispatch("get_loaded_images", error); if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, array, error)) return {}; return array; } lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() { Status error; StructuredData::ObjectSP obj = Dispatch("get_process_id", error); if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return LLDB_INVALID_PROCESS_ID; return obj->GetUnsignedIntegerValue(LLDB_INVALID_PROCESS_ID); } bool ScriptedProcessPythonInterface::IsAlive() { Status error; StructuredData::ObjectSP obj = Dispatch("is_alive", error); if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return {}; return obj->GetBooleanValue(); } std::optional ScriptedProcessPythonInterface::GetScriptedThreadPluginName() { Status error; StructuredData::ObjectSP obj = Dispatch("get_scripted_thread_plugin", error); if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return {}; return obj->GetStringValue().str(); } lldb::ScriptedThreadInterfaceSP ScriptedProcessPythonInterface::CreateScriptedThreadInterface() { return m_interpreter.CreateScriptedThreadInterface(); } StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() { Status error; StructuredData::DictionarySP dict = Dispatch("get_process_metadata", error); if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) return {}; return dict; } #endif