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(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   if (!ret_val)
51     return {};
52 
53   m_object_instance_sp =
54       StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val)));
55 
56   return m_object_instance_sp;
57 }
58 
59 Status ScriptedProcessPythonInterface::Launch() {
60   return GetStatusFromMethod("launch");
61 }
62 
63 Status ScriptedProcessPythonInterface::Resume() {
64   return GetStatusFromMethod("resume");
65 }
66 
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 
77 Status ScriptedProcessPythonInterface::Stop() {
78   return GetStatusFromMethod("stop");
79 }
80 
81 llvm::Optional<MemoryRegionInfo>
82 ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
83     lldb::addr_t address, Status &error) {
84   auto mem_region = Dispatch<llvm::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 
95 StructuredData::DictionarySP
96 ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) {
97   Status error;
98   StructuredData::ObjectSP obj = Dispatch("get_thread_with_id", error, tid);
99 
100   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
101     return {};
102 
103   StructuredData::DictionarySP dict{obj->GetAsDictionary()};
104 
105   return dict;
106 }
107 
108 StructuredData::DictionarySP
109 ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) {
110   // TODO: Implement
111   return {};
112 }
113 
114 lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress(
115     lldb::addr_t address, size_t size, Status &error) {
116   return Dispatch<lldb::DataExtractorSP>("read_memory_at_address", error,
117                                          address, size);
118 }
119 
120 StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() {
121   // TODO: Implement
122   return {};
123 }
124 
125 lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() {
126   Status error;
127   StructuredData::ObjectSP obj = Dispatch("get_process_id", error);
128 
129   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
130     return LLDB_INVALID_PROCESS_ID;
131 
132   return obj->GetIntegerValue(LLDB_INVALID_PROCESS_ID);
133 }
134 
135 bool ScriptedProcessPythonInterface::IsAlive() {
136   Status error;
137   StructuredData::ObjectSP obj = Dispatch("is_alive", error);
138 
139   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
140     return {};
141 
142   return obj->GetBooleanValue();
143 }
144 
145 llvm::Optional<std::string>
146 ScriptedProcessPythonInterface::GetScriptedThreadPluginName() {
147   Status error;
148   StructuredData::ObjectSP obj = Dispatch("get_scripted_thread_plugin", error);
149 
150   if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error))
151     return {};
152 
153   return obj->GetStringValue().str();
154 }
155 
156 lldb::ScriptedThreadInterfaceSP
157 ScriptedProcessPythonInterface::GetScriptedThreadInterface() {
158   if (!m_scripted_thread_interface_sp)
159     m_scripted_thread_interface_sp =
160         std::make_shared<ScriptedThreadPythonInterface>(m_interpreter);
161 
162   return m_scripted_thread_interface_sp;
163 }
164 
165 #endif
166