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