Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / source / Plugins / Process / scripted / ScriptedProcess.cpp
blobf2a647c1b0bea4ccfdb190ac608b339d65465f88
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 //===----------------------------------------------------------------------===//
9 #include "ScriptedProcess.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/PluginManager.h"
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"
28 #include <mutex>
30 LLDB_PLUGIN_DEFINE(ScriptedProcess)
32 using namespace lldb;
33 using namespace lldb_private;
35 llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() {
36 return "Scripted Process plug-in.";
39 static constexpr lldb::ScriptLanguage g_supported_script_languages[] = {
40 ScriptLanguage::eScriptLanguagePython,
43 bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) {
44 llvm::ArrayRef<lldb::ScriptLanguage> supported_languages =
45 llvm::ArrayRef(g_supported_script_languages);
47 return llvm::is_contained(supported_languages, language);
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;
58 ScriptedMetadata scripted_metadata(target_sp->GetProcessLaunchInfo());
60 Status error;
61 auto process_sp = std::shared_ptr<ScriptedProcess>(
62 new ScriptedProcess(target_sp, listener_sp, scripted_metadata, error));
64 if (error.Fail() || !process_sp || !process_sp->m_interface_up) {
65 LLDB_LOGF(GetLog(LLDBLog::Process), "%s", error.AsCString());
66 return nullptr;
69 return process_sp;
72 bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
73 bool plugin_specified_by_name) {
74 return true;
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) {
83 if (!target_sp) {
84 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
85 __FUNCTION__, "Invalid target");
86 return;
89 ScriptInterpreter *interpreter =
90 target_sp->GetDebugger().GetScriptInterpreter();
92 if (!interpreter) {
93 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
94 __FUNCTION__,
95 "Debugger has no Script Interpreter");
96 return;
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;
108 ExecutionContext exe_ctx(target_sp, /*get_process=*/false);
110 // Create process script object
111 auto obj_or_err = GetInterface().CreatePluginObject(
112 m_scripted_metadata.GetClassName(), exe_ctx,
113 m_scripted_metadata.GetArgsSP());
115 if (!obj_or_err) {
116 llvm::consumeError(obj_or_err.takeError());
117 error.SetErrorString("Failed to create script object.");
118 return;
121 StructuredData::GenericSP object_sp = *obj_or_err;
123 if (!object_sp || !object_sp->IsValid()) {
124 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
125 __FUNCTION__,
126 "Failed to create valid script object");
127 return;
131 ScriptedProcess::~ScriptedProcess() {
132 Clear();
133 // We need to call finalize on the process before destroying ourselves to
134 // make sure all of the broadcaster cleanup goes as planned. If we destruct
135 // this class, then Process::~Process() might have problems trying to fully
136 // destroy the broadcaster.
137 Finalize();
140 void ScriptedProcess::Initialize() {
141 static llvm::once_flag g_once_flag;
143 llvm::call_once(g_once_flag, []() {
144 PluginManager::RegisterPlugin(GetPluginNameStatic(),
145 GetPluginDescriptionStatic(), CreateInstance);
149 void ScriptedProcess::Terminate() {
150 PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
153 Status ScriptedProcess::DoLoadCore() {
154 ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
156 return DoLaunch(nullptr, launch_info);
159 Status ScriptedProcess::DoLaunch(Module *exe_module,
160 ProcessLaunchInfo &launch_info) {
161 LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s launching process", __FUNCTION__);
163 /* MARK: This doesn't reflect how lldb actually launches a process.
164 In reality, it attaches to debugserver, then resume the process.
165 That's not true in all cases. If debugserver is remote, lldb
166 asks debugserver to launch the process for it. */
167 Status error = GetInterface().Launch();
168 SetPrivateState(eStateStopped);
169 return error;
172 void ScriptedProcess::DidLaunch() { m_pid = GetInterface().GetProcessID(); }
174 void ScriptedProcess::DidResume() {
175 // Update the PID again, in case the user provided a placeholder pid at launch
176 m_pid = GetInterface().GetProcessID();
179 Status ScriptedProcess::DoResume() {
180 LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s resuming process", __FUNCTION__);
182 return GetInterface().Resume();
185 Status ScriptedProcess::DoAttach(const ProcessAttachInfo &attach_info) {
186 Status error = GetInterface().Attach(attach_info);
187 SetPrivateState(eStateRunning);
188 SetPrivateState(eStateStopped);
189 if (error.Fail())
190 return error;
191 // NOTE: We need to set the PID before finishing to attach otherwise we will
192 // hit an assert when calling the attach completion handler.
193 DidLaunch();
195 return {};
198 Status
199 ScriptedProcess::DoAttachToProcessWithID(lldb::pid_t pid,
200 const ProcessAttachInfo &attach_info) {
201 return DoAttach(attach_info);
204 Status ScriptedProcess::DoAttachToProcessWithName(
205 const char *process_name, const ProcessAttachInfo &attach_info) {
206 return DoAttach(attach_info);
209 void ScriptedProcess::DidAttach(ArchSpec &process_arch) {
210 process_arch = GetArchitecture();
213 Status ScriptedProcess::DoDestroy() { return Status(); }
215 bool ScriptedProcess::IsAlive() { return GetInterface().IsAlive(); }
217 size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
218 Status &error) {
219 lldb::DataExtractorSP data_extractor_sp =
220 GetInterface().ReadMemoryAtAddress(addr, size, error);
222 if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
223 return 0;
225 offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
226 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
228 if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
229 return ScriptedInterface::ErrorWithMessage<size_t>(
230 LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error);
232 // FIXME: We should use the diagnostic system to report a warning if the
233 // `bytes_copied` is different from `size`.
235 return bytes_copied;
238 size_t ScriptedProcess::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
239 size_t size, Status &error) {
240 lldb::DataExtractorSP data_extractor_sp = std::make_shared<DataExtractor>(
241 buf, size, GetByteOrder(), GetAddressByteSize());
243 if (!data_extractor_sp || !data_extractor_sp->GetByteSize())
244 return 0;
246 lldb::offset_t bytes_written =
247 GetInterface().WriteMemoryAtAddress(vm_addr, data_extractor_sp, error);
249 if (!bytes_written || bytes_written == LLDB_INVALID_OFFSET)
250 return ScriptedInterface::ErrorWithMessage<size_t>(
251 LLVM_PRETTY_FUNCTION, "Failed to copy write buffer to memory.", error);
253 // FIXME: We should use the diagnostic system to report a warning if the
254 // `bytes_written` is different from `size`.
256 return bytes_written;
259 Status ScriptedProcess::EnableBreakpointSite(BreakpointSite *bp_site) {
260 assert(bp_site != nullptr);
262 if (bp_site->IsEnabled()) {
263 return {};
266 if (bp_site->HardwareRequired()) {
267 return Status("Scripted Processes don't support hardware breakpoints");
270 Status error;
271 GetInterface().CreateBreakpoint(bp_site->GetLoadAddress(), error);
273 return error;
276 ArchSpec ScriptedProcess::GetArchitecture() {
277 return GetTarget().GetArchitecture();
280 Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
281 MemoryRegionInfo &region) {
282 Status error;
283 if (auto region_or_err =
284 GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
285 region = *region_or_err;
287 return error;
290 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
291 Status error;
292 lldb::addr_t address = 0;
294 while (auto region_or_err =
295 GetInterface().GetMemoryRegionContainingAddress(address, error)) {
296 if (error.Fail())
297 break;
299 MemoryRegionInfo &mem_region = *region_or_err;
300 auto range = mem_region.GetRange();
301 address += range.GetRangeBase() + range.GetByteSize();
302 region_list.push_back(mem_region);
305 return error;
308 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
310 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
311 ThreadList &new_thread_list) {
312 // TODO: Implement
313 // This is supposed to get the current set of threads, if any of them are in
314 // old_thread_list then they get copied to new_thread_list, and then any
315 // actually new threads will get added to new_thread_list.
316 m_thread_plans.ClearThreadCache();
318 Status error;
319 StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo();
321 if (!thread_info_sp)
322 return ScriptedInterface::ErrorWithMessage<bool>(
323 LLVM_PRETTY_FUNCTION,
324 "Couldn't fetch thread list from Scripted Process.", error);
326 // Because `StructuredData::Dictionary` uses a `std::map<ConstString,
327 // ObjectSP>` for storage, each item is sorted based on the key alphabetical
328 // order. Since `GetThreadsInfo` provides thread indices as the key element,
329 // thread info comes ordered alphabetically, instead of numerically, so we
330 // need to sort the thread indices before creating thread.
332 StructuredData::ArraySP keys = thread_info_sp->GetKeys();
334 std::map<size_t, StructuredData::ObjectSP> sorted_threads;
335 auto sort_keys = [&sorted_threads,
336 &thread_info_sp](StructuredData::Object *item) -> bool {
337 if (!item)
338 return false;
340 llvm::StringRef key = item->GetStringValue();
341 size_t idx = 0;
343 // Make sure the provided index is actually an integer
344 if (!llvm::to_integer(key, idx))
345 return false;
347 sorted_threads[idx] = thread_info_sp->GetValueForKey(key);
348 return true;
351 size_t thread_count = thread_info_sp->GetSize();
353 if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count)
354 // Might be worth showing the unsorted thread list instead of return early.
355 return ScriptedInterface::ErrorWithMessage<bool>(
356 LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error);
358 auto create_scripted_thread =
359 [this, &error, &new_thread_list](
360 const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool {
361 size_t idx = pair.first;
362 StructuredData::ObjectSP object_sp = pair.second;
364 if (!object_sp)
365 return ScriptedInterface::ErrorWithMessage<bool>(
366 LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);
368 auto thread_or_error =
369 ScriptedThread::Create(*this, object_sp->GetAsGeneric());
371 if (!thread_or_error)
372 return ScriptedInterface::ErrorWithMessage<bool>(
373 LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error);
375 ThreadSP thread_sp = thread_or_error.get();
376 lldbassert(thread_sp && "Couldn't initialize scripted thread.");
378 RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
379 if (!reg_ctx_sp)
380 return ScriptedInterface::ErrorWithMessage<bool>(
381 LLVM_PRETTY_FUNCTION,
382 llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx))
383 .str(),
384 error);
386 new_thread_list.AddThread(thread_sp);
388 return true;
391 llvm::for_each(sorted_threads, create_scripted_thread);
393 return new_thread_list.GetSize(false) > 0;
396 void ScriptedProcess::RefreshStateAfterStop() {
397 // Let all threads recover from stopping and do any clean up based on the
398 // previous thread state (if any).
399 m_thread_list.RefreshStateAfterStop();
402 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
403 info.Clear();
404 info.SetProcessID(GetID());
405 info.SetArchitecture(GetArchitecture());
406 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
407 if (module_sp) {
408 const bool add_exe_file_as_first_arg = false;
409 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
410 add_exe_file_as_first_arg);
412 return true;
415 lldb_private::StructuredData::ObjectSP
416 ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
417 Status error;
418 auto error_with_message = [&error](llvm::StringRef message) {
419 return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
420 message.data(), error);
423 StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages();
425 if (!loaded_images_sp || !loaded_images_sp->GetSize())
426 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
427 LLVM_PRETTY_FUNCTION, "No loaded images.", error);
429 ModuleList module_list;
430 Target &target = GetTarget();
432 auto reload_image = [&target, &module_list, &error_with_message](
433 StructuredData::Object *obj) -> bool {
434 StructuredData::Dictionary *dict = obj->GetAsDictionary();
436 if (!dict)
437 return error_with_message("Couldn't cast image object into dictionary.");
439 ModuleSpec module_spec;
440 llvm::StringRef value;
442 bool has_path = dict->HasKey("path");
443 bool has_uuid = dict->HasKey("uuid");
444 if (!has_path && !has_uuid)
445 return error_with_message("Dictionary should have key 'path' or 'uuid'");
446 if (!dict->HasKey("load_addr"))
447 return error_with_message("Dictionary is missing key 'load_addr'");
449 if (has_path) {
450 dict->GetValueForKeyAsString("path", value);
451 module_spec.GetFileSpec().SetPath(value);
454 if (has_uuid) {
455 dict->GetValueForKeyAsString("uuid", value);
456 module_spec.GetUUID().SetFromStringRef(value);
458 module_spec.GetArchitecture() = target.GetArchitecture();
460 ModuleSP module_sp =
461 target.GetOrCreateModule(module_spec, true /* notify */);
463 if (!module_sp)
464 return error_with_message("Couldn't create or get module.");
466 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
467 lldb::offset_t slide = LLDB_INVALID_OFFSET;
468 dict->GetValueForKeyAsInteger("load_addr", load_addr);
469 dict->GetValueForKeyAsInteger("slide", slide);
470 if (load_addr == LLDB_INVALID_ADDRESS)
471 return error_with_message(
472 "Couldn't get valid load address or slide offset.");
474 if (slide != LLDB_INVALID_OFFSET)
475 load_addr += slide;
477 bool changed = false;
478 module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/,
479 changed);
481 if (!changed && !module_sp->GetObjectFile())
482 return error_with_message("Couldn't set the load address for module.");
484 dict->GetValueForKeyAsString("path", value);
485 FileSpec objfile(value);
486 module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename());
488 return module_list.AppendIfNeeded(module_sp);
491 if (!loaded_images_sp->ForEach(reload_image))
492 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
493 LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);
495 target.ModulesDidLoad(module_list);
497 return loaded_images_sp;
500 lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() {
501 StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata();
503 Status error;
504 if (!metadata_sp || !metadata_sp->GetSize())
505 return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>(
506 LLVM_PRETTY_FUNCTION, "No metadata.", error);
508 return metadata_sp;
511 void ScriptedProcess::UpdateQueueListIfNeeded() {
512 CheckScriptedInterface();
513 for (ThreadSP thread_sp : Threads()) {
514 if (const char *queue_name = thread_sp->GetQueueName()) {
515 QueueSP queue_sp = std::make_shared<Queue>(
516 m_process->shared_from_this(), thread_sp->GetQueueID(), queue_name);
517 m_queue_list.AddQueue(queue_sp);
522 ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
523 CheckScriptedInterface();
524 return *m_interface_up;
527 void *ScriptedProcess::GetImplementation() {
528 StructuredData::GenericSP object_instance_sp =
529 GetInterface().GetScriptObjectInstance();
530 if (object_instance_sp &&
531 object_instance_sp->GetType() == eStructuredDataTypeGeneric)
532 return object_instance_sp->GetAsGeneric()->GetValue();
533 return nullptr;