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