1 //===-- ScriptedProcess.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 "ScriptedProcess.h"
10 
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/PluginManager.h"
14 
15 #include "lldb/Host/OptionParser.h"
16 
17 #include "lldb/Interpreter/OptionArgParser.h"
18 #include "lldb/Interpreter/OptionGroupBoolean.h"
19 #include "lldb/Interpreter/ScriptInterpreter.h"
20 #include "lldb/Target/MemoryRegionInfo.h"
21 
22 LLDB_PLUGIN_DEFINE(ScriptedProcess)
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 ConstString ScriptedProcess::GetPluginNameStatic() {
28   static ConstString g_name("ScriptedProcess");
29   return g_name;
30 }
31 
32 const char *ScriptedProcess::GetPluginDescriptionStatic() {
33   return "Scripted Process plug-in.";
34 }
35 
36 lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
37                                                 lldb::ListenerSP listener_sp,
38                                                 const FileSpec *file,
39                                                 bool can_connect) {
40   ScriptedProcess::LaunchInfo launch_info(target_sp->GetProcessLaunchInfo());
41 
42   auto process_sp =
43       std::make_shared<ScriptedProcess>(target_sp, listener_sp, launch_info);
44 
45   if (!process_sp || !process_sp->m_script_object_sp ||
46       !process_sp->m_script_object_sp->IsValid())
47     return nullptr;
48 
49   return process_sp;
50 }
51 
52 bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
53                                bool plugin_specified_by_name) {
54   return true;
55 }
56 
57 ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp,
58                                  lldb::ListenerSP listener_sp,
59                                  const ScriptedProcess::LaunchInfo &launch_info)
60     : Process(target_sp, listener_sp), m_launch_info(launch_info) {
61   if (!target_sp)
62     return;
63 
64   m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();
65 
66   if (!m_interpreter)
67     return;
68 
69   StructuredData::ObjectSP object_sp = GetInterface().CreatePluginObject(
70       m_launch_info.GetClassName().c_str(), target_sp,
71       m_launch_info.GetDictionarySP());
72 
73   if (object_sp && object_sp->IsValid())
74     m_script_object_sp = object_sp;
75 }
76 
77 ScriptedProcess::~ScriptedProcess() {
78   Clear();
79   // We need to call finalize on the process before destroying ourselves to
80   // make sure all of the broadcaster cleanup goes as planned. If we destruct
81   // this class, then Process::~Process() might have problems trying to fully
82   // destroy the broadcaster.
83   Finalize();
84 }
85 
86 void ScriptedProcess::Initialize() {
87   static llvm::once_flag g_once_flag;
88 
89   llvm::call_once(g_once_flag, []() {
90     PluginManager::RegisterPlugin(GetPluginNameStatic(),
91                                   GetPluginDescriptionStatic(), CreateInstance);
92   });
93 }
94 
95 void ScriptedProcess::Terminate() {
96   PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
97 }
98 
99 ConstString ScriptedProcess::GetPluginName() { return GetPluginNameStatic(); }
100 
101 uint32_t ScriptedProcess::GetPluginVersion() { return 1; }
102 
103 Status ScriptedProcess::DoLoadCore() {
104   ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
105 
106   return DoLaunch(nullptr, launch_info);
107 }
108 
109 Status ScriptedProcess::DoLaunch(Module *exe_module,
110                                  ProcessLaunchInfo &launch_info) {
111   if (!m_interpreter)
112     return Status("No interpreter.");
113 
114   if (!m_script_object_sp)
115     return Status("No python object.");
116 
117   Status status = GetInterface().Launch();
118 
119   if (status.Success()) {
120     SetPrivateState(eStateRunning);
121     SetPrivateState(eStateStopped);
122   }
123 
124   return status;
125 }
126 
127 void ScriptedProcess::DidLaunch() {
128   if (m_interpreter)
129     m_pid = GetInterface().GetProcessID();
130 }
131 
132 Status ScriptedProcess::DoResume() {
133   if (!m_interpreter)
134     return Status("No interpreter.");
135 
136   if (!m_script_object_sp)
137     return Status("No python object.");
138 
139   Status status = GetInterface().Resume();
140 
141   if (status.Success()) {
142     SetPrivateState(eStateRunning);
143     SetPrivateState(eStateStopped);
144   }
145 
146   return status;
147 }
148 
149 Status ScriptedProcess::DoDestroy() { return Status(); }
150 
151 bool ScriptedProcess::IsAlive() {
152   if (!m_interpreter)
153     return false;
154 
155   return GetInterface().IsAlive();
156 }
157 
158 size_t ScriptedProcess::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
159                                    Status &error) {
160   return DoReadMemory(addr, buf, size, error);
161 }
162 
163 size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
164                                      Status &error) {
165 
166   auto error_with_message = [&error](llvm::StringRef message) {
167     error.SetErrorString(message);
168     return LLDB_INVALID_ADDRESS;
169   };
170 
171   if (!m_interpreter)
172     return error_with_message("No interpreter.");
173 
174   lldb::DataExtractorSP data_extractor_sp =
175       GetInterface().ReadMemoryAtAddress(addr, size, error);
176 
177   if (!data_extractor_sp || error.Fail())
178     return LLDB_INVALID_ADDRESS;
179 
180   if (data_extractor_sp->GetByteSize() != size)
181     return error_with_message("Failed to read requested memory size.");
182 
183   offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
184       0, size, buf, size, GetByteOrder());
185 
186   if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
187     return error_with_message("Failed to copy read memory to buffer.");
188 
189   return size;
190 }
191 
192 ArchSpec ScriptedProcess::GetArchitecture() {
193   return GetTarget().GetArchitecture();
194 }
195 
196 Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
197                                             MemoryRegionInfo &region) {
198   return Status();
199 }
200 
201 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
202   Status error;
203 
204   if (!m_interpreter) {
205     error.SetErrorString("No interpreter.");
206     return error;
207   }
208 
209   lldb::addr_t address = 0;
210   lldb::MemoryRegionInfoSP mem_region_sp = nullptr;
211 
212   while ((mem_region_sp =
213               GetInterface().GetMemoryRegionContainingAddress(address))) {
214     auto range = mem_region_sp->GetRange();
215     address += range.GetRangeBase() + range.GetByteSize();
216     region_list.push_back(*mem_region_sp.get());
217   }
218 
219   return error;
220 }
221 
222 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
223 
224 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
225                                          ThreadList &new_thread_list) {
226   return new_thread_list.GetSize(false) > 0;
227 }
228 
229 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
230   info.Clear();
231   info.SetProcessID(GetID());
232   info.SetArchitecture(GetArchitecture());
233   lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
234   if (module_sp) {
235     const bool add_exe_file_as_first_arg = false;
236     info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
237                            add_exe_file_as_first_arg);
238   }
239   return true;
240 }
241 
242 ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
243   return m_interpreter->GetScriptedProcessInterface();
244 }
245