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 #include "lldb/Host/ThreadLauncher.h"
17 #include "lldb/Interpreter/CommandInterpreter.h"
18 #include "lldb/Interpreter/OptionArgParser.h"
19 #include "lldb/Interpreter/OptionGroupBoolean.h"
20 #include "lldb/Interpreter/ScriptInterpreter.h"
21 #include "lldb/Target/MemoryRegionInfo.h"
22 #include "lldb/Target/RegisterContext.h"
23 
24 #include "lldb/Utility/State.h"
25 
26 #include <mutex>
27 
28 LLDB_PLUGIN_DEFINE(ScriptedProcess)
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 ConstString ScriptedProcess::GetPluginNameStatic() {
34   static ConstString g_name("ScriptedProcess");
35   return g_name;
36 }
37 
38 const char *ScriptedProcess::GetPluginDescriptionStatic() {
39   return "Scripted Process plug-in.";
40 }
41 
42 static constexpr lldb::ScriptLanguage g_supported_script_languages[] = {
43     ScriptLanguage::eScriptLanguagePython,
44 };
45 
46 bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) {
47   llvm::ArrayRef<lldb::ScriptLanguage> supported_languages =
48       llvm::makeArrayRef(g_supported_script_languages);
49 
50   return llvm::is_contained(supported_languages, language);
51 }
52 
53 void ScriptedProcess::CheckInterpreterAndScriptObject() const {
54   lldbassert(m_interpreter && "Invalid Script Interpreter.");
55   lldbassert(m_script_object_sp && "Invalid Script Object.");
56 }
57 
58 lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
59                                                 lldb::ListenerSP listener_sp,
60                                                 const FileSpec *file,
61                                                 bool can_connect) {
62   if (!target_sp ||
63       !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage()))
64     return nullptr;
65 
66   Status error;
67   ScriptedProcess::ScriptedProcessInfo scripted_process_info(
68       target_sp->GetProcessLaunchInfo());
69 
70   auto process_sp = std::make_shared<ScriptedProcess>(
71       target_sp, listener_sp, scripted_process_info, error);
72 
73   if (error.Fail() || !process_sp || !process_sp->m_script_object_sp ||
74       !process_sp->m_script_object_sp->IsValid()) {
75     LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS), "%s",
76               error.AsCString());
77     return nullptr;
78   }
79 
80   return process_sp;
81 }
82 
83 bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
84                                bool plugin_specified_by_name) {
85   return true;
86 }
87 
88 ScriptedProcess::ScriptedProcess(
89     lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
90     const ScriptedProcess::ScriptedProcessInfo &scripted_process_info,
91     Status &error)
92     : Process(target_sp, listener_sp),
93       m_scripted_process_info(scripted_process_info) {
94 
95   if (!target_sp) {
96     error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
97                                    __FUNCTION__, "Invalid target");
98     return;
99   }
100 
101   m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();
102 
103   if (!m_interpreter) {
104     error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
105                                    __FUNCTION__,
106                                    "Debugger has no Script Interpreter");
107     return;
108   }
109 
110   ExecutionContext exe_ctx(target_sp, /*get_process=*/false);
111 
112   StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject(
113       m_scripted_process_info.GetClassName().c_str(), exe_ctx,
114       m_scripted_process_info.GetDictionarySP());
115 
116   if (!object_sp || !object_sp->IsValid()) {
117     error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
118                                    __FUNCTION__,
119                                    "Failed to create valid script object");
120     return;
121   }
122 
123   m_script_object_sp = object_sp;
124 }
125 
126 ScriptedProcess::~ScriptedProcess() {
127   Clear();
128   // We need to call finalize on the process before destroying ourselves to
129   // make sure all of the broadcaster cleanup goes as planned. If we destruct
130   // this class, then Process::~Process() might have problems trying to fully
131   // destroy the broadcaster.
132   Finalize();
133 }
134 
135 void ScriptedProcess::Initialize() {
136   static llvm::once_flag g_once_flag;
137 
138   llvm::call_once(g_once_flag, []() {
139     PluginManager::RegisterPlugin(GetPluginNameStatic(),
140                                   GetPluginDescriptionStatic(), CreateInstance);
141   });
142 }
143 
144 void ScriptedProcess::Terminate() {
145   PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
146 }
147 
148 ConstString ScriptedProcess::GetPluginName() { return GetPluginNameStatic(); }
149 
150 Status ScriptedProcess::DoLoadCore() {
151   ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
152 
153   return DoLaunch(nullptr, launch_info);
154 }
155 
156 Status ScriptedProcess::DoLaunch(Module *exe_module,
157                                  ProcessLaunchInfo &launch_info) {
158   CheckInterpreterAndScriptObject();
159 
160   /* FIXME: This doesn't reflect how lldb actually launches a process.
161            In reality, it attaches to debugserver, then resume the process. */
162   Status error = GetInterface().Launch();
163   SetPrivateState(eStateRunning);
164 
165   if (error.Fail())
166     return error;
167 
168   // TODO: Fetch next state from stopped event queue then send stop event
169   //  const StateType state = SetThreadStopInfo(response);
170   //  if (state != eStateInvalid) {
171   //    SetPrivateState(state);
172 
173   SetPrivateState(eStateStopped);
174 
175   UpdateThreadListIfNeeded();
176   GetThreadList();
177 
178   return {};
179 }
180 
181 void ScriptedProcess::DidLaunch() {
182   CheckInterpreterAndScriptObject();
183   m_pid = GetInterface().GetProcessID();
184 }
185 
186 Status ScriptedProcess::DoResume() {
187   CheckInterpreterAndScriptObject();
188 
189   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
190   // FIXME: Fetch data from thread.
191   const StateType thread_resume_state = eStateRunning;
192   LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__,
193             StateAsCString(thread_resume_state));
194 
195   bool resume = (thread_resume_state == eStateRunning);
196   assert(thread_resume_state == eStateRunning && "invalid thread resume state");
197 
198   Status error;
199   if (resume) {
200     LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__);
201 
202     SetPrivateState(eStateRunning);
203     SetPrivateState(eStateStopped);
204     error = GetInterface().Resume();
205   }
206 
207   return error;
208 }
209 
210 Status ScriptedProcess::DoStop() {
211   CheckInterpreterAndScriptObject();
212 
213   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
214 
215   if (GetInterface().ShouldStop()) {
216     SetPrivateState(eStateStopped);
217     LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__);
218     return {};
219   }
220 
221   LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__);
222   return GetInterface().Stop();
223 }
224 
225 Status ScriptedProcess::DoDestroy() { return Status(); }
226 
227 bool ScriptedProcess::IsAlive() {
228   if (m_interpreter && m_script_object_sp)
229     return GetInterface().IsAlive();
230   return false;
231 }
232 
233 size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
234                                      Status &error) {
235   if (!m_interpreter)
236     return GetInterface().ErrorWithMessage<size_t>(LLVM_PRETTY_FUNCTION,
237                                                    "No interpreter.", error);
238 
239   lldb::DataExtractorSP data_extractor_sp =
240       GetInterface().ReadMemoryAtAddress(addr, size, error);
241 
242   if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
243     return 0;
244 
245   offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
246       0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
247 
248   if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
249     return GetInterface().ErrorWithMessage<size_t>(
250         LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error);
251 
252   return size;
253 }
254 
255 ArchSpec ScriptedProcess::GetArchitecture() {
256   return GetTarget().GetArchitecture();
257 }
258 
259 Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
260                                             MemoryRegionInfo &region) {
261   CheckInterpreterAndScriptObject();
262 
263   Status error;
264   if (auto region_or_err =
265           GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
266     region = *region_or_err;
267 
268   return error;
269 }
270 
271 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
272   CheckInterpreterAndScriptObject();
273 
274   Status error;
275   lldb::addr_t address = 0;
276 
277   while (auto region_or_err =
278              GetInterface().GetMemoryRegionContainingAddress(address, error)) {
279     if (error.Fail())
280       break;
281 
282     MemoryRegionInfo &mem_region = *region_or_err;
283     auto range = mem_region.GetRange();
284     address += range.GetRangeBase() + range.GetByteSize();
285     region_list.push_back(mem_region);
286   }
287 
288   return error;
289 }
290 
291 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
292 
293 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
294                                          ThreadList &new_thread_list) {
295   // TODO: Implement
296   // This is supposed to get the current set of threads, if any of them are in
297   // old_thread_list then they get copied to new_thread_list, and then any
298   // actually new threads will get added to new_thread_list.
299 
300   CheckInterpreterAndScriptObject();
301 
302   Status error;
303   ScriptLanguage language = m_interpreter->GetLanguage();
304 
305   if (language != eScriptLanguagePython)
306     return GetInterface().ErrorWithMessage<bool>(
307         LLVM_PRETTY_FUNCTION,
308         llvm::Twine("ScriptInterpreter language (" +
309                     llvm::Twine(m_interpreter->LanguageToString(language)) +
310                     llvm::Twine(") not supported."))
311             .str(),
312         error);
313 
314   lldb::ThreadSP thread_sp;
315   thread_sp = std::make_shared<ScriptedThread>(*this, error);
316 
317   if (!thread_sp || error.Fail())
318     return GetInterface().ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
319                                                  error.AsCString(), error);
320 
321   new_thread_list.AddThread(thread_sp);
322 
323   return new_thread_list.GetSize(false) > 0;
324 }
325 
326 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
327   info.Clear();
328   info.SetProcessID(GetID());
329   info.SetArchitecture(GetArchitecture());
330   lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
331   if (module_sp) {
332     const bool add_exe_file_as_first_arg = false;
333     info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
334                            add_exe_file_as_first_arg);
335   }
336   return true;
337 }
338 
339 ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
340   return m_interpreter->GetScriptedProcessInterface();
341 }
342