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