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/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" 27 28 #include <mutex> 29 30 LLDB_PLUGIN_DEFINE(ScriptedProcess) 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() { 36 return "Scripted Process plug-in."; 37 } 38 39 static constexpr lldb::ScriptLanguage g_supported_script_languages[] = { 40 ScriptLanguage::eScriptLanguagePython, 41 }; 42 43 bool 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 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; 57 58 ScriptedMetadata scripted_metadata(target_sp->GetProcessLaunchInfo()); 59 60 Status error; 61 auto process_sp = std::shared_ptr<ScriptedProcess>( 62 new ScriptedProcess(target_sp, listener_sp, scripted_metadata, error)); 63 64 if (error.Fail() || !process_sp || !process_sp->m_interface_up) { 65 LLDB_LOGF(GetLog(LLDBLog::Process), "%s", error.AsCString()); 66 return nullptr; 67 } 68 69 return process_sp; 70 } 71 72 bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp, 73 bool plugin_specified_by_name) { 74 return true; 75 } 76 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) { 82 83 if (!target_sp) { 84 error = Status::FromErrorStringWithFormat( 85 "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__, "Invalid target"); 86 return; 87 } 88 89 ScriptInterpreter *interpreter = 90 target_sp->GetDebugger().GetScriptInterpreter(); 91 92 if (!interpreter) { 93 error = Status::FromErrorStringWithFormat( 94 "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__, 95 "Debugger has no Script Interpreter"); 96 return; 97 } 98 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; 106 } 107 108 ExecutionContext exe_ctx(target_sp, /*get_process=*/false); 109 110 // Create process script object 111 auto obj_or_err = GetInterface().CreatePluginObject( 112 m_scripted_metadata.GetClassName(), exe_ctx, 113 m_scripted_metadata.GetArgsSP()); 114 115 if (!obj_or_err) { 116 llvm::consumeError(obj_or_err.takeError()); 117 error = Status::FromErrorString("Failed to create script object."); 118 return; 119 } 120 121 StructuredData::GenericSP object_sp = *obj_or_err; 122 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; 128 } 129 } 130 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 */); 144 } 145 146 void ScriptedProcess::Initialize() { 147 static llvm::once_flag g_once_flag; 148 149 llvm::call_once(g_once_flag, []() { 150 PluginManager::RegisterPlugin(GetPluginNameStatic(), 151 GetPluginDescriptionStatic(), CreateInstance); 152 }); 153 } 154 155 void ScriptedProcess::Terminate() { 156 PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance); 157 } 158 159 Status ScriptedProcess::DoLoadCore() { 160 ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo(); 161 162 return DoLaunch(nullptr, launch_info); 163 } 164 165 Status ScriptedProcess::DoLaunch(Module *exe_module, 166 ProcessLaunchInfo &launch_info) { 167 LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s launching process", __FUNCTION__); 168 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; 176 } 177 178 void ScriptedProcess::DidLaunch() { m_pid = GetInterface().GetProcessID(); } 179 180 void ScriptedProcess::DidResume() { 181 // Update the PID again, in case the user provided a placeholder pid at launch 182 m_pid = GetInterface().GetProcessID(); 183 } 184 185 Status ScriptedProcess::DoResume(RunDirection direction) { 186 LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s resuming process", __FUNCTION__); 187 188 if (direction == RunDirection::eRunForward) 189 return GetInterface().Resume(); 190 // FIXME: Pipe reverse continue through Scripted Processes 191 return Status::FromErrorStringWithFormatv( 192 "error: {0} does not support reverse execution of processes", 193 GetPluginName()); 194 } 195 196 Status ScriptedProcess::DoAttach(const ProcessAttachInfo &attach_info) { 197 Status error = GetInterface().Attach(attach_info); 198 SetPrivateState(eStateRunning); 199 SetPrivateState(eStateStopped); 200 if (error.Fail()) 201 return error; 202 // NOTE: We need to set the PID before finishing to attach otherwise we will 203 // hit an assert when calling the attach completion handler. 204 DidLaunch(); 205 206 return {}; 207 } 208 209 Status 210 ScriptedProcess::DoAttachToProcessWithID(lldb::pid_t pid, 211 const ProcessAttachInfo &attach_info) { 212 return DoAttach(attach_info); 213 } 214 215 Status ScriptedProcess::DoAttachToProcessWithName( 216 const char *process_name, const ProcessAttachInfo &attach_info) { 217 return DoAttach(attach_info); 218 } 219 220 void ScriptedProcess::DidAttach(ArchSpec &process_arch) { 221 process_arch = GetArchitecture(); 222 } 223 224 Status ScriptedProcess::DoDestroy() { return Status(); } 225 226 bool ScriptedProcess::IsAlive() { return GetInterface().IsAlive(); } 227 228 size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, 229 Status &error) { 230 lldb::DataExtractorSP data_extractor_sp = 231 GetInterface().ReadMemoryAtAddress(addr, size, error); 232 233 if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail()) 234 return 0; 235 236 offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData( 237 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder()); 238 239 if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET) 240 return ScriptedInterface::ErrorWithMessage<size_t>( 241 LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error); 242 243 // FIXME: We should use the diagnostic system to report a warning if the 244 // `bytes_copied` is different from `size`. 245 246 return bytes_copied; 247 } 248 249 size_t ScriptedProcess::DoWriteMemory(lldb::addr_t vm_addr, const void *buf, 250 size_t size, Status &error) { 251 lldb::DataExtractorSP data_extractor_sp = std::make_shared<DataExtractor>( 252 buf, size, GetByteOrder(), GetAddressByteSize()); 253 254 if (!data_extractor_sp || !data_extractor_sp->GetByteSize()) 255 return 0; 256 257 lldb::offset_t bytes_written = 258 GetInterface().WriteMemoryAtAddress(vm_addr, data_extractor_sp, error); 259 260 if (!bytes_written || bytes_written == LLDB_INVALID_OFFSET) 261 return ScriptedInterface::ErrorWithMessage<size_t>( 262 LLVM_PRETTY_FUNCTION, "Failed to copy write buffer to memory.", error); 263 264 // FIXME: We should use the diagnostic system to report a warning if the 265 // `bytes_written` is different from `size`. 266 267 return bytes_written; 268 } 269 270 Status ScriptedProcess::EnableBreakpointSite(BreakpointSite *bp_site) { 271 assert(bp_site != nullptr); 272 273 if (bp_site->IsEnabled()) { 274 return {}; 275 } 276 277 if (bp_site->HardwareRequired()) { 278 return Status::FromErrorString( 279 "Scripted Processes don't support hardware breakpoints"); 280 } 281 282 Status error; 283 GetInterface().CreateBreakpoint(bp_site->GetLoadAddress(), error); 284 285 return error; 286 } 287 288 ArchSpec ScriptedProcess::GetArchitecture() { 289 return GetTarget().GetArchitecture(); 290 } 291 292 Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr, 293 MemoryRegionInfo ®ion) { 294 Status error; 295 if (auto region_or_err = 296 GetInterface().GetMemoryRegionContainingAddress(load_addr, error)) 297 region = *region_or_err; 298 299 return error; 300 } 301 302 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) { 303 Status error; 304 lldb::addr_t address = 0; 305 306 while (auto region_or_err = 307 GetInterface().GetMemoryRegionContainingAddress(address, error)) { 308 if (error.Fail()) 309 break; 310 311 MemoryRegionInfo &mem_region = *region_or_err; 312 auto range = mem_region.GetRange(); 313 address += range.GetRangeBase() + range.GetByteSize(); 314 region_list.push_back(mem_region); 315 } 316 317 return error; 318 } 319 320 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); } 321 322 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list, 323 ThreadList &new_thread_list) { 324 // TODO: Implement 325 // This is supposed to get the current set of threads, if any of them are in 326 // old_thread_list then they get copied to new_thread_list, and then any 327 // actually new threads will get added to new_thread_list. 328 m_thread_plans.ClearThreadCache(); 329 330 Status error; 331 StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo(); 332 333 if (!thread_info_sp) 334 return ScriptedInterface::ErrorWithMessage<bool>( 335 LLVM_PRETTY_FUNCTION, 336 "Couldn't fetch thread list from Scripted Process.", error); 337 338 // Because `StructuredData::Dictionary` uses a `std::map<ConstString, 339 // ObjectSP>` for storage, each item is sorted based on the key alphabetical 340 // order. Since `GetThreadsInfo` provides thread indices as the key element, 341 // thread info comes ordered alphabetically, instead of numerically, so we 342 // need to sort the thread indices before creating thread. 343 344 StructuredData::ArraySP keys = thread_info_sp->GetKeys(); 345 346 std::map<size_t, StructuredData::ObjectSP> sorted_threads; 347 auto sort_keys = [&sorted_threads, 348 &thread_info_sp](StructuredData::Object *item) -> bool { 349 if (!item) 350 return false; 351 352 llvm::StringRef key = item->GetStringValue(); 353 size_t idx = 0; 354 355 // Make sure the provided index is actually an integer 356 if (!llvm::to_integer(key, idx)) 357 return false; 358 359 sorted_threads[idx] = thread_info_sp->GetValueForKey(key); 360 return true; 361 }; 362 363 size_t thread_count = thread_info_sp->GetSize(); 364 365 if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count) 366 // Might be worth showing the unsorted thread list instead of return early. 367 return ScriptedInterface::ErrorWithMessage<bool>( 368 LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error); 369 370 auto create_scripted_thread = 371 [this, &error, &new_thread_list]( 372 const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool { 373 size_t idx = pair.first; 374 StructuredData::ObjectSP object_sp = pair.second; 375 376 if (!object_sp) 377 return ScriptedInterface::ErrorWithMessage<bool>( 378 LLVM_PRETTY_FUNCTION, "Invalid thread info object", error); 379 380 auto thread_or_error = 381 ScriptedThread::Create(*this, object_sp->GetAsGeneric()); 382 383 if (!thread_or_error) 384 return ScriptedInterface::ErrorWithMessage<bool>( 385 LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error); 386 387 ThreadSP thread_sp = thread_or_error.get(); 388 lldbassert(thread_sp && "Couldn't initialize scripted thread."); 389 390 RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); 391 if (!reg_ctx_sp) 392 return ScriptedInterface::ErrorWithMessage<bool>( 393 LLVM_PRETTY_FUNCTION, 394 llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx)) 395 .str(), 396 error); 397 398 new_thread_list.AddThread(thread_sp); 399 400 return true; 401 }; 402 403 llvm::for_each(sorted_threads, create_scripted_thread); 404 405 return new_thread_list.GetSize(false) > 0; 406 } 407 408 void ScriptedProcess::RefreshStateAfterStop() { 409 // Let all threads recover from stopping and do any clean up based on the 410 // previous thread state (if any). 411 m_thread_list.RefreshStateAfterStop(); 412 } 413 414 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) { 415 info.Clear(); 416 info.SetProcessID(GetID()); 417 info.SetArchitecture(GetArchitecture()); 418 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 419 if (module_sp) { 420 const bool add_exe_file_as_first_arg = false; 421 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 422 add_exe_file_as_first_arg); 423 } 424 return true; 425 } 426 427 lldb_private::StructuredData::ObjectSP 428 ScriptedProcess::GetLoadedDynamicLibrariesInfos() { 429 Status error; 430 auto error_with_message = [&error](llvm::StringRef message) { 431 return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION, 432 message.data(), error); 433 }; 434 435 StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages(); 436 437 if (!loaded_images_sp || !loaded_images_sp->GetSize()) 438 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( 439 LLVM_PRETTY_FUNCTION, "No loaded images.", error); 440 441 ModuleList module_list; 442 Target &target = GetTarget(); 443 444 auto reload_image = [&target, &module_list, &error_with_message]( 445 StructuredData::Object *obj) -> bool { 446 StructuredData::Dictionary *dict = obj->GetAsDictionary(); 447 448 if (!dict) 449 return error_with_message("Couldn't cast image object into dictionary."); 450 451 ModuleSpec module_spec; 452 llvm::StringRef value; 453 454 bool has_path = dict->HasKey("path"); 455 bool has_uuid = dict->HasKey("uuid"); 456 if (!has_path && !has_uuid) 457 return error_with_message("Dictionary should have key 'path' or 'uuid'"); 458 if (!dict->HasKey("load_addr")) 459 return error_with_message("Dictionary is missing key 'load_addr'"); 460 461 if (has_path) { 462 dict->GetValueForKeyAsString("path", value); 463 module_spec.GetFileSpec().SetPath(value); 464 } 465 466 if (has_uuid) { 467 dict->GetValueForKeyAsString("uuid", value); 468 module_spec.GetUUID().SetFromStringRef(value); 469 } 470 module_spec.GetArchitecture() = target.GetArchitecture(); 471 472 ModuleSP module_sp = 473 target.GetOrCreateModule(module_spec, true /* notify */); 474 475 if (!module_sp) 476 return error_with_message("Couldn't create or get module."); 477 478 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 479 lldb::offset_t slide = LLDB_INVALID_OFFSET; 480 dict->GetValueForKeyAsInteger("load_addr", load_addr); 481 dict->GetValueForKeyAsInteger("slide", slide); 482 if (load_addr == LLDB_INVALID_ADDRESS) 483 return error_with_message( 484 "Couldn't get valid load address or slide offset."); 485 486 if (slide != LLDB_INVALID_OFFSET) 487 load_addr += slide; 488 489 bool changed = false; 490 module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/, 491 changed); 492 493 if (!changed && !module_sp->GetObjectFile()) 494 return error_with_message("Couldn't set the load address for module."); 495 496 dict->GetValueForKeyAsString("path", value); 497 FileSpec objfile(value); 498 module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename()); 499 500 return module_list.AppendIfNeeded(module_sp); 501 }; 502 503 if (!loaded_images_sp->ForEach(reload_image)) 504 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( 505 LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error); 506 507 target.ModulesDidLoad(module_list); 508 509 return loaded_images_sp; 510 } 511 512 lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() { 513 StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata(); 514 515 Status error; 516 if (!metadata_sp || !metadata_sp->GetSize()) 517 return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>( 518 LLVM_PRETTY_FUNCTION, "No metadata.", error); 519 520 return metadata_sp; 521 } 522 523 void ScriptedProcess::UpdateQueueListIfNeeded() { 524 CheckScriptedInterface(); 525 for (ThreadSP thread_sp : Threads()) { 526 if (const char *queue_name = thread_sp->GetQueueName()) { 527 QueueSP queue_sp = std::make_shared<Queue>( 528 m_process->shared_from_this(), thread_sp->GetQueueID(), queue_name); 529 m_queue_list.AddQueue(queue_sp); 530 } 531 } 532 } 533 534 ScriptedProcessInterface &ScriptedProcess::GetInterface() const { 535 CheckScriptedInterface(); 536 return *m_interface_up; 537 } 538 539 void *ScriptedProcess::GetImplementation() { 540 StructuredData::GenericSP object_instance_sp = 541 GetInterface().GetScriptObjectInstance(); 542 if (object_instance_sp && 543 object_instance_sp->GetType() == eStructuredDataTypeGeneric) 544 return object_instance_sp->GetAsGeneric()->GetValue(); 545 return nullptr; 546 } 547