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