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/Interpreter/ScriptedMetadata.h" 22#include "lldb/Target/MemoryRegionInfo.h" 23#include "lldb/Target/Queue.h" 24#include "lldb/Target/RegisterContext.h" 25#include "lldb/Utility/LLDBLog.h" 26#include "lldb/Utility/State.h" 27 28#include <mutex> 29 30LLDB_PLUGIN_DEFINE(ScriptedProcess) 31 32using namespace lldb; 33using namespace lldb_private; 34 35llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() { 36 return "Scripted Process plug-in."; 37} 38 39static constexpr lldb::ScriptLanguage g_supported_script_languages[] = { 40 ScriptLanguage::eScriptLanguagePython, 41}; 42 43bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) { 44 llvm::ArrayRef<lldb::ScriptLanguage> supported_languages = 45 llvm::ArrayRef(g_supported_script_languages); 46 47 return llvm::is_contained(supported_languages, language); 48} 49 50void ScriptedProcess::CheckInterpreterAndScriptObject() const { 51 lldbassert(m_interpreter && "Invalid Script Interpreter."); 52 lldbassert(m_script_object_sp && "Invalid Script Object."); 53} 54 55lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp, 56 lldb::ListenerSP listener_sp, 57 const FileSpec *file, 58 bool can_connect) { 59 if (!target_sp || 60 !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage())) 61 return nullptr; 62 63 ScriptedMetadata scripted_metadata(target_sp->GetProcessLaunchInfo()); 64 65 Status error; 66 auto process_sp = std::shared_ptr<ScriptedProcess>( 67 new ScriptedProcess(target_sp, listener_sp, scripted_metadata, error)); 68 69 if (error.Fail() || !process_sp || !process_sp->m_script_object_sp || 70 !process_sp->m_script_object_sp->IsValid()) { 71 LLDB_LOGF(GetLog(LLDBLog::Process), "%s", error.AsCString()); 72 return nullptr; 73 } 74 75 return process_sp; 76} 77 78bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp, 79 bool plugin_specified_by_name) { 80 return true; 81} 82 83ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp, 84 lldb::ListenerSP listener_sp, 85 const ScriptedMetadata &scripted_metadata, 86 Status &error) 87 : Process(target_sp, listener_sp), m_scripted_metadata(scripted_metadata) { 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_metadata.GetClassName(), exe_ctx, 108 m_scripted_metadata.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 120ScriptedProcess::~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 129void 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 138void ScriptedProcess::Terminate() { 139 PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance); 140} 141 142Status ScriptedProcess::DoLoadCore() { 143 ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo(); 144 145 return DoLaunch(nullptr, launch_info); 146} 147 148Status 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 170void ScriptedProcess::DidLaunch() { 171 CheckInterpreterAndScriptObject(); 172 m_pid = GetInterface().GetProcessID(); 173 GetLoadedDynamicLibrariesInfos(); 174} 175 176Status ScriptedProcess::DoResume() { 177 CheckInterpreterAndScriptObject(); 178 179 Log *log = GetLog(LLDBLog::Process); 180 // FIXME: Fetch data from thread. 181 const StateType thread_resume_state = eStateRunning; 182 LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__, 183 StateAsCString(thread_resume_state)); 184 185 bool resume = (thread_resume_state == eStateRunning); 186 assert(thread_resume_state == eStateRunning && "invalid thread resume state"); 187 188 Status error; 189 if (resume) { 190 LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__); 191 192 SetPrivateState(eStateRunning); 193 SetPrivateState(eStateStopped); 194 error = GetInterface().Resume(); 195 } 196 197 return error; 198} 199 200Status ScriptedProcess::DoStop() { 201 CheckInterpreterAndScriptObject(); 202 203 Log *log = GetLog(LLDBLog::Process); 204 205 if (GetInterface().ShouldStop()) { 206 SetPrivateState(eStateStopped); 207 LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__); 208 return {}; 209 } 210 211 LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__); 212 return GetInterface().Stop(); 213} 214 215Status ScriptedProcess::DoDestroy() { return Status(); } 216 217bool ScriptedProcess::IsAlive() { 218 if (m_interpreter && m_script_object_sp) 219 return GetInterface().IsAlive(); 220 return false; 221} 222 223size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, 224 Status &error) { 225 if (!m_interpreter) 226 return ScriptedInterface::ErrorWithMessage<size_t>( 227 LLVM_PRETTY_FUNCTION, "No interpreter.", error); 228 229 lldb::DataExtractorSP data_extractor_sp = 230 GetInterface().ReadMemoryAtAddress(addr, size, error); 231 232 if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail()) 233 return 0; 234 235 offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData( 236 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder()); 237 238 if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET) 239 return ScriptedInterface::ErrorWithMessage<size_t>( 240 LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error); 241 242 return size; 243} 244 245ArchSpec ScriptedProcess::GetArchitecture() { 246 return GetTarget().GetArchitecture(); 247} 248 249Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr, 250 MemoryRegionInfo ®ion) { 251 CheckInterpreterAndScriptObject(); 252 253 Status error; 254 if (auto region_or_err = 255 GetInterface().GetMemoryRegionContainingAddress(load_addr, error)) 256 region = *region_or_err; 257 258 return error; 259} 260 261Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) { 262 CheckInterpreterAndScriptObject(); 263 264 Status error; 265 lldb::addr_t address = 0; 266 267 while (auto region_or_err = 268 GetInterface().GetMemoryRegionContainingAddress(address, error)) { 269 if (error.Fail()) 270 break; 271 272 MemoryRegionInfo &mem_region = *region_or_err; 273 auto range = mem_region.GetRange(); 274 address += range.GetRangeBase() + range.GetByteSize(); 275 region_list.push_back(mem_region); 276 } 277 278 return error; 279} 280 281void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); } 282 283bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list, 284 ThreadList &new_thread_list) { 285 // TODO: Implement 286 // This is supposed to get the current set of threads, if any of them are in 287 // old_thread_list then they get copied to new_thread_list, and then any 288 // actually new threads will get added to new_thread_list. 289 290 CheckInterpreterAndScriptObject(); 291 m_thread_plans.ClearThreadCache(); 292 293 Status error; 294 ScriptLanguage language = m_interpreter->GetLanguage(); 295 296 if (language != eScriptLanguagePython) 297 return ScriptedInterface::ErrorWithMessage<bool>( 298 LLVM_PRETTY_FUNCTION, 299 llvm::Twine("ScriptInterpreter language (" + 300 llvm::Twine(m_interpreter->LanguageToString(language)) + 301 llvm::Twine(") not supported.")) 302 .str(), 303 error); 304 305 StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo(); 306 307 if (!thread_info_sp) 308 return ScriptedInterface::ErrorWithMessage<bool>( 309 LLVM_PRETTY_FUNCTION, 310 "Couldn't fetch thread list from Scripted Process.", error); 311 312 // Because `StructuredData::Dictionary` uses a `std::map<ConstString, 313 // ObjectSP>` for storage, each item is sorted based on the key alphabetical 314 // order. Since `GetThreadsInfo` provides thread indices as the key element, 315 // thread info comes ordered alphabetically, instead of numerically, so we 316 // need to sort the thread indices before creating thread. 317 318 StructuredData::ArraySP keys = thread_info_sp->GetKeys(); 319 320 std::map<size_t, StructuredData::ObjectSP> sorted_threads; 321 auto sort_keys = [&sorted_threads, 322 &thread_info_sp](StructuredData::Object *item) -> bool { 323 if (!item) 324 return false; 325 326 llvm::StringRef key = item->GetStringValue(); 327 size_t idx = 0; 328 329 // Make sure the provided index is actually an integer 330 if (!llvm::to_integer(key, idx)) 331 return false; 332 333 sorted_threads[idx] = thread_info_sp->GetValueForKey(key); 334 return true; 335 }; 336 337 size_t thread_count = thread_info_sp->GetSize(); 338 339 if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count) 340 // Might be worth showing the unsorted thread list instead of return early. 341 return ScriptedInterface::ErrorWithMessage<bool>( 342 LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error); 343 344 auto create_scripted_thread = 345 [this, &error, &new_thread_list]( 346 const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool { 347 size_t idx = pair.first; 348 StructuredData::ObjectSP object_sp = pair.second; 349 350 if (!object_sp) 351 return ScriptedInterface::ErrorWithMessage<bool>( 352 LLVM_PRETTY_FUNCTION, "Invalid thread info object", error); 353 354 auto thread_or_error = 355 ScriptedThread::Create(*this, object_sp->GetAsGeneric()); 356 357 if (!thread_or_error) 358 return ScriptedInterface::ErrorWithMessage<bool>( 359 LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error); 360 361 ThreadSP thread_sp = thread_or_error.get(); 362 lldbassert(thread_sp && "Couldn't initialize scripted thread."); 363 364 RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); 365 if (!reg_ctx_sp) 366 return ScriptedInterface::ErrorWithMessage<bool>( 367 LLVM_PRETTY_FUNCTION, 368 llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx)) 369 .str(), 370 error); 371 372 new_thread_list.AddThread(thread_sp); 373 374 return true; 375 }; 376 377 llvm::for_each(sorted_threads, create_scripted_thread); 378 379 return new_thread_list.GetSize(false) > 0; 380} 381 382void ScriptedProcess::RefreshStateAfterStop() { 383 // Let all threads recover from stopping and do any clean up based on the 384 // previous thread state (if any). 385 m_thread_list.RefreshStateAfterStop(); 386} 387 388bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) { 389 info.Clear(); 390 info.SetProcessID(GetID()); 391 info.SetArchitecture(GetArchitecture()); 392 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 393 if (module_sp) { 394 const bool add_exe_file_as_first_arg = false; 395 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 396 add_exe_file_as_first_arg); 397 } 398 return true; 399} 400 401lldb_private::StructuredData::ObjectSP 402ScriptedProcess::GetLoadedDynamicLibrariesInfos() { 403 CheckInterpreterAndScriptObject(); 404 405 Status error; 406 auto error_with_message = [&error](llvm::StringRef message) { 407 return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION, 408 message.data(), error); 409 }; 410 411 StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages(); 412 413 if (!loaded_images_sp || !loaded_images_sp->GetSize()) 414 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( 415 LLVM_PRETTY_FUNCTION, "No loaded images.", error); 416 417 ModuleList module_list; 418 Target &target = GetTarget(); 419 420 auto reload_image = [&target, &module_list, &error_with_message]( 421 StructuredData::Object *obj) -> bool { 422 StructuredData::Dictionary *dict = obj->GetAsDictionary(); 423 424 if (!dict) 425 return error_with_message("Couldn't cast image object into dictionary."); 426 427 ModuleSpec module_spec; 428 llvm::StringRef value; 429 430 bool has_path = dict->HasKey("path"); 431 bool has_uuid = dict->HasKey("uuid"); 432 if (!has_path && !has_uuid) 433 return error_with_message("Dictionary should have key 'path' or 'uuid'"); 434 if (!dict->HasKey("load_addr")) 435 return error_with_message("Dictionary is missing key 'load_addr'"); 436 437 if (has_path) { 438 dict->GetValueForKeyAsString("path", value); 439 module_spec.GetFileSpec().SetPath(value); 440 } 441 442 if (has_uuid) { 443 dict->GetValueForKeyAsString("uuid", value); 444 module_spec.GetUUID().SetFromStringRef(value); 445 } 446 module_spec.GetArchitecture() = target.GetArchitecture(); 447 448 ModuleSP module_sp = 449 target.GetOrCreateModule(module_spec, true /* notify */); 450 451 if (!module_sp) 452 return error_with_message("Couldn't create or get module."); 453 454 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 455 lldb::addr_t slide = LLDB_INVALID_OFFSET; 456 dict->GetValueForKeyAsInteger("load_addr", load_addr); 457 dict->GetValueForKeyAsInteger("slide", slide); 458 if (load_addr == LLDB_INVALID_ADDRESS) 459 return error_with_message( 460 "Couldn't get valid load address or slide offset."); 461 462 if (slide != LLDB_INVALID_OFFSET) 463 load_addr += slide; 464 465 bool changed = false; 466 module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/, 467 changed); 468 469 if (!changed && !module_sp->GetObjectFile()) 470 return error_with_message("Couldn't set the load address for module."); 471 472 dict->GetValueForKeyAsString("path", value); 473 FileSpec objfile(value); 474 module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename()); 475 476 return module_list.AppendIfNeeded(module_sp); 477 }; 478 479 if (!loaded_images_sp->ForEach(reload_image)) 480 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( 481 LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error); 482 483 target.ModulesDidLoad(module_list); 484 485 return loaded_images_sp; 486} 487 488lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() { 489 CheckInterpreterAndScriptObject(); 490 491 StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata(); 492 493 Status error; 494 if (!metadata_sp || !metadata_sp->GetSize()) 495 return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>( 496 LLVM_PRETTY_FUNCTION, "No metadata.", error); 497 498 return metadata_sp; 499} 500 501void ScriptedProcess::UpdateQueueListIfNeeded() { 502 CheckInterpreterAndScriptObject(); 503 for (ThreadSP thread_sp : Threads()) { 504 if (const char *queue_name = thread_sp->GetQueueName()) { 505 QueueSP queue_sp = std::make_shared<Queue>( 506 m_process->shared_from_this(), thread_sp->GetQueueID(), queue_name); 507 m_queue_list.AddQueue(queue_sp); 508 } 509 } 510} 511 512ScriptedProcessInterface &ScriptedProcess::GetInterface() const { 513 return m_interpreter->GetScriptedProcessInterface(); 514} 515