1fe6060f1SDimitry Andric //===-- ScriptedProcess.cpp -----------------------------------------------===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric 9fe6060f1SDimitry Andric #include "ScriptedProcess.h" 10fe6060f1SDimitry Andric 11fe6060f1SDimitry Andric #include "lldb/Core/Debugger.h" 12fe6060f1SDimitry Andric #include "lldb/Core/Module.h" 13fe6060f1SDimitry Andric #include "lldb/Core/PluginManager.h" 14fe6060f1SDimitry Andric 15fe6060f1SDimitry Andric #include "lldb/Host/OptionParser.h" 16fe6060f1SDimitry Andric #include "lldb/Host/ThreadLauncher.h" 17fe6060f1SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 18fe6060f1SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h" 19fe6060f1SDimitry Andric #include "lldb/Interpreter/OptionGroupBoolean.h" 20fe6060f1SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h" 21*bdd1243dSDimitry Andric #include "lldb/Interpreter/ScriptedMetadata.h" 22fe6060f1SDimitry Andric #include "lldb/Target/MemoryRegionInfo.h" 23*bdd1243dSDimitry Andric #include "lldb/Target/Queue.h" 24fe6060f1SDimitry Andric #include "lldb/Target/RegisterContext.h" 2581ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 26fe6060f1SDimitry Andric #include "lldb/Utility/State.h" 27fe6060f1SDimitry Andric 28fe6060f1SDimitry Andric #include <mutex> 29fe6060f1SDimitry Andric 30fe6060f1SDimitry Andric LLDB_PLUGIN_DEFINE(ScriptedProcess) 31fe6060f1SDimitry Andric 32fe6060f1SDimitry Andric using namespace lldb; 33fe6060f1SDimitry Andric using namespace lldb_private; 34fe6060f1SDimitry Andric 35349cc55cSDimitry Andric llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() { 36fe6060f1SDimitry Andric return "Scripted Process plug-in."; 37fe6060f1SDimitry Andric } 38fe6060f1SDimitry Andric 39fe6060f1SDimitry Andric static constexpr lldb::ScriptLanguage g_supported_script_languages[] = { 40fe6060f1SDimitry Andric ScriptLanguage::eScriptLanguagePython, 41fe6060f1SDimitry Andric }; 42fe6060f1SDimitry Andric 43fe6060f1SDimitry Andric bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) { 44fe6060f1SDimitry Andric llvm::ArrayRef<lldb::ScriptLanguage> supported_languages = 45*bdd1243dSDimitry Andric llvm::ArrayRef(g_supported_script_languages); 46fe6060f1SDimitry Andric 47fe6060f1SDimitry Andric return llvm::is_contained(supported_languages, language); 48fe6060f1SDimitry Andric } 49fe6060f1SDimitry Andric 50fe6060f1SDimitry Andric void ScriptedProcess::CheckInterpreterAndScriptObject() const { 51fe6060f1SDimitry Andric lldbassert(m_interpreter && "Invalid Script Interpreter."); 52fe6060f1SDimitry Andric lldbassert(m_script_object_sp && "Invalid Script Object."); 53fe6060f1SDimitry Andric } 54fe6060f1SDimitry Andric 55fe6060f1SDimitry Andric lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp, 56fe6060f1SDimitry Andric lldb::ListenerSP listener_sp, 57fe6060f1SDimitry Andric const FileSpec *file, 58fe6060f1SDimitry Andric bool can_connect) { 59fe6060f1SDimitry Andric if (!target_sp || 60fe6060f1SDimitry Andric !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage())) 61fe6060f1SDimitry Andric return nullptr; 62fe6060f1SDimitry Andric 63*bdd1243dSDimitry Andric ScriptedMetadata scripted_metadata(target_sp->GetProcessLaunchInfo()); 64fe6060f1SDimitry Andric 65*bdd1243dSDimitry Andric Status error; 66*bdd1243dSDimitry Andric auto process_sp = std::shared_ptr<ScriptedProcess>( 67*bdd1243dSDimitry Andric new ScriptedProcess(target_sp, listener_sp, scripted_metadata, error)); 68fe6060f1SDimitry Andric 69fe6060f1SDimitry Andric if (error.Fail() || !process_sp || !process_sp->m_script_object_sp || 70fe6060f1SDimitry Andric !process_sp->m_script_object_sp->IsValid()) { 7181ad6265SDimitry Andric LLDB_LOGF(GetLog(LLDBLog::Process), "%s", error.AsCString()); 72fe6060f1SDimitry Andric return nullptr; 73fe6060f1SDimitry Andric } 74fe6060f1SDimitry Andric 75fe6060f1SDimitry Andric return process_sp; 76fe6060f1SDimitry Andric } 77fe6060f1SDimitry Andric 78fe6060f1SDimitry Andric bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp, 79fe6060f1SDimitry Andric bool plugin_specified_by_name) { 80fe6060f1SDimitry Andric return true; 81fe6060f1SDimitry Andric } 82fe6060f1SDimitry Andric 83*bdd1243dSDimitry Andric ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp, 84*bdd1243dSDimitry Andric lldb::ListenerSP listener_sp, 85*bdd1243dSDimitry Andric const ScriptedMetadata &scripted_metadata, 86fe6060f1SDimitry Andric Status &error) 87*bdd1243dSDimitry Andric : Process(target_sp, listener_sp), m_scripted_metadata(scripted_metadata) { 88fe6060f1SDimitry Andric 89fe6060f1SDimitry Andric if (!target_sp) { 90fe6060f1SDimitry Andric error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", 91fe6060f1SDimitry Andric __FUNCTION__, "Invalid target"); 92fe6060f1SDimitry Andric return; 93fe6060f1SDimitry Andric } 94fe6060f1SDimitry Andric 95fe6060f1SDimitry Andric m_interpreter = target_sp->GetDebugger().GetScriptInterpreter(); 96fe6060f1SDimitry Andric 97fe6060f1SDimitry Andric if (!m_interpreter) { 98fe6060f1SDimitry Andric error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", 99fe6060f1SDimitry Andric __FUNCTION__, 100fe6060f1SDimitry Andric "Debugger has no Script Interpreter"); 101fe6060f1SDimitry Andric return; 102fe6060f1SDimitry Andric } 103fe6060f1SDimitry Andric 104349cc55cSDimitry Andric ExecutionContext exe_ctx(target_sp, /*get_process=*/false); 105349cc55cSDimitry Andric 106349cc55cSDimitry Andric StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject( 107*bdd1243dSDimitry Andric m_scripted_metadata.GetClassName(), exe_ctx, 108*bdd1243dSDimitry Andric m_scripted_metadata.GetArgsSP()); 109fe6060f1SDimitry Andric 110fe6060f1SDimitry Andric if (!object_sp || !object_sp->IsValid()) { 111fe6060f1SDimitry Andric error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", 112fe6060f1SDimitry Andric __FUNCTION__, 113fe6060f1SDimitry Andric "Failed to create valid script object"); 114fe6060f1SDimitry Andric return; 115fe6060f1SDimitry Andric } 116fe6060f1SDimitry Andric 117fe6060f1SDimitry Andric m_script_object_sp = object_sp; 118fe6060f1SDimitry Andric } 119fe6060f1SDimitry Andric 120fe6060f1SDimitry Andric ScriptedProcess::~ScriptedProcess() { 121fe6060f1SDimitry Andric Clear(); 122fe6060f1SDimitry Andric // We need to call finalize on the process before destroying ourselves to 123fe6060f1SDimitry Andric // make sure all of the broadcaster cleanup goes as planned. If we destruct 124fe6060f1SDimitry Andric // this class, then Process::~Process() might have problems trying to fully 125fe6060f1SDimitry Andric // destroy the broadcaster. 126fe6060f1SDimitry Andric Finalize(); 127fe6060f1SDimitry Andric } 128fe6060f1SDimitry Andric 129fe6060f1SDimitry Andric void ScriptedProcess::Initialize() { 130fe6060f1SDimitry Andric static llvm::once_flag g_once_flag; 131fe6060f1SDimitry Andric 132fe6060f1SDimitry Andric llvm::call_once(g_once_flag, []() { 133fe6060f1SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 134fe6060f1SDimitry Andric GetPluginDescriptionStatic(), CreateInstance); 135fe6060f1SDimitry Andric }); 136fe6060f1SDimitry Andric } 137fe6060f1SDimitry Andric 138fe6060f1SDimitry Andric void ScriptedProcess::Terminate() { 139fe6060f1SDimitry Andric PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance); 140fe6060f1SDimitry Andric } 141fe6060f1SDimitry Andric 142fe6060f1SDimitry Andric Status ScriptedProcess::DoLoadCore() { 143fe6060f1SDimitry Andric ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo(); 144fe6060f1SDimitry Andric 145fe6060f1SDimitry Andric return DoLaunch(nullptr, launch_info); 146fe6060f1SDimitry Andric } 147fe6060f1SDimitry Andric 148fe6060f1SDimitry Andric Status ScriptedProcess::DoLaunch(Module *exe_module, 149fe6060f1SDimitry Andric ProcessLaunchInfo &launch_info) { 150fe6060f1SDimitry Andric CheckInterpreterAndScriptObject(); 151fe6060f1SDimitry Andric 152fe6060f1SDimitry Andric /* FIXME: This doesn't reflect how lldb actually launches a process. 153fe6060f1SDimitry Andric In reality, it attaches to debugserver, then resume the process. */ 154fe6060f1SDimitry Andric Status error = GetInterface().Launch(); 155fe6060f1SDimitry Andric SetPrivateState(eStateRunning); 156fe6060f1SDimitry Andric 157fe6060f1SDimitry Andric if (error.Fail()) 158fe6060f1SDimitry Andric return error; 159fe6060f1SDimitry Andric 160fe6060f1SDimitry Andric // TODO: Fetch next state from stopped event queue then send stop event 161fe6060f1SDimitry Andric // const StateType state = SetThreadStopInfo(response); 162fe6060f1SDimitry Andric // if (state != eStateInvalid) { 163fe6060f1SDimitry Andric // SetPrivateState(state); 164fe6060f1SDimitry Andric 165fe6060f1SDimitry Andric SetPrivateState(eStateStopped); 166fe6060f1SDimitry Andric 167fe6060f1SDimitry Andric return {}; 168fe6060f1SDimitry Andric } 169fe6060f1SDimitry Andric 170fe6060f1SDimitry Andric void ScriptedProcess::DidLaunch() { 171fe6060f1SDimitry Andric CheckInterpreterAndScriptObject(); 172fe6060f1SDimitry Andric m_pid = GetInterface().GetProcessID(); 17381ad6265SDimitry Andric GetLoadedDynamicLibrariesInfos(); 174fe6060f1SDimitry Andric } 175fe6060f1SDimitry Andric 176fe6060f1SDimitry Andric Status ScriptedProcess::DoResume() { 177fe6060f1SDimitry Andric CheckInterpreterAndScriptObject(); 178fe6060f1SDimitry Andric 17981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 180fe6060f1SDimitry Andric // FIXME: Fetch data from thread. 181fe6060f1SDimitry Andric const StateType thread_resume_state = eStateRunning; 182fe6060f1SDimitry Andric LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__, 183fe6060f1SDimitry Andric StateAsCString(thread_resume_state)); 184fe6060f1SDimitry Andric 185fe6060f1SDimitry Andric bool resume = (thread_resume_state == eStateRunning); 186fe6060f1SDimitry Andric assert(thread_resume_state == eStateRunning && "invalid thread resume state"); 187fe6060f1SDimitry Andric 188fe6060f1SDimitry Andric Status error; 189fe6060f1SDimitry Andric if (resume) { 190fe6060f1SDimitry Andric LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__); 191fe6060f1SDimitry Andric 192fe6060f1SDimitry Andric SetPrivateState(eStateRunning); 193fe6060f1SDimitry Andric SetPrivateState(eStateStopped); 194fe6060f1SDimitry Andric error = GetInterface().Resume(); 195fe6060f1SDimitry Andric } 196fe6060f1SDimitry Andric 197fe6060f1SDimitry Andric return error; 198fe6060f1SDimitry Andric } 199fe6060f1SDimitry Andric 200fe6060f1SDimitry Andric Status ScriptedProcess::DoStop() { 201fe6060f1SDimitry Andric CheckInterpreterAndScriptObject(); 202fe6060f1SDimitry Andric 20381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 204fe6060f1SDimitry Andric 205fe6060f1SDimitry Andric if (GetInterface().ShouldStop()) { 206fe6060f1SDimitry Andric SetPrivateState(eStateStopped); 207fe6060f1SDimitry Andric LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__); 208fe6060f1SDimitry Andric return {}; 209fe6060f1SDimitry Andric } 210fe6060f1SDimitry Andric 211fe6060f1SDimitry Andric LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__); 212fe6060f1SDimitry Andric return GetInterface().Stop(); 213fe6060f1SDimitry Andric } 214fe6060f1SDimitry Andric 215fe6060f1SDimitry Andric Status ScriptedProcess::DoDestroy() { return Status(); } 216fe6060f1SDimitry Andric 217fe6060f1SDimitry Andric bool ScriptedProcess::IsAlive() { 218fe6060f1SDimitry Andric if (m_interpreter && m_script_object_sp) 219fe6060f1SDimitry Andric return GetInterface().IsAlive(); 220fe6060f1SDimitry Andric return false; 221fe6060f1SDimitry Andric } 222fe6060f1SDimitry Andric 223fe6060f1SDimitry Andric size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, 224fe6060f1SDimitry Andric Status &error) { 225fe6060f1SDimitry Andric if (!m_interpreter) 22604eeddc0SDimitry Andric return ScriptedInterface::ErrorWithMessage<size_t>( 22704eeddc0SDimitry Andric LLVM_PRETTY_FUNCTION, "No interpreter.", error); 228fe6060f1SDimitry Andric 229fe6060f1SDimitry Andric lldb::DataExtractorSP data_extractor_sp = 230fe6060f1SDimitry Andric GetInterface().ReadMemoryAtAddress(addr, size, error); 231fe6060f1SDimitry Andric 232349cc55cSDimitry Andric if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail()) 233fe6060f1SDimitry Andric return 0; 234fe6060f1SDimitry Andric 235fe6060f1SDimitry Andric offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData( 236fe6060f1SDimitry Andric 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder()); 237fe6060f1SDimitry Andric 238fe6060f1SDimitry Andric if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET) 23904eeddc0SDimitry Andric return ScriptedInterface::ErrorWithMessage<size_t>( 240349cc55cSDimitry Andric LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error); 241fe6060f1SDimitry Andric 242fe6060f1SDimitry Andric return size; 243fe6060f1SDimitry Andric } 244fe6060f1SDimitry Andric 245fe6060f1SDimitry Andric ArchSpec ScriptedProcess::GetArchitecture() { 246fe6060f1SDimitry Andric return GetTarget().GetArchitecture(); 247fe6060f1SDimitry Andric } 248fe6060f1SDimitry Andric 249d56accc7SDimitry Andric Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr, 250fe6060f1SDimitry Andric MemoryRegionInfo ®ion) { 251349cc55cSDimitry Andric CheckInterpreterAndScriptObject(); 252349cc55cSDimitry Andric 253349cc55cSDimitry Andric Status error; 254349cc55cSDimitry Andric if (auto region_or_err = 255349cc55cSDimitry Andric GetInterface().GetMemoryRegionContainingAddress(load_addr, error)) 256349cc55cSDimitry Andric region = *region_or_err; 257349cc55cSDimitry Andric 258349cc55cSDimitry Andric return error; 259fe6060f1SDimitry Andric } 260fe6060f1SDimitry Andric 261fe6060f1SDimitry Andric Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) { 262fe6060f1SDimitry Andric CheckInterpreterAndScriptObject(); 263fe6060f1SDimitry Andric 264349cc55cSDimitry Andric Status error; 265fe6060f1SDimitry Andric lldb::addr_t address = 0; 266fe6060f1SDimitry Andric 267349cc55cSDimitry Andric while (auto region_or_err = 268349cc55cSDimitry Andric GetInterface().GetMemoryRegionContainingAddress(address, error)) { 269349cc55cSDimitry Andric if (error.Fail()) 270349cc55cSDimitry Andric break; 271349cc55cSDimitry Andric 272349cc55cSDimitry Andric MemoryRegionInfo &mem_region = *region_or_err; 273349cc55cSDimitry Andric auto range = mem_region.GetRange(); 274fe6060f1SDimitry Andric address += range.GetRangeBase() + range.GetByteSize(); 275349cc55cSDimitry Andric region_list.push_back(mem_region); 276fe6060f1SDimitry Andric } 277fe6060f1SDimitry Andric 278349cc55cSDimitry Andric return error; 279fe6060f1SDimitry Andric } 280fe6060f1SDimitry Andric 281fe6060f1SDimitry Andric void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); } 282fe6060f1SDimitry Andric 283fe6060f1SDimitry Andric bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list, 284fe6060f1SDimitry Andric ThreadList &new_thread_list) { 285fe6060f1SDimitry Andric // TODO: Implement 286fe6060f1SDimitry Andric // This is supposed to get the current set of threads, if any of them are in 287fe6060f1SDimitry Andric // old_thread_list then they get copied to new_thread_list, and then any 288fe6060f1SDimitry Andric // actually new threads will get added to new_thread_list. 289349cc55cSDimitry Andric 290349cc55cSDimitry Andric CheckInterpreterAndScriptObject(); 291349cc55cSDimitry Andric m_thread_plans.ClearThreadCache(); 292349cc55cSDimitry Andric 293349cc55cSDimitry Andric Status error; 294349cc55cSDimitry Andric ScriptLanguage language = m_interpreter->GetLanguage(); 295349cc55cSDimitry Andric 296349cc55cSDimitry Andric if (language != eScriptLanguagePython) 29704eeddc0SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>( 298349cc55cSDimitry Andric LLVM_PRETTY_FUNCTION, 299349cc55cSDimitry Andric llvm::Twine("ScriptInterpreter language (" + 300349cc55cSDimitry Andric llvm::Twine(m_interpreter->LanguageToString(language)) + 301349cc55cSDimitry Andric llvm::Twine(") not supported.")) 302349cc55cSDimitry Andric .str(), 303349cc55cSDimitry Andric error); 304349cc55cSDimitry Andric 30504eeddc0SDimitry Andric StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo(); 306349cc55cSDimitry Andric 30704eeddc0SDimitry Andric if (!thread_info_sp) 30804eeddc0SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>( 30904eeddc0SDimitry Andric LLVM_PRETTY_FUNCTION, 31004eeddc0SDimitry Andric "Couldn't fetch thread list from Scripted Process.", error); 31104eeddc0SDimitry Andric 31281ad6265SDimitry Andric // Because `StructuredData::Dictionary` uses a `std::map<ConstString, 31381ad6265SDimitry Andric // ObjectSP>` for storage, each item is sorted based on the key alphabetical 31481ad6265SDimitry Andric // order. Since `GetThreadsInfo` provides thread indices as the key element, 31581ad6265SDimitry Andric // thread info comes ordered alphabetically, instead of numerically, so we 31681ad6265SDimitry Andric // need to sort the thread indices before creating thread. 31781ad6265SDimitry Andric 31881ad6265SDimitry Andric StructuredData::ArraySP keys = thread_info_sp->GetKeys(); 31981ad6265SDimitry Andric 32081ad6265SDimitry Andric std::map<size_t, StructuredData::ObjectSP> sorted_threads; 32181ad6265SDimitry Andric auto sort_keys = [&sorted_threads, 32281ad6265SDimitry Andric &thread_info_sp](StructuredData::Object *item) -> bool { 32381ad6265SDimitry Andric if (!item) 32481ad6265SDimitry Andric return false; 32581ad6265SDimitry Andric 32681ad6265SDimitry Andric llvm::StringRef key = item->GetStringValue(); 32781ad6265SDimitry Andric size_t idx = 0; 32881ad6265SDimitry Andric 32981ad6265SDimitry Andric // Make sure the provided index is actually an integer 33081ad6265SDimitry Andric if (!llvm::to_integer(key, idx)) 33181ad6265SDimitry Andric return false; 33281ad6265SDimitry Andric 33381ad6265SDimitry Andric sorted_threads[idx] = thread_info_sp->GetValueForKey(key); 33481ad6265SDimitry Andric return true; 33581ad6265SDimitry Andric }; 33681ad6265SDimitry Andric 33781ad6265SDimitry Andric size_t thread_count = thread_info_sp->GetSize(); 33881ad6265SDimitry Andric 33981ad6265SDimitry Andric if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count) 34081ad6265SDimitry Andric // Might be worth showing the unsorted thread list instead of return early. 34181ad6265SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>( 34281ad6265SDimitry Andric LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error); 34381ad6265SDimitry Andric 34404eeddc0SDimitry Andric auto create_scripted_thread = 34581ad6265SDimitry Andric [this, &error, &new_thread_list]( 34681ad6265SDimitry Andric const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool { 34781ad6265SDimitry Andric size_t idx = pair.first; 34881ad6265SDimitry Andric StructuredData::ObjectSP object_sp = pair.second; 34981ad6265SDimitry Andric 35081ad6265SDimitry Andric if (!object_sp) 35104eeddc0SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>( 35204eeddc0SDimitry Andric LLVM_PRETTY_FUNCTION, "Invalid thread info object", error); 35304eeddc0SDimitry Andric 35481ad6265SDimitry Andric auto thread_or_error = 35581ad6265SDimitry Andric ScriptedThread::Create(*this, object_sp->GetAsGeneric()); 35604eeddc0SDimitry Andric 35704eeddc0SDimitry Andric if (!thread_or_error) 35804eeddc0SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>( 35904eeddc0SDimitry Andric LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error); 36004eeddc0SDimitry Andric 36104eeddc0SDimitry Andric ThreadSP thread_sp = thread_or_error.get(); 36204eeddc0SDimitry Andric lldbassert(thread_sp && "Couldn't initialize scripted thread."); 363349cc55cSDimitry Andric 3640eae32dcSDimitry Andric RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); 3650eae32dcSDimitry Andric if (!reg_ctx_sp) 36604eeddc0SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>( 36704eeddc0SDimitry Andric LLVM_PRETTY_FUNCTION, 36881ad6265SDimitry Andric llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx)) 36904eeddc0SDimitry Andric .str(), 37004eeddc0SDimitry Andric error); 3710eae32dcSDimitry Andric 372349cc55cSDimitry Andric new_thread_list.AddThread(thread_sp); 373349cc55cSDimitry Andric 37404eeddc0SDimitry Andric return true; 37504eeddc0SDimitry Andric }; 37604eeddc0SDimitry Andric 37781ad6265SDimitry Andric llvm::for_each(sorted_threads, create_scripted_thread); 37804eeddc0SDimitry Andric 379fe6060f1SDimitry Andric return new_thread_list.GetSize(false) > 0; 380fe6060f1SDimitry Andric } 381fe6060f1SDimitry Andric 382349cc55cSDimitry Andric void ScriptedProcess::RefreshStateAfterStop() { 383349cc55cSDimitry Andric // Let all threads recover from stopping and do any clean up based on the 384349cc55cSDimitry Andric // previous thread state (if any). 38581ad6265SDimitry Andric m_thread_list.RefreshStateAfterStop(); 386349cc55cSDimitry Andric } 387349cc55cSDimitry Andric 388fe6060f1SDimitry Andric bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) { 389fe6060f1SDimitry Andric info.Clear(); 390fe6060f1SDimitry Andric info.SetProcessID(GetID()); 391fe6060f1SDimitry Andric info.SetArchitecture(GetArchitecture()); 392fe6060f1SDimitry Andric lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 393fe6060f1SDimitry Andric if (module_sp) { 394fe6060f1SDimitry Andric const bool add_exe_file_as_first_arg = false; 395fe6060f1SDimitry Andric info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 396fe6060f1SDimitry Andric add_exe_file_as_first_arg); 397fe6060f1SDimitry Andric } 398fe6060f1SDimitry Andric return true; 399fe6060f1SDimitry Andric } 400fe6060f1SDimitry Andric 40181ad6265SDimitry Andric lldb_private::StructuredData::ObjectSP 40281ad6265SDimitry Andric ScriptedProcess::GetLoadedDynamicLibrariesInfos() { 40381ad6265SDimitry Andric CheckInterpreterAndScriptObject(); 40481ad6265SDimitry Andric 40581ad6265SDimitry Andric Status error; 40681ad6265SDimitry Andric auto error_with_message = [&error](llvm::StringRef message) { 40781ad6265SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION, 40881ad6265SDimitry Andric message.data(), error); 40981ad6265SDimitry Andric }; 41081ad6265SDimitry Andric 41181ad6265SDimitry Andric StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages(); 41281ad6265SDimitry Andric 41381ad6265SDimitry Andric if (!loaded_images_sp || !loaded_images_sp->GetSize()) 414*bdd1243dSDimitry Andric return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( 41581ad6265SDimitry Andric LLVM_PRETTY_FUNCTION, "No loaded images.", error); 41681ad6265SDimitry Andric 41781ad6265SDimitry Andric ModuleList module_list; 41881ad6265SDimitry Andric Target &target = GetTarget(); 41981ad6265SDimitry Andric 42081ad6265SDimitry Andric auto reload_image = [&target, &module_list, &error_with_message]( 42181ad6265SDimitry Andric StructuredData::Object *obj) -> bool { 42281ad6265SDimitry Andric StructuredData::Dictionary *dict = obj->GetAsDictionary(); 42381ad6265SDimitry Andric 42481ad6265SDimitry Andric if (!dict) 42581ad6265SDimitry Andric return error_with_message("Couldn't cast image object into dictionary."); 42681ad6265SDimitry Andric 42781ad6265SDimitry Andric ModuleSpec module_spec; 42881ad6265SDimitry Andric llvm::StringRef value; 42981ad6265SDimitry Andric 43081ad6265SDimitry Andric bool has_path = dict->HasKey("path"); 43181ad6265SDimitry Andric bool has_uuid = dict->HasKey("uuid"); 43281ad6265SDimitry Andric if (!has_path && !has_uuid) 43381ad6265SDimitry Andric return error_with_message("Dictionary should have key 'path' or 'uuid'"); 43481ad6265SDimitry Andric if (!dict->HasKey("load_addr")) 43581ad6265SDimitry Andric return error_with_message("Dictionary is missing key 'load_addr'"); 43681ad6265SDimitry Andric 43781ad6265SDimitry Andric if (has_path) { 43881ad6265SDimitry Andric dict->GetValueForKeyAsString("path", value); 43981ad6265SDimitry Andric module_spec.GetFileSpec().SetPath(value); 44081ad6265SDimitry Andric } 44181ad6265SDimitry Andric 44281ad6265SDimitry Andric if (has_uuid) { 44381ad6265SDimitry Andric dict->GetValueForKeyAsString("uuid", value); 44481ad6265SDimitry Andric module_spec.GetUUID().SetFromStringRef(value); 44581ad6265SDimitry Andric } 44681ad6265SDimitry Andric module_spec.GetArchitecture() = target.GetArchitecture(); 44781ad6265SDimitry Andric 44881ad6265SDimitry Andric ModuleSP module_sp = 44981ad6265SDimitry Andric target.GetOrCreateModule(module_spec, true /* notify */); 45081ad6265SDimitry Andric 45181ad6265SDimitry Andric if (!module_sp) 45281ad6265SDimitry Andric return error_with_message("Couldn't create or get module."); 45381ad6265SDimitry Andric 45481ad6265SDimitry Andric lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 45581ad6265SDimitry Andric lldb::addr_t slide = LLDB_INVALID_OFFSET; 45681ad6265SDimitry Andric dict->GetValueForKeyAsInteger("load_addr", load_addr); 45781ad6265SDimitry Andric dict->GetValueForKeyAsInteger("slide", slide); 45881ad6265SDimitry Andric if (load_addr == LLDB_INVALID_ADDRESS) 45981ad6265SDimitry Andric return error_with_message( 46081ad6265SDimitry Andric "Couldn't get valid load address or slide offset."); 46181ad6265SDimitry Andric 46281ad6265SDimitry Andric if (slide != LLDB_INVALID_OFFSET) 46381ad6265SDimitry Andric load_addr += slide; 46481ad6265SDimitry Andric 46581ad6265SDimitry Andric bool changed = false; 46681ad6265SDimitry Andric module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/, 46781ad6265SDimitry Andric changed); 46881ad6265SDimitry Andric 46981ad6265SDimitry Andric if (!changed && !module_sp->GetObjectFile()) 47081ad6265SDimitry Andric return error_with_message("Couldn't set the load address for module."); 47181ad6265SDimitry Andric 47281ad6265SDimitry Andric dict->GetValueForKeyAsString("path", value); 47381ad6265SDimitry Andric FileSpec objfile(value); 47481ad6265SDimitry Andric module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename()); 47581ad6265SDimitry Andric 47681ad6265SDimitry Andric return module_list.AppendIfNeeded(module_sp); 47781ad6265SDimitry Andric }; 47881ad6265SDimitry Andric 47981ad6265SDimitry Andric if (!loaded_images_sp->ForEach(reload_image)) 480*bdd1243dSDimitry Andric return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( 48181ad6265SDimitry Andric LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error); 48281ad6265SDimitry Andric 48381ad6265SDimitry Andric target.ModulesDidLoad(module_list); 48481ad6265SDimitry Andric 48581ad6265SDimitry Andric return loaded_images_sp; 48681ad6265SDimitry Andric } 48781ad6265SDimitry Andric 488*bdd1243dSDimitry Andric lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() { 489*bdd1243dSDimitry Andric CheckInterpreterAndScriptObject(); 490*bdd1243dSDimitry Andric 491*bdd1243dSDimitry Andric StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata(); 492*bdd1243dSDimitry Andric 493*bdd1243dSDimitry Andric Status error; 494*bdd1243dSDimitry Andric if (!metadata_sp || !metadata_sp->GetSize()) 495*bdd1243dSDimitry Andric return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>( 496*bdd1243dSDimitry Andric LLVM_PRETTY_FUNCTION, "No metadata.", error); 497*bdd1243dSDimitry Andric 498*bdd1243dSDimitry Andric return metadata_sp; 499*bdd1243dSDimitry Andric } 500*bdd1243dSDimitry Andric 501*bdd1243dSDimitry Andric void ScriptedProcess::UpdateQueueListIfNeeded() { 502*bdd1243dSDimitry Andric CheckInterpreterAndScriptObject(); 503*bdd1243dSDimitry Andric for (ThreadSP thread_sp : Threads()) { 504*bdd1243dSDimitry Andric if (const char *queue_name = thread_sp->GetQueueName()) { 505*bdd1243dSDimitry Andric QueueSP queue_sp = std::make_shared<Queue>( 506*bdd1243dSDimitry Andric m_process->shared_from_this(), thread_sp->GetQueueID(), queue_name); 507*bdd1243dSDimitry Andric m_queue_list.AddQueue(queue_sp); 508*bdd1243dSDimitry Andric } 509*bdd1243dSDimitry Andric } 510*bdd1243dSDimitry Andric } 511*bdd1243dSDimitry Andric 512fe6060f1SDimitry Andric ScriptedProcessInterface &ScriptedProcess::GetInterface() const { 513fe6060f1SDimitry Andric return m_interpreter->GetScriptedProcessInterface(); 514fe6060f1SDimitry Andric } 515