1344a3780SDimitry Andric //===-- ScriptedProcessPythonInterface.cpp --------------------------------===//
2344a3780SDimitry Andric //
3344a3780SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4344a3780SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5344a3780SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6344a3780SDimitry Andric //
7344a3780SDimitry Andric //===----------------------------------------------------------------------===//
8344a3780SDimitry Andric 
9344a3780SDimitry Andric #include "lldb/Host/Config.h"
107fa27ce4SDimitry Andric #if LLDB_ENABLE_PYTHON
117fa27ce4SDimitry Andric // LLDB Python header must be included first
12b1c73532SDimitry Andric #include "../lldb-python.h"
137fa27ce4SDimitry Andric #endif
147fa27ce4SDimitry Andric #include "lldb/Target/Process.h"
15c0981da4SDimitry Andric #include "lldb/Utility/Log.h"
16e3b55780SDimitry Andric #include "lldb/Utility/Status.h"
17344a3780SDimitry Andric #include "lldb/lldb-enumerations.h"
18344a3780SDimitry Andric 
19344a3780SDimitry Andric #if LLDB_ENABLE_PYTHON
20344a3780SDimitry Andric 
21b1c73532SDimitry Andric #include "../SWIGPythonBridge.h"
22b1c73532SDimitry Andric #include "../ScriptInterpreterPythonImpl.h"
23344a3780SDimitry Andric #include "ScriptedProcessPythonInterface.h"
24c0981da4SDimitry Andric #include "ScriptedThreadPythonInterface.h"
25e3b55780SDimitry Andric #include <optional>
26344a3780SDimitry Andric 
27344a3780SDimitry Andric using namespace lldb;
28344a3780SDimitry Andric using namespace lldb_private;
29344a3780SDimitry Andric using namespace lldb_private::python;
30344a3780SDimitry Andric using Locker = ScriptInterpreterPythonImpl::Locker;
31344a3780SDimitry Andric 
ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl & interpreter)32c0981da4SDimitry Andric ScriptedProcessPythonInterface::ScriptedProcessPythonInterface(
33c0981da4SDimitry Andric     ScriptInterpreterPythonImpl &interpreter)
34c0981da4SDimitry Andric     : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {}
35c0981da4SDimitry Andric 
36b1c73532SDimitry Andric llvm::Expected<StructuredData::GenericSP>
CreatePluginObject(llvm::StringRef class_name,ExecutionContext & exe_ctx,StructuredData::DictionarySP args_sp,StructuredData::Generic * script_obj)37b1c73532SDimitry Andric ScriptedProcessPythonInterface::CreatePluginObject(
38c0981da4SDimitry Andric     llvm::StringRef class_name, ExecutionContext &exe_ctx,
396f8fc217SDimitry Andric     StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
40b1c73532SDimitry Andric   ExecutionContextRefSP exe_ctx_ref_sp =
41e3b55780SDimitry Andric       std::make_shared<ExecutionContextRef>(exe_ctx);
42b1c73532SDimitry Andric   StructuredDataImpl sd_impl(args_sp);
43b1c73532SDimitry Andric   return ScriptedPythonInterface::CreatePluginObject(class_name, script_obj,
44b1c73532SDimitry Andric                                                      exe_ctx_ref_sp, sd_impl);
45344a3780SDimitry Andric }
46344a3780SDimitry Andric 
GetCapabilities()477fa27ce4SDimitry Andric StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() {
487fa27ce4SDimitry Andric   Status error;
497fa27ce4SDimitry Andric   StructuredData::DictionarySP dict =
507fa27ce4SDimitry Andric       Dispatch<StructuredData::DictionarySP>("get_capabilities", error);
517fa27ce4SDimitry Andric 
52ac9a064cSDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict,
53ac9a064cSDimitry Andric                                                     error))
547fa27ce4SDimitry Andric     return {};
557fa27ce4SDimitry Andric 
567fa27ce4SDimitry Andric   return dict;
577fa27ce4SDimitry Andric }
587fa27ce4SDimitry Andric 
597fa27ce4SDimitry Andric Status
Attach(const ProcessAttachInfo & attach_info)607fa27ce4SDimitry Andric ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) {
617fa27ce4SDimitry Andric   lldb::ProcessAttachInfoSP attach_info_sp =
627fa27ce4SDimitry Andric       std::make_shared<ProcessAttachInfo>(attach_info);
637fa27ce4SDimitry Andric   return GetStatusFromMethod("attach", attach_info_sp);
647fa27ce4SDimitry Andric }
657fa27ce4SDimitry Andric 
Launch()66344a3780SDimitry Andric Status ScriptedProcessPythonInterface::Launch() {
67344a3780SDimitry Andric   return GetStatusFromMethod("launch");
68344a3780SDimitry Andric }
69344a3780SDimitry Andric 
Resume()70344a3780SDimitry Andric Status ScriptedProcessPythonInterface::Resume() {
717fa27ce4SDimitry Andric   // When calling ScriptedProcess.Resume from lldb we should always stop.
727fa27ce4SDimitry Andric   return GetStatusFromMethod("resume", /*should_stop=*/true);
73344a3780SDimitry Andric }
74344a3780SDimitry Andric 
75e3b55780SDimitry Andric std::optional<MemoryRegionInfo>
GetMemoryRegionContainingAddress(lldb::addr_t address,Status & error)76344a3780SDimitry Andric ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
77c0981da4SDimitry Andric     lldb::addr_t address, Status &error) {
78e3b55780SDimitry Andric   auto mem_region = Dispatch<std::optional<MemoryRegionInfo>>(
79c0981da4SDimitry Andric       "get_memory_region_containing_address", error, address);
80c0981da4SDimitry Andric 
81c0981da4SDimitry Andric   if (error.Fail()) {
82c0981da4SDimitry Andric     return ErrorWithMessage<MemoryRegionInfo>(LLVM_PRETTY_FUNCTION,
83c0981da4SDimitry Andric                                               error.AsCString(), error);
84c0981da4SDimitry Andric   }
85c0981da4SDimitry Andric 
86c0981da4SDimitry Andric   return mem_region;
87344a3780SDimitry Andric }
88344a3780SDimitry Andric 
GetThreadsInfo()896f8fc217SDimitry Andric StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() {
906f8fc217SDimitry Andric   Status error;
916f8fc217SDimitry Andric   StructuredData::DictionarySP dict =
926f8fc217SDimitry Andric       Dispatch<StructuredData::DictionarySP>("get_threads_info", error);
936f8fc217SDimitry Andric 
94ac9a064cSDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict,
95ac9a064cSDimitry Andric                                                     error))
966f8fc217SDimitry Andric     return {};
976f8fc217SDimitry Andric 
986f8fc217SDimitry Andric   return dict;
996f8fc217SDimitry Andric }
1006f8fc217SDimitry Andric 
CreateBreakpoint(lldb::addr_t addr,Status & error)1017fa27ce4SDimitry Andric bool ScriptedProcessPythonInterface::CreateBreakpoint(lldb::addr_t addr,
1027fa27ce4SDimitry Andric                                                       Status &error) {
1037fa27ce4SDimitry Andric   Status py_error;
1047fa27ce4SDimitry Andric   StructuredData::ObjectSP obj =
1057fa27ce4SDimitry Andric       Dispatch("create_breakpoint", py_error, addr, error);
1067fa27ce4SDimitry Andric 
1077fa27ce4SDimitry Andric   // If there was an error on the python call, surface it to the user.
1087fa27ce4SDimitry Andric   if (py_error.Fail())
1097fa27ce4SDimitry Andric     error = py_error;
110c0981da4SDimitry Andric 
111ac9a064cSDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
112ac9a064cSDimitry Andric                                                     error))
113c0981da4SDimitry Andric     return {};
114c0981da4SDimitry Andric 
1157fa27ce4SDimitry Andric   return obj->GetBooleanValue();
116344a3780SDimitry Andric }
117344a3780SDimitry Andric 
ReadMemoryAtAddress(lldb::addr_t address,size_t size,Status & error)118344a3780SDimitry Andric lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress(
119344a3780SDimitry Andric     lldb::addr_t address, size_t size, Status &error) {
120e3b55780SDimitry Andric   Status py_error;
121e3b55780SDimitry Andric   lldb::DataExtractorSP data_sp = Dispatch<lldb::DataExtractorSP>(
122e3b55780SDimitry Andric       "read_memory_at_address", py_error, address, size, error);
123e3b55780SDimitry Andric 
124e3b55780SDimitry Andric   // If there was an error on the python call, surface it to the user.
125e3b55780SDimitry Andric   if (py_error.Fail())
126e3b55780SDimitry Andric     error = py_error;
127e3b55780SDimitry Andric 
128e3b55780SDimitry Andric   return data_sp;
129344a3780SDimitry Andric }
130344a3780SDimitry Andric 
WriteMemoryAtAddress(lldb::addr_t addr,lldb::DataExtractorSP data_sp,Status & error)1317fa27ce4SDimitry Andric lldb::offset_t ScriptedProcessPythonInterface::WriteMemoryAtAddress(
1327fa27ce4SDimitry Andric     lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) {
1337fa27ce4SDimitry Andric   Status py_error;
1347fa27ce4SDimitry Andric   StructuredData::ObjectSP obj =
1357fa27ce4SDimitry Andric       Dispatch("write_memory_at_address", py_error, addr, data_sp, error);
1367fa27ce4SDimitry Andric 
137ac9a064cSDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
138ac9a064cSDimitry Andric                                                     error))
1397fa27ce4SDimitry Andric     return LLDB_INVALID_OFFSET;
1407fa27ce4SDimitry Andric 
1417fa27ce4SDimitry Andric   // If there was an error on the python call, surface it to the user.
1427fa27ce4SDimitry Andric   if (py_error.Fail())
1437fa27ce4SDimitry Andric     error = py_error;
1447fa27ce4SDimitry Andric 
1457fa27ce4SDimitry Andric   return obj->GetUnsignedIntegerValue(LLDB_INVALID_OFFSET);
1467fa27ce4SDimitry Andric }
1477fa27ce4SDimitry Andric 
GetLoadedImages()148145449b1SDimitry Andric StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() {
149145449b1SDimitry Andric   Status error;
150145449b1SDimitry Andric   StructuredData::ArraySP array =
151145449b1SDimitry Andric       Dispatch<StructuredData::ArraySP>("get_loaded_images", error);
152145449b1SDimitry Andric 
153ac9a064cSDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, array,
154ac9a064cSDimitry Andric                                                     error))
1557fa27ce4SDimitry Andric     return {};
156145449b1SDimitry Andric 
157145449b1SDimitry Andric   return array;
158344a3780SDimitry Andric }
159344a3780SDimitry Andric 
GetProcessID()160344a3780SDimitry Andric lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() {
161c0981da4SDimitry Andric   Status error;
162c0981da4SDimitry Andric   StructuredData::ObjectSP obj = Dispatch("get_process_id", error);
163c0981da4SDimitry Andric 
164ac9a064cSDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
165ac9a064cSDimitry Andric                                                     error))
166c0981da4SDimitry Andric     return LLDB_INVALID_PROCESS_ID;
167c0981da4SDimitry Andric 
1687fa27ce4SDimitry Andric   return obj->GetUnsignedIntegerValue(LLDB_INVALID_PROCESS_ID);
169344a3780SDimitry Andric }
170344a3780SDimitry Andric 
IsAlive()171344a3780SDimitry Andric bool ScriptedProcessPythonInterface::IsAlive() {
172c0981da4SDimitry Andric   Status error;
173c0981da4SDimitry Andric   StructuredData::ObjectSP obj = Dispatch("is_alive", error);
174344a3780SDimitry Andric 
175ac9a064cSDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
176ac9a064cSDimitry Andric                                                     error))
177c0981da4SDimitry Andric     return {};
178344a3780SDimitry Andric 
179c0981da4SDimitry Andric   return obj->GetBooleanValue();
180c0981da4SDimitry Andric }
181c0981da4SDimitry Andric 
182e3b55780SDimitry Andric std::optional<std::string>
GetScriptedThreadPluginName()183c0981da4SDimitry Andric ScriptedProcessPythonInterface::GetScriptedThreadPluginName() {
184c0981da4SDimitry Andric   Status error;
185c0981da4SDimitry Andric   StructuredData::ObjectSP obj = Dispatch("get_scripted_thread_plugin", error);
186c0981da4SDimitry Andric 
187ac9a064cSDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
188ac9a064cSDimitry Andric                                                     error))
189c0981da4SDimitry Andric     return {};
190c0981da4SDimitry Andric 
191c0981da4SDimitry Andric   return obj->GetStringValue().str();
192c0981da4SDimitry Andric }
193c0981da4SDimitry Andric 
194c0981da4SDimitry Andric lldb::ScriptedThreadInterfaceSP
CreateScriptedThreadInterface()1956f8fc217SDimitry Andric ScriptedProcessPythonInterface::CreateScriptedThreadInterface() {
196b1c73532SDimitry Andric   return m_interpreter.CreateScriptedThreadInterface();
197344a3780SDimitry Andric }
198344a3780SDimitry Andric 
GetMetadata()199e3b55780SDimitry Andric StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() {
200e3b55780SDimitry Andric   Status error;
201e3b55780SDimitry Andric   StructuredData::DictionarySP dict =
202e3b55780SDimitry Andric       Dispatch<StructuredData::DictionarySP>("get_process_metadata", error);
203e3b55780SDimitry Andric 
204ac9a064cSDimitry Andric   if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict,
205ac9a064cSDimitry Andric                                                     error))
206e3b55780SDimitry Andric     return {};
207e3b55780SDimitry Andric 
208e3b55780SDimitry Andric   return dict;
209e3b55780SDimitry Andric }
210e3b55780SDimitry Andric 
211344a3780SDimitry Andric #endif
212