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