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