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 Status ScriptedProcess::DoLoadCore() {
149   ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
150 
151   return DoLaunch(nullptr, launch_info);
152 }
153 
154 Status ScriptedProcess::DoLaunch(Module *exe_module,
155                                  ProcessLaunchInfo &launch_info) {
156   CheckInterpreterAndScriptObject();
157 
158   /* FIXME: This doesn't reflect how lldb actually launches a process.
159            In reality, it attaches to debugserver, then resume the process. */
160   Status error = GetInterface().Launch();
161   SetPrivateState(eStateRunning);
162 
163   if (error.Fail())
164     return error;
165 
166   // TODO: Fetch next state from stopped event queue then send stop event
167   //  const StateType state = SetThreadStopInfo(response);
168   //  if (state != eStateInvalid) {
169   //    SetPrivateState(state);
170 
171   SetPrivateState(eStateStopped);
172 
173   UpdateThreadListIfNeeded();
174   GetThreadList();
175 
176   return {};
177 }
178 
179 void ScriptedProcess::DidLaunch() {
180   CheckInterpreterAndScriptObject();
181   m_pid = GetInterface().GetProcessID();
182 }
183 
184 Status ScriptedProcess::DoResume() {
185   CheckInterpreterAndScriptObject();
186 
187   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
188   // FIXME: Fetch data from thread.
189   const StateType thread_resume_state = eStateRunning;
190   LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__,
191             StateAsCString(thread_resume_state));
192 
193   bool resume = (thread_resume_state == eStateRunning);
194   assert(thread_resume_state == eStateRunning && "invalid thread resume state");
195 
196   Status error;
197   if (resume) {
198     LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__);
199 
200     SetPrivateState(eStateRunning);
201     SetPrivateState(eStateStopped);
202     error = GetInterface().Resume();
203   }
204 
205   return error;
206 }
207 
208 Status ScriptedProcess::DoStop() {
209   CheckInterpreterAndScriptObject();
210 
211   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
212 
213   if (GetInterface().ShouldStop()) {
214     SetPrivateState(eStateStopped);
215     LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__);
216     return {};
217   }
218 
219   LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__);
220   return GetInterface().Stop();
221 }
222 
223 Status ScriptedProcess::DoDestroy() { return Status(); }
224 
225 bool ScriptedProcess::IsAlive() {
226   if (m_interpreter && m_script_object_sp)
227     return GetInterface().IsAlive();
228   return false;
229 }
230 
231 size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
232                                      Status &error) {
233   if (!m_interpreter)
234     return GetInterface().ErrorWithMessage<size_t>(LLVM_PRETTY_FUNCTION,
235                                                    "No interpreter.", error);
236 
237   lldb::DataExtractorSP data_extractor_sp =
238       GetInterface().ReadMemoryAtAddress(addr, size, error);
239 
240   if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
241     return 0;
242 
243   offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
244       0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
245 
246   if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
247     return GetInterface().ErrorWithMessage<size_t>(
248         LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error);
249 
250   return size;
251 }
252 
253 ArchSpec ScriptedProcess::GetArchitecture() {
254   return GetTarget().GetArchitecture();
255 }
256 
257 Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
258                                             MemoryRegionInfo &region) {
259   CheckInterpreterAndScriptObject();
260 
261   Status error;
262   if (auto region_or_err =
263           GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
264     region = *region_or_err;
265 
266   return error;
267 }
268 
269 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
270   CheckInterpreterAndScriptObject();
271 
272   Status error;
273   lldb::addr_t address = 0;
274 
275   while (auto region_or_err =
276              GetInterface().GetMemoryRegionContainingAddress(address, error)) {
277     if (error.Fail())
278       break;
279 
280     MemoryRegionInfo &mem_region = *region_or_err;
281     auto range = mem_region.GetRange();
282     address += range.GetRangeBase() + range.GetByteSize();
283     region_list.push_back(mem_region);
284   }
285 
286   return error;
287 }
288 
289 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
290 
291 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
292                                          ThreadList &new_thread_list) {
293   // TODO: Implement
294   // This is supposed to get the current set of threads, if any of them are in
295   // old_thread_list then they get copied to new_thread_list, and then any
296   // actually new threads will get added to new_thread_list.
297 
298   CheckInterpreterAndScriptObject();
299 
300   Status error;
301   ScriptLanguage language = m_interpreter->GetLanguage();
302 
303   if (language != eScriptLanguagePython)
304     return GetInterface().ErrorWithMessage<bool>(
305         LLVM_PRETTY_FUNCTION,
306         llvm::Twine("ScriptInterpreter language (" +
307                     llvm::Twine(m_interpreter->LanguageToString(language)) +
308                     llvm::Twine(") not supported."))
309             .str(),
310         error);
311 
312   lldb::ThreadSP thread_sp;
313   thread_sp = std::make_shared<ScriptedThread>(*this, error);
314 
315   if (!thread_sp || error.Fail())
316     return GetInterface().ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
317                                                  error.AsCString(), error);
318 
319   new_thread_list.AddThread(thread_sp);
320 
321   return new_thread_list.GetSize(false) > 0;
322 }
323 
324 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
325   info.Clear();
326   info.SetProcessID(GetID());
327   info.SetArchitecture(GetArchitecture());
328   lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
329   if (module_sp) {
330     const bool add_exe_file_as_first_arg = false;
331     info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
332                            add_exe_file_as_first_arg);
333   }
334   return true;
335 }
336 
337 ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
338   return m_interpreter->GetScriptedProcessInterface();
339 }
340