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