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