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