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