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