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/RegisterContext.h" 23 #include "lldb/Utility/State.h" 24 25 #include <mutex> 26 27 LLDB_PLUGIN_DEFINE(ScriptedProcess) 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() { 33 return "Scripted Process plug-in."; 34 } 35 36 static constexpr lldb::ScriptLanguage g_supported_script_languages[] = { 37 ScriptLanguage::eScriptLanguagePython, 38 }; 39 40 bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) { 41 llvm::ArrayRef<lldb::ScriptLanguage> supported_languages = 42 llvm::makeArrayRef(g_supported_script_languages); 43 44 return llvm::is_contained(supported_languages, language); 45 } 46 47 void ScriptedProcess::CheckInterpreterAndScriptObject() const { 48 lldbassert(m_interpreter && "Invalid Script Interpreter."); 49 lldbassert(m_script_object_sp && "Invalid Script Object."); 50 } 51 52 lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp, 53 lldb::ListenerSP listener_sp, 54 const FileSpec *file, 55 bool can_connect) { 56 if (!target_sp || 57 !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage())) 58 return nullptr; 59 60 Status error; 61 ScriptedProcess::ScriptedProcessInfo scripted_process_info( 62 target_sp->GetProcessLaunchInfo()); 63 64 auto process_sp = std::make_shared<ScriptedProcess>( 65 target_sp, listener_sp, scripted_process_info, error); 66 67 if (error.Fail() || !process_sp || !process_sp->m_script_object_sp || 68 !process_sp->m_script_object_sp->IsValid()) { 69 LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS), "%s", 70 error.AsCString()); 71 return nullptr; 72 } 73 74 return process_sp; 75 } 76 77 bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp, 78 bool plugin_specified_by_name) { 79 return true; 80 } 81 82 ScriptedProcess::ScriptedProcess( 83 lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, 84 const ScriptedProcess::ScriptedProcessInfo &scripted_process_info, 85 Status &error) 86 : Process(target_sp, listener_sp), 87 m_scripted_process_info(scripted_process_info) { 88 89 if (!target_sp) { 90 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", 91 __FUNCTION__, "Invalid target"); 92 return; 93 } 94 95 m_interpreter = target_sp->GetDebugger().GetScriptInterpreter(); 96 97 if (!m_interpreter) { 98 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", 99 __FUNCTION__, 100 "Debugger has no Script Interpreter"); 101 return; 102 } 103 104 ExecutionContext exe_ctx(target_sp, /*get_process=*/false); 105 106 StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject( 107 m_scripted_process_info.GetClassName().c_str(), exe_ctx, 108 m_scripted_process_info.GetArgsSP()); 109 110 if (!object_sp || !object_sp->IsValid()) { 111 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", 112 __FUNCTION__, 113 "Failed to create valid script object"); 114 return; 115 } 116 117 m_script_object_sp = object_sp; 118 } 119 120 ScriptedProcess::~ScriptedProcess() { 121 Clear(); 122 // We need to call finalize on the process before destroying ourselves to 123 // make sure all of the broadcaster cleanup goes as planned. If we destruct 124 // this class, then Process::~Process() might have problems trying to fully 125 // destroy the broadcaster. 126 Finalize(); 127 } 128 129 void ScriptedProcess::Initialize() { 130 static llvm::once_flag g_once_flag; 131 132 llvm::call_once(g_once_flag, []() { 133 PluginManager::RegisterPlugin(GetPluginNameStatic(), 134 GetPluginDescriptionStatic(), CreateInstance); 135 }); 136 } 137 138 void ScriptedProcess::Terminate() { 139 PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance); 140 } 141 142 Status ScriptedProcess::DoLoadCore() { 143 ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo(); 144 145 return DoLaunch(nullptr, launch_info); 146 } 147 148 Status ScriptedProcess::DoLaunch(Module *exe_module, 149 ProcessLaunchInfo &launch_info) { 150 CheckInterpreterAndScriptObject(); 151 152 /* FIXME: This doesn't reflect how lldb actually launches a process. 153 In reality, it attaches to debugserver, then resume the process. */ 154 Status error = GetInterface().Launch(); 155 SetPrivateState(eStateRunning); 156 157 if (error.Fail()) 158 return error; 159 160 // TODO: Fetch next state from stopped event queue then send stop event 161 // const StateType state = SetThreadStopInfo(response); 162 // if (state != eStateInvalid) { 163 // SetPrivateState(state); 164 165 SetPrivateState(eStateStopped); 166 167 return {}; 168 } 169 170 void ScriptedProcess::DidLaunch() { 171 CheckInterpreterAndScriptObject(); 172 m_pid = GetInterface().GetProcessID(); 173 } 174 175 Status ScriptedProcess::DoResume() { 176 CheckInterpreterAndScriptObject(); 177 178 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 179 // FIXME: Fetch data from thread. 180 const StateType thread_resume_state = eStateRunning; 181 LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__, 182 StateAsCString(thread_resume_state)); 183 184 bool resume = (thread_resume_state == eStateRunning); 185 assert(thread_resume_state == eStateRunning && "invalid thread resume state"); 186 187 Status error; 188 if (resume) { 189 LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__); 190 191 SetPrivateState(eStateRunning); 192 SetPrivateState(eStateStopped); 193 error = GetInterface().Resume(); 194 } 195 196 return error; 197 } 198 199 Status ScriptedProcess::DoStop() { 200 CheckInterpreterAndScriptObject(); 201 202 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 203 204 if (GetInterface().ShouldStop()) { 205 SetPrivateState(eStateStopped); 206 LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__); 207 return {}; 208 } 209 210 LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__); 211 return GetInterface().Stop(); 212 } 213 214 Status ScriptedProcess::DoDestroy() { return Status(); } 215 216 bool ScriptedProcess::IsAlive() { 217 if (m_interpreter && m_script_object_sp) 218 return GetInterface().IsAlive(); 219 return false; 220 } 221 222 size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, 223 Status &error) { 224 if (!m_interpreter) 225 return ScriptedInterface::ErrorWithMessage<size_t>( 226 LLVM_PRETTY_FUNCTION, "No interpreter.", error); 227 228 lldb::DataExtractorSP data_extractor_sp = 229 GetInterface().ReadMemoryAtAddress(addr, size, error); 230 231 if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail()) 232 return 0; 233 234 offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData( 235 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder()); 236 237 if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET) 238 return ScriptedInterface::ErrorWithMessage<size_t>( 239 LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error); 240 241 return size; 242 } 243 244 ArchSpec ScriptedProcess::GetArchitecture() { 245 return GetTarget().GetArchitecture(); 246 } 247 248 Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr, 249 MemoryRegionInfo ®ion) { 250 CheckInterpreterAndScriptObject(); 251 252 Status error; 253 if (auto region_or_err = 254 GetInterface().GetMemoryRegionContainingAddress(load_addr, error)) 255 region = *region_or_err; 256 257 return error; 258 } 259 260 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) { 261 CheckInterpreterAndScriptObject(); 262 263 Status error; 264 lldb::addr_t address = 0; 265 266 while (auto region_or_err = 267 GetInterface().GetMemoryRegionContainingAddress(address, error)) { 268 if (error.Fail()) 269 break; 270 271 MemoryRegionInfo &mem_region = *region_or_err; 272 auto range = mem_region.GetRange(); 273 address += range.GetRangeBase() + range.GetByteSize(); 274 region_list.push_back(mem_region); 275 } 276 277 return error; 278 } 279 280 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); } 281 282 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list, 283 ThreadList &new_thread_list) { 284 // TODO: Implement 285 // This is supposed to get the current set of threads, if any of them are in 286 // old_thread_list then they get copied to new_thread_list, and then any 287 // actually new threads will get added to new_thread_list. 288 289 CheckInterpreterAndScriptObject(); 290 m_thread_plans.ClearThreadCache(); 291 292 Status error; 293 ScriptLanguage language = m_interpreter->GetLanguage(); 294 295 if (language != eScriptLanguagePython) 296 return ScriptedInterface::ErrorWithMessage<bool>( 297 LLVM_PRETTY_FUNCTION, 298 llvm::Twine("ScriptInterpreter language (" + 299 llvm::Twine(m_interpreter->LanguageToString(language)) + 300 llvm::Twine(") not supported.")) 301 .str(), 302 error); 303 304 StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo(); 305 306 if (!thread_info_sp) 307 return ScriptedInterface::ErrorWithMessage<bool>( 308 LLVM_PRETTY_FUNCTION, 309 "Couldn't fetch thread list from Scripted Process.", error); 310 311 auto create_scripted_thread = 312 [this, &old_thread_list, &error, 313 &new_thread_list](ConstString key, StructuredData::Object *val) -> bool { 314 if (!val) 315 return ScriptedInterface::ErrorWithMessage<bool>( 316 LLVM_PRETTY_FUNCTION, "Invalid thread info object", error); 317 318 lldb::tid_t tid = LLDB_INVALID_THREAD_ID; 319 if (!llvm::to_integer(key.AsCString(), tid)) 320 return ScriptedInterface::ErrorWithMessage<bool>( 321 LLVM_PRETTY_FUNCTION, "Invalid thread id", error); 322 323 if (ThreadSP thread_sp = 324 old_thread_list.FindThreadByID(tid, false /*=can_update*/)) { 325 // If the thread was already in the old_thread_list, 326 // just add it back to the new_thread_list. 327 new_thread_list.AddThread(thread_sp); 328 return true; 329 } 330 331 auto thread_or_error = ScriptedThread::Create(*this, val->GetAsGeneric()); 332 333 if (!thread_or_error) 334 return ScriptedInterface::ErrorWithMessage<bool>( 335 LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error); 336 337 ThreadSP thread_sp = thread_or_error.get(); 338 lldbassert(thread_sp && "Couldn't initialize scripted thread."); 339 340 RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); 341 if (!reg_ctx_sp) 342 return ScriptedInterface::ErrorWithMessage<bool>( 343 LLVM_PRETTY_FUNCTION, 344 llvm::Twine("Invalid Register Context for thread " + 345 llvm::Twine(key.AsCString())) 346 .str(), 347 error); 348 349 new_thread_list.AddThread(thread_sp); 350 351 return true; 352 }; 353 354 thread_info_sp->ForEach(create_scripted_thread); 355 356 return new_thread_list.GetSize(false) > 0; 357 } 358 359 void ScriptedProcess::RefreshStateAfterStop() { 360 // Let all threads recover from stopping and do any clean up based on the 361 // previous thread state (if any). 362 } 363 364 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) { 365 info.Clear(); 366 info.SetProcessID(GetID()); 367 info.SetArchitecture(GetArchitecture()); 368 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 369 if (module_sp) { 370 const bool add_exe_file_as_first_arg = false; 371 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 372 add_exe_file_as_first_arg); 373 } 374 return true; 375 } 376 377 ScriptedProcessInterface &ScriptedProcess::GetInterface() const { 378 return m_interpreter->GetScriptedProcessInterface(); 379 } 380