[InstCombine] Remove foldSelectICmpEq() fold (#122098)
[llvm-project.git] / lldb / source / Plugins / Process / scripted / ScriptedProcess.cpp
blobd2111ce877ce55d1d5a8dae6ad7f90b46ddcd2b3
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 = Status::FromErrorStringWithFormat(
85 "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__, "Invalid target");
86 return;
89 ScriptInterpreter *interpreter =
90 target_sp->GetDebugger().GetScriptInterpreter();
92 if (!interpreter) {
93 error = Status::FromErrorStringWithFormat(
94 "ScriptedProcess::%s () - ERROR: %s", __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 = Status::FromErrorStringWithFormat(
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 = Status::FromErrorString("Failed to create script object.");
118 return;
121 StructuredData::GenericSP object_sp = *obj_or_err;
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;
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 */);
146 void ScriptedProcess::Initialize() {
147 static llvm::once_flag g_once_flag;
149 llvm::call_once(g_once_flag, []() {
150 PluginManager::RegisterPlugin(GetPluginNameStatic(),
151 GetPluginDescriptionStatic(), CreateInstance);
155 void ScriptedProcess::Terminate() {
156 PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
159 Status ScriptedProcess::DoLoadCore() {
160 ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
162 return DoLaunch(nullptr, launch_info);
165 Status ScriptedProcess::DoLaunch(Module *exe_module,
166 ProcessLaunchInfo &launch_info) {
167 LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s launching process", __FUNCTION__);
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;
178 void ScriptedProcess::DidLaunch() { m_pid = GetInterface().GetProcessID(); }
180 void ScriptedProcess::DidResume() {
181 // Update the PID again, in case the user provided a placeholder pid at launch
182 m_pid = GetInterface().GetProcessID();
185 Status ScriptedProcess::DoResume() {
186 LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s resuming process", __FUNCTION__);
188 return GetInterface().Resume();
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();
201 return {};
204 Status
205 ScriptedProcess::DoAttachToProcessWithID(lldb::pid_t pid,
206 const ProcessAttachInfo &attach_info) {
207 return DoAttach(attach_info);
210 Status ScriptedProcess::DoAttachToProcessWithName(
211 const char *process_name, const ProcessAttachInfo &attach_info) {
212 return DoAttach(attach_info);
215 void ScriptedProcess::DidAttach(ArchSpec &process_arch) {
216 process_arch = GetArchitecture();
219 Status ScriptedProcess::DoDestroy() { return Status(); }
221 bool ScriptedProcess::IsAlive() { return GetInterface().IsAlive(); }
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);
228 if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
229 return 0;
231 offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
232 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
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);
238 // FIXME: We should use the diagnostic system to report a warning if the
239 // `bytes_copied` is different from `size`.
241 return bytes_copied;
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());
249 if (!data_extractor_sp || !data_extractor_sp->GetByteSize())
250 return 0;
252 lldb::offset_t bytes_written =
253 GetInterface().WriteMemoryAtAddress(vm_addr, data_extractor_sp, error);
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);
259 // FIXME: We should use the diagnostic system to report a warning if the
260 // `bytes_written` is different from `size`.
262 return bytes_written;
265 Status ScriptedProcess::EnableBreakpointSite(BreakpointSite *bp_site) {
266 assert(bp_site != nullptr);
268 if (bp_site->IsEnabled()) {
269 return {};
272 if (bp_site->HardwareRequired()) {
273 return Status::FromErrorString(
274 "Scripted Processes don't support hardware breakpoints");
277 Status error;
278 GetInterface().CreateBreakpoint(bp_site->GetLoadAddress(), error);
280 return error;
283 ArchSpec ScriptedProcess::GetArchitecture() {
284 return GetTarget().GetArchitecture();
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;
294 return error;
297 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos &region_list) {
298 Status error;
299 lldb::addr_t address = 0;
301 while (auto region_or_err =
302 GetInterface().GetMemoryRegionContainingAddress(address, error)) {
303 if (error.Fail())
304 break;
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);
312 return error;
315 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
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();
325 Status error;
326 StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo();
328 if (!thread_info_sp)
329 return ScriptedInterface::ErrorWithMessage<bool>(
330 LLVM_PRETTY_FUNCTION,
331 "Couldn't fetch thread list from Scripted Process.", error);
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.
339 StructuredData::ArraySP keys = thread_info_sp->GetKeys();
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;
347 llvm::StringRef key = item->GetStringValue();
348 size_t idx = 0;
350 // Make sure the provided index is actually an integer
351 if (!llvm::to_integer(key, idx))
352 return false;
354 sorted_threads[idx] = thread_info_sp->GetValueForKey(key);
355 return true;
358 size_t thread_count = thread_info_sp->GetSize();
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);
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;
371 if (!object_sp)
372 return ScriptedInterface::ErrorWithMessage<bool>(
373 LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);
375 auto thread_or_error =
376 ScriptedThread::Create(*this, object_sp->GetAsGeneric());
378 if (!thread_or_error)
379 return ScriptedInterface::ErrorWithMessage<bool>(
380 LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error);
382 ThreadSP thread_sp = thread_or_error.get();
383 lldbassert(thread_sp && "Couldn't initialize scripted thread.");
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);
393 new_thread_list.AddThread(thread_sp);
395 return true;
398 llvm::for_each(sorted_threads, create_scripted_thread);
400 return new_thread_list.GetSize(false) > 0;
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();
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);
419 return true;
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);
430 StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages();
432 if (!loaded_images_sp || !loaded_images_sp->GetSize())
433 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
434 LLVM_PRETTY_FUNCTION, "No loaded images.", error);
436 ModuleList module_list;
437 Target &target = GetTarget();
439 auto reload_image = [&target, &module_list, &error_with_message](
440 StructuredData::Object *obj) -> bool {
441 StructuredData::Dictionary *dict = obj->GetAsDictionary();
443 if (!dict)
444 return error_with_message("Couldn't cast image object into dictionary.");
446 ModuleSpec module_spec;
447 llvm::StringRef value;
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'");
456 if (has_path) {
457 dict->GetValueForKeyAsString("path", value);
458 module_spec.GetFileSpec().SetPath(value);
461 if (has_uuid) {
462 dict->GetValueForKeyAsString("uuid", value);
463 module_spec.GetUUID().SetFromStringRef(value);
465 module_spec.GetArchitecture() = target.GetArchitecture();
467 ModuleSP module_sp =
468 target.GetOrCreateModule(module_spec, true /* notify */);
470 if (!module_sp)
471 return error_with_message("Couldn't create or get module.");
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.");
481 if (slide != LLDB_INVALID_OFFSET)
482 load_addr += slide;
484 bool changed = false;
485 module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/,
486 changed);
488 if (!changed && !module_sp->GetObjectFile())
489 return error_with_message("Couldn't set the load address for module.");
491 dict->GetValueForKeyAsString("path", value);
492 FileSpec objfile(value);
493 module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename());
495 return module_list.AppendIfNeeded(module_sp);
498 if (!loaded_images_sp->ForEach(reload_image))
499 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
500 LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);
502 target.ModulesDidLoad(module_list);
504 return loaded_images_sp;
507 lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() {
508 StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata();
510 Status error;
511 if (!metadata_sp || !metadata_sp->GetSize())
512 return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>(
513 LLVM_PRETTY_FUNCTION, "No metadata.", error);
515 return metadata_sp;
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);
529 ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
530 CheckScriptedInterface();
531 return *m_interface_up;
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;