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 
ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl & interpreter)32 ScriptedProcessPythonInterface::ScriptedProcessPythonInterface(
33     ScriptInterpreterPythonImpl &interpreter)
34     : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {}
35 
36 llvm::Expected<StructuredData::GenericSP>
CreatePluginObject(llvm::StringRef class_name,ExecutionContext & exe_ctx,StructuredData::DictionarySP args_sp,StructuredData::Generic * script_obj)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 
GetCapabilities()47 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() {
48   Status error;
49   StructuredData::DictionarySP dict =
50       Dispatch<StructuredData::DictionarySP>("get_capabilities", error);
51 
52   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error))
53     return {};
54 
55   return dict;
56 }
57 
58 Status
Attach(const ProcessAttachInfo & attach_info)59 ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) {
60   lldb::ProcessAttachInfoSP attach_info_sp =
61       std::make_shared<ProcessAttachInfo>(attach_info);
62   return GetStatusFromMethod("attach", attach_info_sp);
63 }
64 
Launch()65 Status ScriptedProcessPythonInterface::Launch() {
66   return GetStatusFromMethod("launch");
67 }
68 
Resume()69 Status ScriptedProcessPythonInterface::Resume() {
70   // When calling ScriptedProcess.Resume from lldb we should always stop.
71   return GetStatusFromMethod("resume", /*should_stop=*/true);
72 }
73 
74 std::optional<MemoryRegionInfo>
GetMemoryRegionContainingAddress(lldb::addr_t address,Status & error)75 ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
76     lldb::addr_t address, Status &error) {
77   auto mem_region = Dispatch<std::optional<MemoryRegionInfo>>(
78       "get_memory_region_containing_address", error, address);
79 
80   if (error.Fail()) {
81     return ErrorWithMessage<MemoryRegionInfo>(LLVM_PRETTY_FUNCTION,
82                                               error.AsCString(), error);
83   }
84 
85   return mem_region;
86 }
87 
GetThreadsInfo()88 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() {
89   Status error;
90   StructuredData::DictionarySP dict =
91       Dispatch<StructuredData::DictionarySP>("get_threads_info", error);
92 
93   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error))
94     return {};
95 
96   return dict;
97 }
98 
CreateBreakpoint(lldb::addr_t addr,Status & error)99 bool ScriptedProcessPythonInterface::CreateBreakpoint(lldb::addr_t addr,
100                                                       Status &error) {
101   Status py_error;
102   StructuredData::ObjectSP obj =
103       Dispatch("create_breakpoint", py_error, addr, 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 
ReadMemoryAtAddress(lldb::addr_t address,size_t size,Status & error)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       "read_memory_at_address", py_error, address, size, 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 
WriteMemoryAtAddress(lldb::addr_t addr,lldb::DataExtractorSP data_sp,Status & error)128 lldb::offset_t ScriptedProcessPythonInterface::WriteMemoryAtAddress(
129     lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) {
130   Status py_error;
131   StructuredData::ObjectSP obj =
132       Dispatch("write_memory_at_address", py_error, addr, data_sp, 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 
GetLoadedImages()144 StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() {
145   Status error;
146   StructuredData::ArraySP array =
147       Dispatch<StructuredData::ArraySP>("get_loaded_images", error);
148 
149   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, array, error))
150     return {};
151 
152   return array;
153 }
154 
GetProcessID()155 lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() {
156   Status error;
157   StructuredData::ObjectSP obj = Dispatch("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 
IsAlive()165 bool ScriptedProcessPythonInterface::IsAlive() {
166   Status error;
167   StructuredData::ObjectSP obj = Dispatch("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>
GetScriptedThreadPluginName()176 ScriptedProcessPythonInterface::GetScriptedThreadPluginName() {
177   Status error;
178   StructuredData::ObjectSP obj = Dispatch("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
CreateScriptedThreadInterface()187 ScriptedProcessPythonInterface::CreateScriptedThreadInterface() {
188   return m_interpreter.CreateScriptedThreadInterface();
189 }
190 
GetMetadata()191 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() {
192   Status error;
193   StructuredData::DictionarySP dict =
194       Dispatch<StructuredData::DictionarySP>("get_process_metadata", error);
195 
196   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error))
197     return {};
198 
199   return dict;
200 }
201 
202 #endif
203