xref: /llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp (revision ad03aeadfb72e9c872b297bbaedbf46ebac3572c)
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   return EnableSoftwareBreakpoint(bp_site);
264 }
265 
266 ArchSpec ScriptedProcess::GetArchitecture() {
267   return GetTarget().GetArchitecture();
268 }
269 
270 Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
271                                               MemoryRegionInfo &region) {
272   Status error;
273   if (auto region_or_err =
274           GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
275     region = *region_or_err;
276 
277   return error;
278 }
279 
280 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
281   Status error;
282   lldb::addr_t address = 0;
283 
284   while (auto region_or_err =
285              GetInterface().GetMemoryRegionContainingAddress(address, error)) {
286     if (error.Fail())
287       break;
288 
289     MemoryRegionInfo &mem_region = *region_or_err;
290     auto range = mem_region.GetRange();
291     address += range.GetRangeBase() + range.GetByteSize();
292     region_list.push_back(mem_region);
293   }
294 
295   return error;
296 }
297 
298 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
299 
300 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
301                                          ThreadList &new_thread_list) {
302   // TODO: Implement
303   // This is supposed to get the current set of threads, if any of them are in
304   // old_thread_list then they get copied to new_thread_list, and then any
305   // actually new threads will get added to new_thread_list.
306   m_thread_plans.ClearThreadCache();
307 
308   Status error;
309   StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo();
310 
311   if (!thread_info_sp)
312     return ScriptedInterface::ErrorWithMessage<bool>(
313         LLVM_PRETTY_FUNCTION,
314         "Couldn't fetch thread list from Scripted Process.", error);
315 
316   // Because `StructuredData::Dictionary` uses a `std::map<ConstString,
317   // ObjectSP>` for storage, each item is sorted based on the key alphabetical
318   // order. Since `GetThreadsInfo` provides thread indices as the key element,
319   // thread info comes ordered alphabetically, instead of numerically, so we
320   // need to sort the thread indices before creating thread.
321 
322   StructuredData::ArraySP keys = thread_info_sp->GetKeys();
323 
324   std::map<size_t, StructuredData::ObjectSP> sorted_threads;
325   auto sort_keys = [&sorted_threads,
326                     &thread_info_sp](StructuredData::Object *item) -> bool {
327     if (!item)
328       return false;
329 
330     llvm::StringRef key = item->GetStringValue();
331     size_t idx = 0;
332 
333     // Make sure the provided index is actually an integer
334     if (!llvm::to_integer(key, idx))
335       return false;
336 
337     sorted_threads[idx] = thread_info_sp->GetValueForKey(key);
338     return true;
339   };
340 
341   size_t thread_count = thread_info_sp->GetSize();
342 
343   if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count)
344     // Might be worth showing the unsorted thread list instead of return early.
345     return ScriptedInterface::ErrorWithMessage<bool>(
346         LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error);
347 
348   auto create_scripted_thread =
349       [this, &error, &new_thread_list](
350           const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool {
351     size_t idx = pair.first;
352     StructuredData::ObjectSP object_sp = pair.second;
353 
354     if (!object_sp)
355       return ScriptedInterface::ErrorWithMessage<bool>(
356           LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);
357 
358     auto thread_or_error =
359         ScriptedThread::Create(*this, object_sp->GetAsGeneric());
360 
361     if (!thread_or_error)
362       return ScriptedInterface::ErrorWithMessage<bool>(
363           LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error);
364 
365     ThreadSP thread_sp = thread_or_error.get();
366     lldbassert(thread_sp && "Couldn't initialize scripted thread.");
367 
368     RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
369     if (!reg_ctx_sp)
370       return ScriptedInterface::ErrorWithMessage<bool>(
371           LLVM_PRETTY_FUNCTION,
372           llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx))
373               .str(),
374           error);
375 
376     new_thread_list.AddThread(thread_sp);
377 
378     return true;
379   };
380 
381   llvm::for_each(sorted_threads, create_scripted_thread);
382 
383   return new_thread_list.GetSize(false) > 0;
384 }
385 
386 void ScriptedProcess::RefreshStateAfterStop() {
387   // Let all threads recover from stopping and do any clean up based on the
388   // previous thread state (if any).
389   m_thread_list.RefreshStateAfterStop();
390 }
391 
392 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
393   info.Clear();
394   info.SetProcessID(GetID());
395   info.SetArchitecture(GetArchitecture());
396   lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
397   if (module_sp) {
398     const bool add_exe_file_as_first_arg = false;
399     info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
400                            add_exe_file_as_first_arg);
401   }
402   return true;
403 }
404 
405 lldb_private::StructuredData::ObjectSP
406 ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
407   Status error;
408   auto error_with_message = [&error](llvm::StringRef message) {
409     return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
410                                                      message.data(), error);
411   };
412 
413   StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages();
414 
415   if (!loaded_images_sp || !loaded_images_sp->GetSize())
416     return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
417         LLVM_PRETTY_FUNCTION, "No loaded images.", error);
418 
419   ModuleList module_list;
420   Target &target = GetTarget();
421 
422   auto reload_image = [&target, &module_list, &error_with_message](
423                           StructuredData::Object *obj) -> bool {
424     StructuredData::Dictionary *dict = obj->GetAsDictionary();
425 
426     if (!dict)
427       return error_with_message("Couldn't cast image object into dictionary.");
428 
429     ModuleSpec module_spec;
430     llvm::StringRef value;
431 
432     bool has_path = dict->HasKey("path");
433     bool has_uuid = dict->HasKey("uuid");
434     if (!has_path && !has_uuid)
435       return error_with_message("Dictionary should have key 'path' or 'uuid'");
436     if (!dict->HasKey("load_addr"))
437       return error_with_message("Dictionary is missing key 'load_addr'");
438 
439     if (has_path) {
440       dict->GetValueForKeyAsString("path", value);
441       module_spec.GetFileSpec().SetPath(value);
442     }
443 
444     if (has_uuid) {
445       dict->GetValueForKeyAsString("uuid", value);
446       module_spec.GetUUID().SetFromStringRef(value);
447     }
448     module_spec.GetArchitecture() = target.GetArchitecture();
449 
450     ModuleSP module_sp =
451         target.GetOrCreateModule(module_spec, true /* notify */);
452 
453     if (!module_sp)
454       return error_with_message("Couldn't create or get module.");
455 
456     lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
457     lldb::addr_t slide = LLDB_INVALID_OFFSET;
458     dict->GetValueForKeyAsInteger("load_addr", load_addr);
459     dict->GetValueForKeyAsInteger("slide", slide);
460     if (load_addr == LLDB_INVALID_ADDRESS)
461       return error_with_message(
462           "Couldn't get valid load address or slide offset.");
463 
464     if (slide != LLDB_INVALID_OFFSET)
465       load_addr += slide;
466 
467     bool changed = false;
468     module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/,
469                               changed);
470 
471     if (!changed && !module_sp->GetObjectFile())
472       return error_with_message("Couldn't set the load address for module.");
473 
474     dict->GetValueForKeyAsString("path", value);
475     FileSpec objfile(value);
476     module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename());
477 
478     return module_list.AppendIfNeeded(module_sp);
479   };
480 
481   if (!loaded_images_sp->ForEach(reload_image))
482     return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
483         LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);
484 
485   target.ModulesDidLoad(module_list);
486 
487   return loaded_images_sp;
488 }
489 
490 lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() {
491   StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata();
492 
493   Status error;
494   if (!metadata_sp || !metadata_sp->GetSize())
495     return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>(
496         LLVM_PRETTY_FUNCTION, "No metadata.", error);
497 
498   return metadata_sp;
499 }
500 
501 void ScriptedProcess::UpdateQueueListIfNeeded() {
502   CheckScriptedInterface();
503   for (ThreadSP thread_sp : Threads()) {
504     if (const char *queue_name = thread_sp->GetQueueName()) {
505       QueueSP queue_sp = std::make_shared<Queue>(
506           m_process->shared_from_this(), thread_sp->GetQueueID(), queue_name);
507       m_queue_list.AddQueue(queue_sp);
508     }
509   }
510 }
511 
512 ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
513   CheckScriptedInterface();
514   return *m_interface_up;
515 }
516 
517 void *ScriptedProcess::GetImplementation() {
518   StructuredData::GenericSP object_instance_sp =
519       GetInterface().GetScriptObjectInstance();
520   if (object_instance_sp &&
521       object_instance_sp->GetType() == eStructuredDataTypeGeneric)
522     return object_instance_sp->GetAsGeneric()->GetValue();
523   return nullptr;
524 }
525