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 #include "lldb/Utility/Log.h"
11 #include "lldb/Utility/Status.h"
12 #include "lldb/lldb-enumerations.h"
13
14 #if LLDB_ENABLE_PYTHON
15
16 // LLDB Python header must be included first
17 #include "lldb-python.h"
18
19 #include "SWIGPythonBridge.h"
20 #include "ScriptInterpreterPythonImpl.h"
21 #include "ScriptedProcessPythonInterface.h"
22 #include "ScriptedThreadPythonInterface.h"
23 #include <optional>
24
25 using namespace lldb;
26 using namespace lldb_private;
27 using namespace lldb_private::python;
28 using Locker = ScriptInterpreterPythonImpl::Locker;
29
ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl & interpreter)30 ScriptedProcessPythonInterface::ScriptedProcessPythonInterface(
31 ScriptInterpreterPythonImpl &interpreter)
32 : ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {}
33
CreatePluginObject(llvm::StringRef class_name,ExecutionContext & exe_ctx,StructuredData::DictionarySP args_sp,StructuredData::Generic * script_obj)34 StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject(
35 llvm::StringRef class_name, ExecutionContext &exe_ctx,
36 StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) {
37 if (class_name.empty())
38 return {};
39
40 StructuredDataImpl args_impl(args_sp);
41 std::string error_string;
42
43 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
44 Locker::FreeLock);
45
46 lldb::ExecutionContextRefSP exe_ctx_ref_sp =
47 std::make_shared<ExecutionContextRef>(exe_ctx);
48
49 PythonObject ret_val = LLDBSwigPythonCreateScriptedObject(
50 class_name.str().c_str(), m_interpreter.GetDictionaryName(),
51 exe_ctx_ref_sp, args_impl, error_string);
52
53 m_object_instance_sp =
54 StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val)));
55
56 return m_object_instance_sp;
57 }
58
Launch()59 Status ScriptedProcessPythonInterface::Launch() {
60 return GetStatusFromMethod("launch");
61 }
62
Resume()63 Status ScriptedProcessPythonInterface::Resume() {
64 return GetStatusFromMethod("resume");
65 }
66
ShouldStop()67 bool ScriptedProcessPythonInterface::ShouldStop() {
68 Status error;
69 StructuredData::ObjectSP obj = Dispatch("is_alive", error);
70
71 if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
72 return {};
73
74 return obj->GetBooleanValue();
75 }
76
Stop()77 Status ScriptedProcessPythonInterface::Stop() {
78 return GetStatusFromMethod("stop");
79 }
80
81 std::optional<MemoryRegionInfo>
GetMemoryRegionContainingAddress(lldb::addr_t address,Status & error)82 ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
83 lldb::addr_t address, Status &error) {
84 auto mem_region = Dispatch<std::optional<MemoryRegionInfo>>(
85 "get_memory_region_containing_address", error, address);
86
87 if (error.Fail()) {
88 return ErrorWithMessage<MemoryRegionInfo>(LLVM_PRETTY_FUNCTION,
89 error.AsCString(), error);
90 }
91
92 return mem_region;
93 }
94
GetThreadsInfo()95 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() {
96 Status error;
97 StructuredData::DictionarySP dict =
98 Dispatch<StructuredData::DictionarySP>("get_threads_info", error);
99
100 if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error))
101 return {};
102
103 return dict;
104 }
105
106 StructuredData::DictionarySP
GetThreadWithID(lldb::tid_t tid)107 ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) {
108 Status error;
109 StructuredData::ObjectSP obj = Dispatch("get_thread_with_id", error, tid);
110
111 if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
112 return {};
113
114 StructuredData::DictionarySP dict{obj->GetAsDictionary()};
115
116 return dict;
117 }
118
119 StructuredData::DictionarySP
GetRegistersForThread(lldb::tid_t tid)120 ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) {
121 // TODO: Implement
122 return {};
123 }
124
ReadMemoryAtAddress(lldb::addr_t address,size_t size,Status & error)125 lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress(
126 lldb::addr_t address, size_t size, Status &error) {
127 Status py_error;
128 lldb::DataExtractorSP data_sp = Dispatch<lldb::DataExtractorSP>(
129 "read_memory_at_address", py_error, address, size, error);
130
131 // If there was an error on the python call, surface it to the user.
132 if (py_error.Fail())
133 error = py_error;
134
135 return data_sp;
136 }
137
GetLoadedImages()138 StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() {
139 Status error;
140 StructuredData::ArraySP array =
141 Dispatch<StructuredData::ArraySP>("get_loaded_images", error);
142
143 if (!array || !array->IsValid() || error.Fail()) {
144 return ScriptedInterface::ErrorWithMessage<StructuredData::ArraySP>(
145 LLVM_PRETTY_FUNCTION,
146 llvm::Twine("Null or invalid object (" +
147 llvm::Twine(error.AsCString()) + llvm::Twine(")."))
148 .str(),
149 error);
150 }
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->GetIntegerValue(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 std::make_shared<ScriptedThreadPythonInterface>(m_interpreter);
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