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