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/Queue.h"
23 #include "lldb/Target/RegisterContext.h"
24 #include "lldb/Utility/LLDBLog.h"
25 #include "lldb/Utility/ScriptedMetadata.h"
26 #include "lldb/Utility/State.h"
27 
28 #include <mutex>
29 
30 LLDB_PLUGIN_DEFINE(ScriptedProcess)
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() {
36   return "Scripted Process plug-in.";
37 }
38 
39 static constexpr lldb::ScriptLanguage g_supported_script_languages[] = {
40     ScriptLanguage::eScriptLanguagePython,
41 };
42 
43 bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) {
44   llvm::ArrayRef<lldb::ScriptLanguage> supported_languages =
45       llvm::ArrayRef(g_supported_script_languages);
46 
47   return llvm::is_contained(supported_languages, language);
48 }
49 
50 lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
51                                                 lldb::ListenerSP listener_sp,
52                                                 const FileSpec *file,
53                                                 bool can_connect) {
54   if (!target_sp ||
55       !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage()))
56     return nullptr;
57 
58   ScriptedMetadata scripted_metadata(target_sp->GetProcessLaunchInfo());
59 
60   Status error;
61   auto process_sp = std::shared_ptr<ScriptedProcess>(
62       new ScriptedProcess(target_sp, listener_sp, scripted_metadata, error));
63 
64   if (error.Fail() || !process_sp || !process_sp->m_interface_up) {
65     LLDB_LOGF(GetLog(LLDBLog::Process), "%s", error.AsCString());
66     return nullptr;
67   }
68 
69   return process_sp;
70 }
71 
72 bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
73                                bool plugin_specified_by_name) {
74   return true;
75 }
76 
77 ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp,
78                                  lldb::ListenerSP listener_sp,
79                                  const ScriptedMetadata &scripted_metadata,
80                                  Status &error)
81     : Process(target_sp, listener_sp), m_scripted_metadata(scripted_metadata) {
82 
83   if (!target_sp) {
84     error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
85                                    __FUNCTION__, "Invalid target");
86     return;
87   }
88 
89   ScriptInterpreter *interpreter =
90       target_sp->GetDebugger().GetScriptInterpreter();
91 
92   if (!interpreter) {
93     error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
94                                    __FUNCTION__,
95                                    "Debugger has no Script Interpreter");
96     return;
97   }
98 
99   // Create process instance interface
100   m_interface_up = interpreter->CreateScriptedProcessInterface();
101   if (!m_interface_up) {
102     error.SetErrorStringWithFormat(
103         "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__,
104         "Script interpreter couldn't create Scripted Process Interface");
105     return;
106   }
107 
108   ExecutionContext exe_ctx(target_sp, /*get_process=*/false);
109 
110   // Create process script object
111   StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject(
112       m_scripted_metadata.GetClassName(), exe_ctx,
113       m_scripted_metadata.GetArgsSP());
114 
115   if (!object_sp || !object_sp->IsValid()) {
116     error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
117                                    __FUNCTION__,
118                                    "Failed to create valid script object");
119     return;
120   }
121 }
122 
123 ScriptedProcess::~ScriptedProcess() {
124   Clear();
125   // We need to call finalize on the process before destroying ourselves to
126   // make sure all of the broadcaster cleanup goes as planned. If we destruct
127   // this class, then Process::~Process() might have problems trying to fully
128   // destroy the broadcaster.
129   Finalize();
130 }
131 
132 void ScriptedProcess::Initialize() {
133   static llvm::once_flag g_once_flag;
134 
135   llvm::call_once(g_once_flag, []() {
136     PluginManager::RegisterPlugin(GetPluginNameStatic(),
137                                   GetPluginDescriptionStatic(), CreateInstance);
138   });
139 }
140 
141 void ScriptedProcess::Terminate() {
142   PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
143 }
144 
145 Status ScriptedProcess::DoLoadCore() {
146   ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
147 
148   return DoLaunch(nullptr, launch_info);
149 }
150 
151 Status ScriptedProcess::DoLaunch(Module *exe_module,
152                                  ProcessLaunchInfo &launch_info) {
153   LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s launching process", __FUNCTION__);
154 
155   /* MARK: This doesn't reflect how lldb actually launches a process.
156            In reality, it attaches to debugserver, then resume the process.
157            That's not true in all cases.  If debugserver is remote, lldb
158            asks debugserver to launch the process for it. */
159   Status error = GetInterface().Launch();
160   SetPrivateState(eStateStopped);
161   return error;
162 }
163 
164 void ScriptedProcess::DidLaunch() { m_pid = GetInterface().GetProcessID(); }
165 
166 void ScriptedProcess::DidResume() {
167   // Update the PID again, in case the user provided a placeholder pid at launch
168   m_pid = GetInterface().GetProcessID();
169 }
170 
171 Status ScriptedProcess::DoResume() {
172   LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s resuming process", __FUNCTION__);
173 
174   return GetInterface().Resume();
175 }
176 
177 Status ScriptedProcess::DoAttach(const ProcessAttachInfo &attach_info) {
178   Status error = GetInterface().Attach(attach_info);
179   SetPrivateState(eStateRunning);
180   SetPrivateState(eStateStopped);
181   if (error.Fail())
182     return error;
183   // NOTE: We need to set the PID before finishing to attach otherwise we will
184   // hit an assert when calling the attach completion handler.
185   DidLaunch();
186 
187   return {};
188 }
189 
190 Status
191 ScriptedProcess::DoAttachToProcessWithID(lldb::pid_t pid,
192                                          const ProcessAttachInfo &attach_info) {
193   return DoAttach(attach_info);
194 }
195 
196 Status ScriptedProcess::DoAttachToProcessWithName(
197     const char *process_name, const ProcessAttachInfo &attach_info) {
198   return DoAttach(attach_info);
199 }
200 
201 void ScriptedProcess::DidAttach(ArchSpec &process_arch) {
202   process_arch = GetArchitecture();
203 }
204 
205 Status ScriptedProcess::DoDestroy() { return Status(); }
206 
207 bool ScriptedProcess::IsAlive() { return GetInterface().IsAlive(); }
208 
209 size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
210                                      Status &error) {
211   lldb::DataExtractorSP data_extractor_sp =
212       GetInterface().ReadMemoryAtAddress(addr, size, error);
213 
214   if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
215     return 0;
216 
217   offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
218       0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
219 
220   if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
221     return ScriptedInterface::ErrorWithMessage<size_t>(
222         LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error);
223 
224   // FIXME: We should use the diagnostic system to report a warning if the
225   // `bytes_copied` is different from `size`.
226 
227   return bytes_copied;
228 }
229 
230 size_t ScriptedProcess::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
231                                       size_t size, Status &error) {
232   lldb::DataExtractorSP data_extractor_sp = std::make_shared<DataExtractor>(
233       buf, size, GetByteOrder(), GetAddressByteSize());
234 
235   if (!data_extractor_sp || !data_extractor_sp->GetByteSize())
236     return 0;
237 
238   lldb::offset_t bytes_written =
239       GetInterface().WriteMemoryAtAddress(vm_addr, data_extractor_sp, error);
240 
241   if (!bytes_written || bytes_written == LLDB_INVALID_OFFSET)
242     return ScriptedInterface::ErrorWithMessage<size_t>(
243         LLVM_PRETTY_FUNCTION, "Failed to copy write buffer to memory.", error);
244 
245   // FIXME: We should use the diagnostic system to report a warning if the
246   // `bytes_written` is different from `size`.
247 
248   return bytes_written;
249 }
250 
251 Status ScriptedProcess::EnableBreakpointSite(BreakpointSite *bp_site) {
252   assert(bp_site != nullptr);
253 
254   if (bp_site->IsEnabled()) {
255     return {};
256   }
257 
258   if (bp_site->HardwareRequired()) {
259     return Status("Scripted Processes don't support hardware breakpoints");
260   }
261 
262   Status error;
263   GetInterface().CreateBreakpoint(bp_site->GetLoadAddress(), error);
264 
265   return error;
266 }
267 
268 ArchSpec ScriptedProcess::GetArchitecture() {
269   return GetTarget().GetArchitecture();
270 }
271 
272 Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
273                                               MemoryRegionInfo &region) {
274   Status error;
275   if (auto region_or_err =
276           GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
277     region = *region_or_err;
278 
279   return error;
280 }
281 
282 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
283   Status error;
284   lldb::addr_t address = 0;
285 
286   while (auto region_or_err =
287              GetInterface().GetMemoryRegionContainingAddress(address, error)) {
288     if (error.Fail())
289       break;
290 
291     MemoryRegionInfo &mem_region = *region_or_err;
292     auto range = mem_region.GetRange();
293     address += range.GetRangeBase() + range.GetByteSize();
294     region_list.push_back(mem_region);
295   }
296 
297   return error;
298 }
299 
300 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
301 
302 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
303                                          ThreadList &new_thread_list) {
304   // TODO: Implement
305   // This is supposed to get the current set of threads, if any of them are in
306   // old_thread_list then they get copied to new_thread_list, and then any
307   // actually new threads will get added to new_thread_list.
308   m_thread_plans.ClearThreadCache();
309 
310   Status error;
311   StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo();
312 
313   if (!thread_info_sp)
314     return ScriptedInterface::ErrorWithMessage<bool>(
315         LLVM_PRETTY_FUNCTION,
316         "Couldn't fetch thread list from Scripted Process.", error);
317 
318   // Because `StructuredData::Dictionary` uses a `std::map<ConstString,
319   // ObjectSP>` for storage, each item is sorted based on the key alphabetical
320   // order. Since `GetThreadsInfo` provides thread indices as the key element,
321   // thread info comes ordered alphabetically, instead of numerically, so we
322   // need to sort the thread indices before creating thread.
323 
324   StructuredData::ArraySP keys = thread_info_sp->GetKeys();
325 
326   std::map<size_t, StructuredData::ObjectSP> sorted_threads;
327   auto sort_keys = [&sorted_threads,
328                     &thread_info_sp](StructuredData::Object *item) -> bool {
329     if (!item)
330       return false;
331 
332     llvm::StringRef key = item->GetStringValue();
333     size_t idx = 0;
334 
335     // Make sure the provided index is actually an integer
336     if (!llvm::to_integer(key, idx))
337       return false;
338 
339     sorted_threads[idx] = thread_info_sp->GetValueForKey(key);
340     return true;
341   };
342 
343   size_t thread_count = thread_info_sp->GetSize();
344 
345   if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count)
346     // Might be worth showing the unsorted thread list instead of return early.
347     return ScriptedInterface::ErrorWithMessage<bool>(
348         LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error);
349 
350   auto create_scripted_thread =
351       [this, &error, &new_thread_list](
352           const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool {
353     size_t idx = pair.first;
354     StructuredData::ObjectSP object_sp = pair.second;
355 
356     if (!object_sp)
357       return ScriptedInterface::ErrorWithMessage<bool>(
358           LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);
359 
360     auto thread_or_error =
361         ScriptedThread::Create(*this, object_sp->GetAsGeneric());
362 
363     if (!thread_or_error)
364       return ScriptedInterface::ErrorWithMessage<bool>(
365           LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error);
366 
367     ThreadSP thread_sp = thread_or_error.get();
368     lldbassert(thread_sp && "Couldn't initialize scripted thread.");
369 
370     RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
371     if (!reg_ctx_sp)
372       return ScriptedInterface::ErrorWithMessage<bool>(
373           LLVM_PRETTY_FUNCTION,
374           llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx))
375               .str(),
376           error);
377 
378     new_thread_list.AddThread(thread_sp);
379 
380     return true;
381   };
382 
383   llvm::for_each(sorted_threads, create_scripted_thread);
384 
385   return new_thread_list.GetSize(false) > 0;
386 }
387 
388 void ScriptedProcess::RefreshStateAfterStop() {
389   // Let all threads recover from stopping and do any clean up based on the
390   // previous thread state (if any).
391   m_thread_list.RefreshStateAfterStop();
392 }
393 
394 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
395   info.Clear();
396   info.SetProcessID(GetID());
397   info.SetArchitecture(GetArchitecture());
398   lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
399   if (module_sp) {
400     const bool add_exe_file_as_first_arg = false;
401     info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
402                            add_exe_file_as_first_arg);
403   }
404   return true;
405 }
406 
407 lldb_private::StructuredData::ObjectSP
408 ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
409   Status error;
410   auto error_with_message = [&error](llvm::StringRef message) {
411     return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
412                                                      message.data(), error);
413   };
414 
415   StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages();
416 
417   if (!loaded_images_sp || !loaded_images_sp->GetSize())
418     return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
419         LLVM_PRETTY_FUNCTION, "No loaded images.", error);
420 
421   ModuleList module_list;
422   Target &target = GetTarget();
423 
424   auto reload_image = [&target, &module_list, &error_with_message](
425                           StructuredData::Object *obj) -> bool {
426     StructuredData::Dictionary *dict = obj->GetAsDictionary();
427 
428     if (!dict)
429       return error_with_message("Couldn't cast image object into dictionary.");
430 
431     ModuleSpec module_spec;
432     llvm::StringRef value;
433 
434     bool has_path = dict->HasKey("path");
435     bool has_uuid = dict->HasKey("uuid");
436     if (!has_path && !has_uuid)
437       return error_with_message("Dictionary should have key 'path' or 'uuid'");
438     if (!dict->HasKey("load_addr"))
439       return error_with_message("Dictionary is missing key 'load_addr'");
440 
441     if (has_path) {
442       dict->GetValueForKeyAsString("path", value);
443       module_spec.GetFileSpec().SetPath(value);
444     }
445 
446     if (has_uuid) {
447       dict->GetValueForKeyAsString("uuid", value);
448       module_spec.GetUUID().SetFromStringRef(value);
449     }
450     module_spec.GetArchitecture() = target.GetArchitecture();
451 
452     ModuleSP module_sp =
453         target.GetOrCreateModule(module_spec, true /* notify */);
454 
455     if (!module_sp)
456       return error_with_message("Couldn't create or get module.");
457 
458     lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
459     lldb::offset_t slide = LLDB_INVALID_OFFSET;
460     dict->GetValueForKeyAsInteger("load_addr", load_addr);
461     dict->GetValueForKeyAsInteger("slide", slide);
462     if (load_addr == LLDB_INVALID_ADDRESS)
463       return error_with_message(
464           "Couldn't get valid load address or slide offset.");
465 
466     if (slide != LLDB_INVALID_OFFSET)
467       load_addr += slide;
468 
469     bool changed = false;
470     module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/,
471                               changed);
472 
473     if (!changed && !module_sp->GetObjectFile())
474       return error_with_message("Couldn't set the load address for module.");
475 
476     dict->GetValueForKeyAsString("path", value);
477     FileSpec objfile(value);
478     module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename());
479 
480     return module_list.AppendIfNeeded(module_sp);
481   };
482 
483   if (!loaded_images_sp->ForEach(reload_image))
484     return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
485         LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);
486 
487   target.ModulesDidLoad(module_list);
488 
489   return loaded_images_sp;
490 }
491 
492 lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() {
493   StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata();
494 
495   Status error;
496   if (!metadata_sp || !metadata_sp->GetSize())
497     return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>(
498         LLVM_PRETTY_FUNCTION, "No metadata.", error);
499 
500   return metadata_sp;
501 }
502 
503 void ScriptedProcess::UpdateQueueListIfNeeded() {
504   CheckScriptedInterface();
505   for (ThreadSP thread_sp : Threads()) {
506     if (const char *queue_name = thread_sp->GetQueueName()) {
507       QueueSP queue_sp = std::make_shared<Queue>(
508           m_process->shared_from_this(), thread_sp->GetQueueID(), queue_name);
509       m_queue_list.AddQueue(queue_sp);
510     }
511   }
512 }
513 
514 ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
515   CheckScriptedInterface();
516   return *m_interface_up;
517 }
518 
519 void *ScriptedProcess::GetImplementation() {
520   StructuredData::GenericSP object_instance_sp =
521       GetInterface().GetScriptObjectInstance();
522   if (object_instance_sp &&
523       object_instance_sp->GetType() == eStructuredDataTypeGeneric)
524     return object_instance_sp->GetAsGeneric()->GetValue();
525   return nullptr;
526 }
527