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