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