15f757f3fSDimitry Andric //===-- ScriptedProcessPythonInterface.cpp --------------------------------===//
25f757f3fSDimitry Andric //
35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f757f3fSDimitry Andric //
75f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
85f757f3fSDimitry Andric 
95f757f3fSDimitry Andric #include "lldb/Host/Config.h"
105f757f3fSDimitry Andric #if LLDB_ENABLE_PYTHON
115f757f3fSDimitry Andric // LLDB Python header must be included first
125f757f3fSDimitry Andric #include "../lldb-python.h"
135f757f3fSDimitry Andric #endif
145f757f3fSDimitry Andric #include "lldb/Target/Process.h"
155f757f3fSDimitry Andric #include "lldb/Utility/Log.h"
165f757f3fSDimitry Andric #include "lldb/Utility/Status.h"
175f757f3fSDimitry Andric #include "lldb/lldb-enumerations.h"
185f757f3fSDimitry Andric 
195f757f3fSDimitry Andric #if LLDB_ENABLE_PYTHON
205f757f3fSDimitry Andric 
215f757f3fSDimitry Andric #include "../SWIGPythonBridge.h"
225f757f3fSDimitry Andric #include "../ScriptInterpreterPythonImpl.h"
235f757f3fSDimitry Andric #include "ScriptedProcessPythonInterface.h"
245f757f3fSDimitry Andric #include "ScriptedThreadPythonInterface.h"
255f757f3fSDimitry Andric #include <optional>
265f757f3fSDimitry Andric 
275f757f3fSDimitry Andric using namespace lldb;
285f757f3fSDimitry Andric using namespace lldb_private;
295f757f3fSDimitry Andric using namespace lldb_private::python;
305f757f3fSDimitry Andric using Locker = ScriptInterpreterPythonImpl::Locker;
315f757f3fSDimitry Andric 
325f757f3fSDimitry Andric ScriptedProcessPythonInterface::ScriptedProcessPythonInterface(
335f757f3fSDimitry Andric     ScriptInterpreterPythonImpl &interpreter)
345f757f3fSDimitry Andric     : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {}
355f757f3fSDimitry Andric 
365f757f3fSDimitry Andric llvm::Expected<StructuredData::GenericSP>
375f757f3fSDimitry Andric ScriptedProcessPythonInterface::CreatePluginObject(
385f757f3fSDimitry Andric     llvm::StringRef class_name, ExecutionContext &exe_ctx,
395f757f3fSDimitry Andric     StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
405f757f3fSDimitry Andric   ExecutionContextRefSP exe_ctx_ref_sp =
415f757f3fSDimitry Andric       std::make_shared<ExecutionContextRef>(exe_ctx);
425f757f3fSDimitry Andric   StructuredDataImpl sd_impl(args_sp);
435f757f3fSDimitry Andric   return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj,
445f757f3fSDimitry Andric                                                      exe_ctx_ref_sp, sd_impl);
455f757f3fSDimitry Andric }
465f757f3fSDimitry Andric 
475f757f3fSDimitry Andric StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() {
485f757f3fSDimitry Andric   Status error;
495f757f3fSDimitry Andric   StructuredData::DictionarySP dict =
505f757f3fSDimitry Andric       Dispatch<StructuredData::DictionarySP>("get_capabilities", error);
515f757f3fSDimitry Andric 
52*0fca6ea1SDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict,
53*0fca6ea1SDimitry Andric                                                     error))
545f757f3fSDimitry Andric     return {};
555f757f3fSDimitry Andric 
565f757f3fSDimitry Andric   return dict;
575f757f3fSDimitry Andric }
585f757f3fSDimitry Andric 
595f757f3fSDimitry Andric Status
605f757f3fSDimitry Andric ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) {
615f757f3fSDimitry Andric   lldb::ProcessAttachInfoSP attach_info_sp =
625f757f3fSDimitry Andric       std::make_shared<ProcessAttachInfo>(attach_info);
635f757f3fSDimitry Andric   return GetStatusFromMethod("attach", attach_info_sp);
645f757f3fSDimitry Andric }
655f757f3fSDimitry Andric 
665f757f3fSDimitry Andric Status ScriptedProcessPythonInterface::Launch() {
675f757f3fSDimitry Andric   return GetStatusFromMethod("launch");
685f757f3fSDimitry Andric }
695f757f3fSDimitry Andric 
705f757f3fSDimitry Andric Status ScriptedProcessPythonInterface::Resume() {
715f757f3fSDimitry Andric   // When calling ScriptedProcess.Resume from lldb we should always stop.
725f757f3fSDimitry Andric   return GetStatusFromMethod("resume", /*should_stop=*/true);
735f757f3fSDimitry Andric }
745f757f3fSDimitry Andric 
755f757f3fSDimitry Andric std::optional<MemoryRegionInfo>
765f757f3fSDimitry Andric ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
775f757f3fSDimitry Andric     lldb::addr_t address, Status &error) {
785f757f3fSDimitry Andric   auto mem_region = Dispatch<std::optional<MemoryRegionInfo>>(
795f757f3fSDimitry Andric       "get_memory_region_containing_address", error, address);
805f757f3fSDimitry Andric 
815f757f3fSDimitry Andric   if (error.Fail()) {
825f757f3fSDimitry Andric     return ErrorWithMessage<MemoryRegionInfo>(LLVM_PRETTY_FUNCTION,
835f757f3fSDimitry Andric                                               error.AsCString(), error);
845f757f3fSDimitry Andric   }
855f757f3fSDimitry Andric 
865f757f3fSDimitry Andric   return mem_region;
875f757f3fSDimitry Andric }
885f757f3fSDimitry Andric 
895f757f3fSDimitry Andric StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() {
905f757f3fSDimitry Andric   Status error;
915f757f3fSDimitry Andric   StructuredData::DictionarySP dict =
925f757f3fSDimitry Andric       Dispatch<StructuredData::DictionarySP>("get_threads_info", error);
935f757f3fSDimitry Andric 
94*0fca6ea1SDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict,
95*0fca6ea1SDimitry Andric                                                     error))
965f757f3fSDimitry Andric     return {};
975f757f3fSDimitry Andric 
985f757f3fSDimitry Andric   return dict;
995f757f3fSDimitry Andric }
1005f757f3fSDimitry Andric 
1015f757f3fSDimitry Andric bool ScriptedProcessPythonInterface::CreateBreakpoint(lldb::addr_t addr,
1025f757f3fSDimitry Andric                                                       Status &error) {
1035f757f3fSDimitry Andric   Status py_error;
1045f757f3fSDimitry Andric   StructuredData::ObjectSP obj =
1055f757f3fSDimitry Andric       Dispatch("create_breakpoint", py_error, addr, error);
1065f757f3fSDimitry Andric 
1075f757f3fSDimitry Andric   // If there was an error on the python call, surface it to the user.
1085f757f3fSDimitry Andric   if (py_error.Fail())
1095f757f3fSDimitry Andric     error = py_error;
1105f757f3fSDimitry Andric 
111*0fca6ea1SDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
112*0fca6ea1SDimitry Andric                                                     error))
1135f757f3fSDimitry Andric     return {};
1145f757f3fSDimitry Andric 
1155f757f3fSDimitry Andric   return obj->GetBooleanValue();
1165f757f3fSDimitry Andric }
1175f757f3fSDimitry Andric 
1185f757f3fSDimitry Andric lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress(
1195f757f3fSDimitry Andric     lldb::addr_t address, size_t size, Status &error) {
1205f757f3fSDimitry Andric   Status py_error;
1215f757f3fSDimitry Andric   lldb::DataExtractorSP data_sp = Dispatch<lldb::DataExtractorSP>(
1225f757f3fSDimitry Andric       "read_memory_at_address", py_error, address, size, error);
1235f757f3fSDimitry Andric 
1245f757f3fSDimitry Andric   // If there was an error on the python call, surface it to the user.
1255f757f3fSDimitry Andric   if (py_error.Fail())
1265f757f3fSDimitry Andric     error = py_error;
1275f757f3fSDimitry Andric 
1285f757f3fSDimitry Andric   return data_sp;
1295f757f3fSDimitry Andric }
1305f757f3fSDimitry Andric 
1315f757f3fSDimitry Andric lldb::offset_t ScriptedProcessPythonInterface::WriteMemoryAtAddress(
1325f757f3fSDimitry Andric     lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) {
1335f757f3fSDimitry Andric   Status py_error;
1345f757f3fSDimitry Andric   StructuredData::ObjectSP obj =
1355f757f3fSDimitry Andric       Dispatch("write_memory_at_address", py_error, addr, data_sp, error);
1365f757f3fSDimitry Andric 
137*0fca6ea1SDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
138*0fca6ea1SDimitry Andric                                                     error))
1395f757f3fSDimitry Andric     return LLDB_INVALID_OFFSET;
1405f757f3fSDimitry Andric 
1415f757f3fSDimitry Andric   // If there was an error on the python call, surface it to the user.
1425f757f3fSDimitry Andric   if (py_error.Fail())
1435f757f3fSDimitry Andric     error = py_error;
1445f757f3fSDimitry Andric 
1455f757f3fSDimitry Andric   return obj->GetUnsignedIntegerValue(LLDB_INVALID_OFFSET);
1465f757f3fSDimitry Andric }
1475f757f3fSDimitry Andric 
1485f757f3fSDimitry Andric StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() {
1495f757f3fSDimitry Andric   Status error;
1505f757f3fSDimitry Andric   StructuredData::ArraySP array =
1515f757f3fSDimitry Andric       Dispatch<StructuredData::ArraySP>("get_loaded_images", error);
1525f757f3fSDimitry Andric 
153*0fca6ea1SDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, array,
154*0fca6ea1SDimitry Andric                                                     error))
1555f757f3fSDimitry Andric     return {};
1565f757f3fSDimitry Andric 
1575f757f3fSDimitry Andric   return array;
1585f757f3fSDimitry Andric }
1595f757f3fSDimitry Andric 
1605f757f3fSDimitry Andric lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() {
1615f757f3fSDimitry Andric   Status error;
1625f757f3fSDimitry Andric   StructuredData::ObjectSP obj = Dispatch("get_process_id", error);
1635f757f3fSDimitry Andric 
164*0fca6ea1SDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
165*0fca6ea1SDimitry Andric                                                     error))
1665f757f3fSDimitry Andric     return LLDB_INVALID_PROCESS_ID;
1675f757f3fSDimitry Andric 
1685f757f3fSDimitry Andric   return obj->GetUnsignedIntegerValue(LLDB_INVALID_PROCESS_ID);
1695f757f3fSDimitry Andric }
1705f757f3fSDimitry Andric 
1715f757f3fSDimitry Andric bool ScriptedProcessPythonInterface::IsAlive() {
1725f757f3fSDimitry Andric   Status error;
1735f757f3fSDimitry Andric   StructuredData::ObjectSP obj = Dispatch("is_alive", error);
1745f757f3fSDimitry Andric 
175*0fca6ea1SDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
176*0fca6ea1SDimitry Andric                                                     error))
1775f757f3fSDimitry Andric     return {};
1785f757f3fSDimitry Andric 
1795f757f3fSDimitry Andric   return obj->GetBooleanValue();
1805f757f3fSDimitry Andric }
1815f757f3fSDimitry Andric 
1825f757f3fSDimitry Andric std::optional<std::string>
1835f757f3fSDimitry Andric ScriptedProcessPythonInterface::GetScriptedThreadPluginName() {
1845f757f3fSDimitry Andric   Status error;
1855f757f3fSDimitry Andric   StructuredData::ObjectSP obj = Dispatch("get_scripted_thread_plugin", error);
1865f757f3fSDimitry Andric 
187*0fca6ea1SDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
188*0fca6ea1SDimitry Andric                                                     error))
1895f757f3fSDimitry Andric     return {};
1905f757f3fSDimitry Andric 
1915f757f3fSDimitry Andric   return obj->GetStringValue().str();
1925f757f3fSDimitry Andric }
1935f757f3fSDimitry Andric 
1945f757f3fSDimitry Andric lldb::ScriptedThreadInterfaceSP
1955f757f3fSDimitry Andric ScriptedProcessPythonInterface::CreateScriptedThreadInterface() {
1965f757f3fSDimitry Andric   return m_interpreter.CreateScriptedThreadInterface();
1975f757f3fSDimitry Andric }
1985f757f3fSDimitry Andric 
1995f757f3fSDimitry Andric StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() {
2005f757f3fSDimitry Andric   Status error;
2015f757f3fSDimitry Andric   StructuredData::DictionarySP dict =
2025f757f3fSDimitry Andric       Dispatch<StructuredData::DictionarySP>("get_process_metadata", error);
2035f757f3fSDimitry Andric 
204*0fca6ea1SDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict,
205*0fca6ea1SDimitry Andric                                                     error))
2065f757f3fSDimitry Andric     return {};
2075f757f3fSDimitry Andric 
2085f757f3fSDimitry Andric   return dict;
2095f757f3fSDimitry Andric }
2105f757f3fSDimitry Andric 
2115f757f3fSDimitry Andric #endif
212