1*be691f3bSpatrick //===-- ScriptedProcess.cpp -----------------------------------------------===// 2*be691f3bSpatrick // 3*be691f3bSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*be691f3bSpatrick // See https://llvm.org/LICENSE.txt for license information. 5*be691f3bSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*be691f3bSpatrick // 7*be691f3bSpatrick //===----------------------------------------------------------------------===// 8*be691f3bSpatrick 9*be691f3bSpatrick #include "ScriptedProcess.h" 10*be691f3bSpatrick 11*be691f3bSpatrick #include "lldb/Core/Debugger.h" 12*be691f3bSpatrick #include "lldb/Core/Module.h" 13*be691f3bSpatrick #include "lldb/Core/PluginManager.h" 14*be691f3bSpatrick 15*be691f3bSpatrick #include "lldb/Host/OptionParser.h" 16*be691f3bSpatrick #include "lldb/Host/ThreadLauncher.h" 17*be691f3bSpatrick #include "lldb/Interpreter/CommandInterpreter.h" 18*be691f3bSpatrick #include "lldb/Interpreter/OptionArgParser.h" 19*be691f3bSpatrick #include "lldb/Interpreter/OptionGroupBoolean.h" 20*be691f3bSpatrick #include "lldb/Interpreter/ScriptInterpreter.h" 21*be691f3bSpatrick #include "lldb/Target/MemoryRegionInfo.h" 22*be691f3bSpatrick #include "lldb/Target/RegisterContext.h" 23*be691f3bSpatrick 24*be691f3bSpatrick #include "lldb/Utility/Log.h" 25*be691f3bSpatrick #include "lldb/Utility/Logging.h" 26*be691f3bSpatrick #include "lldb/Utility/State.h" 27*be691f3bSpatrick 28*be691f3bSpatrick #include <mutex> 29*be691f3bSpatrick 30*be691f3bSpatrick LLDB_PLUGIN_DEFINE(ScriptedProcess) 31*be691f3bSpatrick 32*be691f3bSpatrick using namespace lldb; 33*be691f3bSpatrick using namespace lldb_private; 34*be691f3bSpatrick 35*be691f3bSpatrick ConstString ScriptedProcess::GetPluginNameStatic() { 36*be691f3bSpatrick static ConstString g_name("ScriptedProcess"); 37*be691f3bSpatrick return g_name; 38*be691f3bSpatrick } 39*be691f3bSpatrick 40*be691f3bSpatrick const char *ScriptedProcess::GetPluginDescriptionStatic() { 41*be691f3bSpatrick return "Scripted Process plug-in."; 42*be691f3bSpatrick } 43*be691f3bSpatrick 44*be691f3bSpatrick static constexpr lldb::ScriptLanguage g_supported_script_languages[] = { 45*be691f3bSpatrick ScriptLanguage::eScriptLanguagePython, 46*be691f3bSpatrick }; 47*be691f3bSpatrick 48*be691f3bSpatrick bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) { 49*be691f3bSpatrick llvm::ArrayRef<lldb::ScriptLanguage> supported_languages = 50*be691f3bSpatrick llvm::makeArrayRef(g_supported_script_languages); 51*be691f3bSpatrick 52*be691f3bSpatrick return llvm::is_contained(supported_languages, language); 53*be691f3bSpatrick } 54*be691f3bSpatrick 55*be691f3bSpatrick void ScriptedProcess::CheckInterpreterAndScriptObject() const { 56*be691f3bSpatrick lldbassert(m_interpreter && "Invalid Script Interpreter."); 57*be691f3bSpatrick lldbassert(m_script_object_sp && "Invalid Script Object."); 58*be691f3bSpatrick } 59*be691f3bSpatrick 60*be691f3bSpatrick lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp, 61*be691f3bSpatrick lldb::ListenerSP listener_sp, 62*be691f3bSpatrick const FileSpec *file, 63*be691f3bSpatrick bool can_connect) { 64*be691f3bSpatrick if (!target_sp || 65*be691f3bSpatrick !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage())) 66*be691f3bSpatrick return nullptr; 67*be691f3bSpatrick 68*be691f3bSpatrick Status error; 69*be691f3bSpatrick ScriptedProcess::ScriptedProcessInfo scripted_process_info( 70*be691f3bSpatrick target_sp->GetProcessLaunchInfo()); 71*be691f3bSpatrick 72*be691f3bSpatrick auto process_sp = std::make_shared<ScriptedProcess>( 73*be691f3bSpatrick target_sp, listener_sp, scripted_process_info, error); 74*be691f3bSpatrick 75*be691f3bSpatrick if (error.Fail() || !process_sp || !process_sp->m_script_object_sp || 76*be691f3bSpatrick !process_sp->m_script_object_sp->IsValid()) { 77*be691f3bSpatrick LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS), "%s", 78*be691f3bSpatrick error.AsCString()); 79*be691f3bSpatrick return nullptr; 80*be691f3bSpatrick } 81*be691f3bSpatrick 82*be691f3bSpatrick return process_sp; 83*be691f3bSpatrick } 84*be691f3bSpatrick 85*be691f3bSpatrick bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp, 86*be691f3bSpatrick bool plugin_specified_by_name) { 87*be691f3bSpatrick return true; 88*be691f3bSpatrick } 89*be691f3bSpatrick 90*be691f3bSpatrick ScriptedProcess::ScriptedProcess( 91*be691f3bSpatrick lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, 92*be691f3bSpatrick const ScriptedProcess::ScriptedProcessInfo &scripted_process_info, 93*be691f3bSpatrick Status &error) 94*be691f3bSpatrick : Process(target_sp, listener_sp), 95*be691f3bSpatrick m_scripted_process_info(scripted_process_info) { 96*be691f3bSpatrick 97*be691f3bSpatrick if (!target_sp) { 98*be691f3bSpatrick error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", 99*be691f3bSpatrick __FUNCTION__, "Invalid target"); 100*be691f3bSpatrick return; 101*be691f3bSpatrick } 102*be691f3bSpatrick 103*be691f3bSpatrick m_interpreter = target_sp->GetDebugger().GetScriptInterpreter(); 104*be691f3bSpatrick 105*be691f3bSpatrick if (!m_interpreter) { 106*be691f3bSpatrick error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", 107*be691f3bSpatrick __FUNCTION__, 108*be691f3bSpatrick "Debugger has no Script Interpreter"); 109*be691f3bSpatrick return; 110*be691f3bSpatrick } 111*be691f3bSpatrick 112*be691f3bSpatrick StructuredData::ObjectSP object_sp = GetInterface().CreatePluginObject( 113*be691f3bSpatrick m_scripted_process_info.GetClassName().c_str(), target_sp, 114*be691f3bSpatrick m_scripted_process_info.GetDictionarySP()); 115*be691f3bSpatrick 116*be691f3bSpatrick if (!object_sp || !object_sp->IsValid()) { 117*be691f3bSpatrick error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", 118*be691f3bSpatrick __FUNCTION__, 119*be691f3bSpatrick "Failed to create valid script object"); 120*be691f3bSpatrick return; 121*be691f3bSpatrick } 122*be691f3bSpatrick 123*be691f3bSpatrick m_script_object_sp = object_sp; 124*be691f3bSpatrick } 125*be691f3bSpatrick 126*be691f3bSpatrick ScriptedProcess::~ScriptedProcess() { 127*be691f3bSpatrick Clear(); 128*be691f3bSpatrick // We need to call finalize on the process before destroying ourselves to 129*be691f3bSpatrick // make sure all of the broadcaster cleanup goes as planned. If we destruct 130*be691f3bSpatrick // this class, then Process::~Process() might have problems trying to fully 131*be691f3bSpatrick // destroy the broadcaster. 132*be691f3bSpatrick Finalize(); 133*be691f3bSpatrick } 134*be691f3bSpatrick 135*be691f3bSpatrick void ScriptedProcess::Initialize() { 136*be691f3bSpatrick static llvm::once_flag g_once_flag; 137*be691f3bSpatrick 138*be691f3bSpatrick llvm::call_once(g_once_flag, []() { 139*be691f3bSpatrick PluginManager::RegisterPlugin(GetPluginNameStatic(), 140*be691f3bSpatrick GetPluginDescriptionStatic(), CreateInstance); 141*be691f3bSpatrick }); 142*be691f3bSpatrick } 143*be691f3bSpatrick 144*be691f3bSpatrick void ScriptedProcess::Terminate() { 145*be691f3bSpatrick PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance); 146*be691f3bSpatrick } 147*be691f3bSpatrick 148*be691f3bSpatrick ConstString ScriptedProcess::GetPluginName() { return GetPluginNameStatic(); } 149*be691f3bSpatrick 150*be691f3bSpatrick uint32_t ScriptedProcess::GetPluginVersion() { return 1; } 151*be691f3bSpatrick 152*be691f3bSpatrick Status ScriptedProcess::DoLoadCore() { 153*be691f3bSpatrick ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo(); 154*be691f3bSpatrick 155*be691f3bSpatrick return DoLaunch(nullptr, launch_info); 156*be691f3bSpatrick } 157*be691f3bSpatrick 158*be691f3bSpatrick Status ScriptedProcess::DoLaunch(Module *exe_module, 159*be691f3bSpatrick ProcessLaunchInfo &launch_info) { 160*be691f3bSpatrick CheckInterpreterAndScriptObject(); 161*be691f3bSpatrick 162*be691f3bSpatrick /* FIXME: This doesn't reflect how lldb actually launches a process. 163*be691f3bSpatrick In reality, it attaches to debugserver, then resume the process. */ 164*be691f3bSpatrick Status error = GetInterface().Launch(); 165*be691f3bSpatrick SetPrivateState(eStateRunning); 166*be691f3bSpatrick 167*be691f3bSpatrick if (error.Fail()) 168*be691f3bSpatrick return error; 169*be691f3bSpatrick 170*be691f3bSpatrick // TODO: Fetch next state from stopped event queue then send stop event 171*be691f3bSpatrick // const StateType state = SetThreadStopInfo(response); 172*be691f3bSpatrick // if (state != eStateInvalid) { 173*be691f3bSpatrick // SetPrivateState(state); 174*be691f3bSpatrick 175*be691f3bSpatrick SetPrivateState(eStateStopped); 176*be691f3bSpatrick 177*be691f3bSpatrick UpdateThreadListIfNeeded(); 178*be691f3bSpatrick GetThreadList(); 179*be691f3bSpatrick 180*be691f3bSpatrick return {}; 181*be691f3bSpatrick } 182*be691f3bSpatrick 183*be691f3bSpatrick void ScriptedProcess::DidLaunch() { 184*be691f3bSpatrick CheckInterpreterAndScriptObject(); 185*be691f3bSpatrick m_pid = GetInterface().GetProcessID(); 186*be691f3bSpatrick } 187*be691f3bSpatrick 188*be691f3bSpatrick Status ScriptedProcess::DoResume() { 189*be691f3bSpatrick CheckInterpreterAndScriptObject(); 190*be691f3bSpatrick 191*be691f3bSpatrick Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 192*be691f3bSpatrick // FIXME: Fetch data from thread. 193*be691f3bSpatrick const StateType thread_resume_state = eStateRunning; 194*be691f3bSpatrick LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__, 195*be691f3bSpatrick StateAsCString(thread_resume_state)); 196*be691f3bSpatrick 197*be691f3bSpatrick bool resume = (thread_resume_state == eStateRunning); 198*be691f3bSpatrick assert(thread_resume_state == eStateRunning && "invalid thread resume state"); 199*be691f3bSpatrick 200*be691f3bSpatrick Status error; 201*be691f3bSpatrick if (resume) { 202*be691f3bSpatrick LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__); 203*be691f3bSpatrick 204*be691f3bSpatrick SetPrivateState(eStateRunning); 205*be691f3bSpatrick SetPrivateState(eStateStopped); 206*be691f3bSpatrick error = GetInterface().Resume(); 207*be691f3bSpatrick } 208*be691f3bSpatrick 209*be691f3bSpatrick return error; 210*be691f3bSpatrick } 211*be691f3bSpatrick 212*be691f3bSpatrick Status ScriptedProcess::DoStop() { 213*be691f3bSpatrick CheckInterpreterAndScriptObject(); 214*be691f3bSpatrick 215*be691f3bSpatrick Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 216*be691f3bSpatrick 217*be691f3bSpatrick if (GetInterface().ShouldStop()) { 218*be691f3bSpatrick SetPrivateState(eStateStopped); 219*be691f3bSpatrick LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__); 220*be691f3bSpatrick return {}; 221*be691f3bSpatrick } 222*be691f3bSpatrick 223*be691f3bSpatrick LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__); 224*be691f3bSpatrick return GetInterface().Stop(); 225*be691f3bSpatrick } 226*be691f3bSpatrick 227*be691f3bSpatrick Status ScriptedProcess::DoDestroy() { return Status(); } 228*be691f3bSpatrick 229*be691f3bSpatrick bool ScriptedProcess::IsAlive() { 230*be691f3bSpatrick if (m_interpreter && m_script_object_sp) 231*be691f3bSpatrick return GetInterface().IsAlive(); 232*be691f3bSpatrick return false; 233*be691f3bSpatrick } 234*be691f3bSpatrick 235*be691f3bSpatrick size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, 236*be691f3bSpatrick Status &error) { 237*be691f3bSpatrick 238*be691f3bSpatrick auto error_with_message = [&error](llvm::StringRef message) { 239*be691f3bSpatrick error.SetErrorString(message); 240*be691f3bSpatrick return 0; 241*be691f3bSpatrick }; 242*be691f3bSpatrick 243*be691f3bSpatrick if (!m_interpreter) 244*be691f3bSpatrick return error_with_message("No interpreter."); 245*be691f3bSpatrick 246*be691f3bSpatrick lldb::DataExtractorSP data_extractor_sp = 247*be691f3bSpatrick GetInterface().ReadMemoryAtAddress(addr, size, error); 248*be691f3bSpatrick 249*be691f3bSpatrick if (!data_extractor_sp || error.Fail()) 250*be691f3bSpatrick return 0; 251*be691f3bSpatrick 252*be691f3bSpatrick offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData( 253*be691f3bSpatrick 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder()); 254*be691f3bSpatrick 255*be691f3bSpatrick if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET) 256*be691f3bSpatrick return error_with_message("Failed to copy read memory to buffer."); 257*be691f3bSpatrick 258*be691f3bSpatrick return size; 259*be691f3bSpatrick } 260*be691f3bSpatrick 261*be691f3bSpatrick ArchSpec ScriptedProcess::GetArchitecture() { 262*be691f3bSpatrick return GetTarget().GetArchitecture(); 263*be691f3bSpatrick } 264*be691f3bSpatrick 265*be691f3bSpatrick Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr, 266*be691f3bSpatrick MemoryRegionInfo ®ion) { 267*be691f3bSpatrick // TODO: Implement 268*be691f3bSpatrick return Status(); 269*be691f3bSpatrick } 270*be691f3bSpatrick 271*be691f3bSpatrick Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) { 272*be691f3bSpatrick CheckInterpreterAndScriptObject(); 273*be691f3bSpatrick 274*be691f3bSpatrick lldb::addr_t address = 0; 275*be691f3bSpatrick lldb::MemoryRegionInfoSP mem_region_sp = nullptr; 276*be691f3bSpatrick 277*be691f3bSpatrick while ((mem_region_sp = 278*be691f3bSpatrick GetInterface().GetMemoryRegionContainingAddress(address))) { 279*be691f3bSpatrick auto range = mem_region_sp->GetRange(); 280*be691f3bSpatrick address += range.GetRangeBase() + range.GetByteSize(); 281*be691f3bSpatrick region_list.push_back(*mem_region_sp.get()); 282*be691f3bSpatrick } 283*be691f3bSpatrick 284*be691f3bSpatrick return {}; 285*be691f3bSpatrick } 286*be691f3bSpatrick 287*be691f3bSpatrick void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); } 288*be691f3bSpatrick 289*be691f3bSpatrick bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list, 290*be691f3bSpatrick ThreadList &new_thread_list) { 291*be691f3bSpatrick // TODO: Implement 292*be691f3bSpatrick // This is supposed to get the current set of threads, if any of them are in 293*be691f3bSpatrick // old_thread_list then they get copied to new_thread_list, and then any 294*be691f3bSpatrick // actually new threads will get added to new_thread_list. 295*be691f3bSpatrick return new_thread_list.GetSize(false) > 0; 296*be691f3bSpatrick } 297*be691f3bSpatrick 298*be691f3bSpatrick bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) { 299*be691f3bSpatrick info.Clear(); 300*be691f3bSpatrick info.SetProcessID(GetID()); 301*be691f3bSpatrick info.SetArchitecture(GetArchitecture()); 302*be691f3bSpatrick lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 303*be691f3bSpatrick if (module_sp) { 304*be691f3bSpatrick const bool add_exe_file_as_first_arg = false; 305*be691f3bSpatrick info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 306*be691f3bSpatrick add_exe_file_as_first_arg); 307*be691f3bSpatrick } 308*be691f3bSpatrick return true; 309*be691f3bSpatrick } 310*be691f3bSpatrick 311*be691f3bSpatrick ScriptedProcessInterface &ScriptedProcess::GetInterface() const { 312*be691f3bSpatrick return m_interpreter->GetScriptedProcessInterface(); 313*be691f3bSpatrick } 314