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