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