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