xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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