xref: /llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp (revision e31d0c20e411f22a943f1ed5f8b618c529436c59)
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   GetLoadedDynamicLibrariesInfos();
170 }
171 
172 Status ScriptedProcess::DoResume() {
173   LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s resuming process", __FUNCTION__);
174 
175   return GetInterface().Resume();
176 }
177 
178 Status ScriptedProcess::DoAttach(const ProcessAttachInfo &attach_info) {
179   Status error = GetInterface().Attach(attach_info);
180   SetPrivateState(eStateRunning);
181   SetPrivateState(eStateStopped);
182   if (error.Fail())
183     return error;
184   // NOTE: We need to set the PID before finishing to attach otherwise we will
185   // hit an assert when calling the attach completion handler.
186   DidLaunch();
187 
188   return {};
189 }
190 
191 Status
192 ScriptedProcess::DoAttachToProcessWithID(lldb::pid_t pid,
193                                          const ProcessAttachInfo &attach_info) {
194   return DoAttach(attach_info);
195 }
196 
197 Status ScriptedProcess::DoAttachToProcessWithName(
198     const char *process_name, const ProcessAttachInfo &attach_info) {
199   return DoAttach(attach_info);
200 }
201 
202 void ScriptedProcess::DidAttach(ArchSpec &process_arch) {
203   process_arch = GetArchitecture();
204 }
205 
206 Status ScriptedProcess::DoDestroy() { return Status(); }
207 
208 bool ScriptedProcess::IsAlive() { return GetInterface().IsAlive(); }
209 
210 size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
211                                      Status &error) {
212   lldb::DataExtractorSP data_extractor_sp =
213       GetInterface().ReadMemoryAtAddress(addr, size, error);
214 
215   if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
216     return 0;
217 
218   offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
219       0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
220 
221   if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
222     return ScriptedInterface::ErrorWithMessage<size_t>(
223         LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error);
224 
225   // FIXME: We should use the diagnostic system to report a warning if the
226   // `bytes_copied` is different from `size`.
227 
228   return bytes_copied;
229 }
230 
231 size_t ScriptedProcess::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
232                                       size_t size, Status &error) {
233   lldb::DataExtractorSP data_extractor_sp = std::make_shared<DataExtractor>(
234       buf, size, GetByteOrder(), GetAddressByteSize());
235 
236   if (!data_extractor_sp || !data_extractor_sp->GetByteSize())
237     return 0;
238 
239   lldb::offset_t bytes_written =
240       GetInterface().WriteMemoryAtAddress(vm_addr, data_extractor_sp, error);
241 
242   if (!bytes_written || bytes_written == LLDB_INVALID_OFFSET)
243     return ScriptedInterface::ErrorWithMessage<size_t>(
244         LLVM_PRETTY_FUNCTION, "Failed to copy write buffer to memory.", error);
245 
246   // FIXME: We should use the diagnostic system to report a warning if the
247   // `bytes_written` is different from `size`.
248 
249   return bytes_written;
250 }
251 
252 Status ScriptedProcess::EnableBreakpointSite(BreakpointSite *bp_site) {
253   assert(bp_site != nullptr);
254 
255   if (bp_site->IsEnabled()) {
256     return {};
257   }
258 
259   if (bp_site->HardwareRequired()) {
260     return Status("Scripted Processes don't support hardware breakpoints");
261   }
262 
263   Status error;
264   GetInterface().CreateBreakpoint(bp_site->GetLoadAddress(), error);
265 
266   return error;
267 }
268 
269 ArchSpec ScriptedProcess::GetArchitecture() {
270   return GetTarget().GetArchitecture();
271 }
272 
273 Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
274                                               MemoryRegionInfo &region) {
275   Status error;
276   if (auto region_or_err =
277           GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
278     region = *region_or_err;
279 
280   return error;
281 }
282 
283 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
284   Status error;
285   lldb::addr_t address = 0;
286 
287   while (auto region_or_err =
288              GetInterface().GetMemoryRegionContainingAddress(address, error)) {
289     if (error.Fail())
290       break;
291 
292     MemoryRegionInfo &mem_region = *region_or_err;
293     auto range = mem_region.GetRange();
294     address += range.GetRangeBase() + range.GetByteSize();
295     region_list.push_back(mem_region);
296   }
297 
298   return error;
299 }
300 
301 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
302 
303 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
304                                          ThreadList &new_thread_list) {
305   // TODO: Implement
306   // This is supposed to get the current set of threads, if any of them are in
307   // old_thread_list then they get copied to new_thread_list, and then any
308   // actually new threads will get added to new_thread_list.
309   m_thread_plans.ClearThreadCache();
310 
311   Status error;
312   StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo();
313 
314   if (!thread_info_sp)
315     return ScriptedInterface::ErrorWithMessage<bool>(
316         LLVM_PRETTY_FUNCTION,
317         "Couldn't fetch thread list from Scripted Process.", error);
318 
319   // Because `StructuredData::Dictionary` uses a `std::map<ConstString,
320   // ObjectSP>` for storage, each item is sorted based on the key alphabetical
321   // order. Since `GetThreadsInfo` provides thread indices as the key element,
322   // thread info comes ordered alphabetically, instead of numerically, so we
323   // need to sort the thread indices before creating thread.
324 
325   StructuredData::ArraySP keys = thread_info_sp->GetKeys();
326 
327   std::map<size_t, StructuredData::ObjectSP> sorted_threads;
328   auto sort_keys = [&sorted_threads,
329                     &thread_info_sp](StructuredData::Object *item) -> bool {
330     if (!item)
331       return false;
332 
333     llvm::StringRef key = item->GetStringValue();
334     size_t idx = 0;
335 
336     // Make sure the provided index is actually an integer
337     if (!llvm::to_integer(key, idx))
338       return false;
339 
340     sorted_threads[idx] = thread_info_sp->GetValueForKey(key);
341     return true;
342   };
343 
344   size_t thread_count = thread_info_sp->GetSize();
345 
346   if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count)
347     // Might be worth showing the unsorted thread list instead of return early.
348     return ScriptedInterface::ErrorWithMessage<bool>(
349         LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error);
350 
351   auto create_scripted_thread =
352       [this, &error, &new_thread_list](
353           const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool {
354     size_t idx = pair.first;
355     StructuredData::ObjectSP object_sp = pair.second;
356 
357     if (!object_sp)
358       return ScriptedInterface::ErrorWithMessage<bool>(
359           LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);
360 
361     auto thread_or_error =
362         ScriptedThread::Create(*this, object_sp->GetAsGeneric());
363 
364     if (!thread_or_error)
365       return ScriptedInterface::ErrorWithMessage<bool>(
366           LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error);
367 
368     ThreadSP thread_sp = thread_or_error.get();
369     lldbassert(thread_sp && "Couldn't initialize scripted thread.");
370 
371     RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
372     if (!reg_ctx_sp)
373       return ScriptedInterface::ErrorWithMessage<bool>(
374           LLVM_PRETTY_FUNCTION,
375           llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx))
376               .str(),
377           error);
378 
379     new_thread_list.AddThread(thread_sp);
380 
381     return true;
382   };
383 
384   llvm::for_each(sorted_threads, create_scripted_thread);
385 
386   return new_thread_list.GetSize(false) > 0;
387 }
388 
389 void ScriptedProcess::RefreshStateAfterStop() {
390   // Let all threads recover from stopping and do any clean up based on the
391   // previous thread state (if any).
392   m_thread_list.RefreshStateAfterStop();
393 }
394 
395 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
396   info.Clear();
397   info.SetProcessID(GetID());
398   info.SetArchitecture(GetArchitecture());
399   lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
400   if (module_sp) {
401     const bool add_exe_file_as_first_arg = false;
402     info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
403                            add_exe_file_as_first_arg);
404   }
405   return true;
406 }
407 
408 lldb_private::StructuredData::ObjectSP
409 ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
410   Status error;
411   auto error_with_message = [&error](llvm::StringRef message) {
412     return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
413                                                      message.data(), error);
414   };
415 
416   StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages();
417 
418   if (!loaded_images_sp || !loaded_images_sp->GetSize())
419     return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
420         LLVM_PRETTY_FUNCTION, "No loaded images.", error);
421 
422   ModuleList module_list;
423   Target &target = GetTarget();
424 
425   auto reload_image = [&target, &module_list, &error_with_message](
426                           StructuredData::Object *obj) -> bool {
427     StructuredData::Dictionary *dict = obj->GetAsDictionary();
428 
429     if (!dict)
430       return error_with_message("Couldn't cast image object into dictionary.");
431 
432     ModuleSpec module_spec;
433     llvm::StringRef value;
434 
435     bool has_path = dict->HasKey("path");
436     bool has_uuid = dict->HasKey("uuid");
437     if (!has_path && !has_uuid)
438       return error_with_message("Dictionary should have key 'path' or 'uuid'");
439     if (!dict->HasKey("load_addr"))
440       return error_with_message("Dictionary is missing key 'load_addr'");
441 
442     if (has_path) {
443       dict->GetValueForKeyAsString("path", value);
444       module_spec.GetFileSpec().SetPath(value);
445     }
446 
447     if (has_uuid) {
448       dict->GetValueForKeyAsString("uuid", value);
449       module_spec.GetUUID().SetFromStringRef(value);
450     }
451     module_spec.GetArchitecture() = target.GetArchitecture();
452 
453     ModuleSP module_sp =
454         target.GetOrCreateModule(module_spec, true /* notify */);
455 
456     if (!module_sp)
457       return error_with_message("Couldn't create or get module.");
458 
459     lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
460     lldb::addr_t slide = LLDB_INVALID_OFFSET;
461     dict->GetValueForKeyAsInteger("load_addr", load_addr);
462     dict->GetValueForKeyAsInteger("slide", slide);
463     if (load_addr == LLDB_INVALID_ADDRESS)
464       return error_with_message(
465           "Couldn't get valid load address or slide offset.");
466 
467     if (slide != LLDB_INVALID_OFFSET)
468       load_addr += slide;
469 
470     bool changed = false;
471     module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/,
472                               changed);
473 
474     if (!changed && !module_sp->GetObjectFile())
475       return error_with_message("Couldn't set the load address for module.");
476 
477     dict->GetValueForKeyAsString("path", value);
478     FileSpec objfile(value);
479     module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename());
480 
481     return module_list.AppendIfNeeded(module_sp);
482   };
483 
484   if (!loaded_images_sp->ForEach(reload_image))
485     return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
486         LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);
487 
488   target.ModulesDidLoad(module_list);
489 
490   return loaded_images_sp;
491 }
492 
493 lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() {
494   StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata();
495 
496   Status error;
497   if (!metadata_sp || !metadata_sp->GetSize())
498     return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>(
499         LLVM_PRETTY_FUNCTION, "No metadata.", error);
500 
501   return metadata_sp;
502 }
503 
504 void ScriptedProcess::UpdateQueueListIfNeeded() {
505   CheckScriptedInterface();
506   for (ThreadSP thread_sp : Threads()) {
507     if (const char *queue_name = thread_sp->GetQueueName()) {
508       QueueSP queue_sp = std::make_shared<Queue>(
509           m_process->shared_from_this(), thread_sp->GetQueueID(), queue_name);
510       m_queue_list.AddQueue(queue_sp);
511     }
512   }
513 }
514 
515 ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
516   CheckScriptedInterface();
517   return *m_interface_up;
518 }
519 
520 void *ScriptedProcess::GetImplementation() {
521   StructuredData::GenericSP object_instance_sp =
522       GetInterface().GetScriptObjectInstance();
523   if (object_instance_sp &&
524       object_instance_sp->GetType() == eStructuredDataTypeGeneric)
525     return object_instance_sp->GetAsGeneric()->GetValue();
526   return nullptr;
527 }
528