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 return EnableSoftwareBreakpoint(bp_site); 264 } 265 266 ArchSpec ScriptedProcess::GetArchitecture() { 267 return GetTarget().GetArchitecture(); 268 } 269 270 Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr, 271 MemoryRegionInfo ®ion) { 272 Status error; 273 if (auto region_or_err = 274 GetInterface().GetMemoryRegionContainingAddress(load_addr, error)) 275 region = *region_or_err; 276 277 return error; 278 } 279 280 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) { 281 Status error; 282 lldb::addr_t address = 0; 283 284 while (auto region_or_err = 285 GetInterface().GetMemoryRegionContainingAddress(address, error)) { 286 if (error.Fail()) 287 break; 288 289 MemoryRegionInfo &mem_region = *region_or_err; 290 auto range = mem_region.GetRange(); 291 address += range.GetRangeBase() + range.GetByteSize(); 292 region_list.push_back(mem_region); 293 } 294 295 return error; 296 } 297 298 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); } 299 300 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list, 301 ThreadList &new_thread_list) { 302 // TODO: Implement 303 // This is supposed to get the current set of threads, if any of them are in 304 // old_thread_list then they get copied to new_thread_list, and then any 305 // actually new threads will get added to new_thread_list. 306 m_thread_plans.ClearThreadCache(); 307 308 Status error; 309 StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo(); 310 311 if (!thread_info_sp) 312 return ScriptedInterface::ErrorWithMessage<bool>( 313 LLVM_PRETTY_FUNCTION, 314 "Couldn't fetch thread list from Scripted Process.", error); 315 316 // Because `StructuredData::Dictionary` uses a `std::map<ConstString, 317 // ObjectSP>` for storage, each item is sorted based on the key alphabetical 318 // order. Since `GetThreadsInfo` provides thread indices as the key element, 319 // thread info comes ordered alphabetically, instead of numerically, so we 320 // need to sort the thread indices before creating thread. 321 322 StructuredData::ArraySP keys = thread_info_sp->GetKeys(); 323 324 std::map<size_t, StructuredData::ObjectSP> sorted_threads; 325 auto sort_keys = [&sorted_threads, 326 &thread_info_sp](StructuredData::Object *item) -> bool { 327 if (!item) 328 return false; 329 330 llvm::StringRef key = item->GetStringValue(); 331 size_t idx = 0; 332 333 // Make sure the provided index is actually an integer 334 if (!llvm::to_integer(key, idx)) 335 return false; 336 337 sorted_threads[idx] = thread_info_sp->GetValueForKey(key); 338 return true; 339 }; 340 341 size_t thread_count = thread_info_sp->GetSize(); 342 343 if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count) 344 // Might be worth showing the unsorted thread list instead of return early. 345 return ScriptedInterface::ErrorWithMessage<bool>( 346 LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error); 347 348 auto create_scripted_thread = 349 [this, &error, &new_thread_list]( 350 const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool { 351 size_t idx = pair.first; 352 StructuredData::ObjectSP object_sp = pair.second; 353 354 if (!object_sp) 355 return ScriptedInterface::ErrorWithMessage<bool>( 356 LLVM_PRETTY_FUNCTION, "Invalid thread info object", error); 357 358 auto thread_or_error = 359 ScriptedThread::Create(*this, object_sp->GetAsGeneric()); 360 361 if (!thread_or_error) 362 return ScriptedInterface::ErrorWithMessage<bool>( 363 LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error); 364 365 ThreadSP thread_sp = thread_or_error.get(); 366 lldbassert(thread_sp && "Couldn't initialize scripted thread."); 367 368 RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); 369 if (!reg_ctx_sp) 370 return ScriptedInterface::ErrorWithMessage<bool>( 371 LLVM_PRETTY_FUNCTION, 372 llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx)) 373 .str(), 374 error); 375 376 new_thread_list.AddThread(thread_sp); 377 378 return true; 379 }; 380 381 llvm::for_each(sorted_threads, create_scripted_thread); 382 383 return new_thread_list.GetSize(false) > 0; 384 } 385 386 void ScriptedProcess::RefreshStateAfterStop() { 387 // Let all threads recover from stopping and do any clean up based on the 388 // previous thread state (if any). 389 m_thread_list.RefreshStateAfterStop(); 390 } 391 392 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) { 393 info.Clear(); 394 info.SetProcessID(GetID()); 395 info.SetArchitecture(GetArchitecture()); 396 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); 397 if (module_sp) { 398 const bool add_exe_file_as_first_arg = false; 399 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), 400 add_exe_file_as_first_arg); 401 } 402 return true; 403 } 404 405 lldb_private::StructuredData::ObjectSP 406 ScriptedProcess::GetLoadedDynamicLibrariesInfos() { 407 Status error; 408 auto error_with_message = [&error](llvm::StringRef message) { 409 return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION, 410 message.data(), error); 411 }; 412 413 StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages(); 414 415 if (!loaded_images_sp || !loaded_images_sp->GetSize()) 416 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( 417 LLVM_PRETTY_FUNCTION, "No loaded images.", error); 418 419 ModuleList module_list; 420 Target &target = GetTarget(); 421 422 auto reload_image = [&target, &module_list, &error_with_message]( 423 StructuredData::Object *obj) -> bool { 424 StructuredData::Dictionary *dict = obj->GetAsDictionary(); 425 426 if (!dict) 427 return error_with_message("Couldn't cast image object into dictionary."); 428 429 ModuleSpec module_spec; 430 llvm::StringRef value; 431 432 bool has_path = dict->HasKey("path"); 433 bool has_uuid = dict->HasKey("uuid"); 434 if (!has_path && !has_uuid) 435 return error_with_message("Dictionary should have key 'path' or 'uuid'"); 436 if (!dict->HasKey("load_addr")) 437 return error_with_message("Dictionary is missing key 'load_addr'"); 438 439 if (has_path) { 440 dict->GetValueForKeyAsString("path", value); 441 module_spec.GetFileSpec().SetPath(value); 442 } 443 444 if (has_uuid) { 445 dict->GetValueForKeyAsString("uuid", value); 446 module_spec.GetUUID().SetFromStringRef(value); 447 } 448 module_spec.GetArchitecture() = target.GetArchitecture(); 449 450 ModuleSP module_sp = 451 target.GetOrCreateModule(module_spec, true /* notify */); 452 453 if (!module_sp) 454 return error_with_message("Couldn't create or get module."); 455 456 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 457 lldb::addr_t slide = LLDB_INVALID_OFFSET; 458 dict->GetValueForKeyAsInteger("load_addr", load_addr); 459 dict->GetValueForKeyAsInteger("slide", slide); 460 if (load_addr == LLDB_INVALID_ADDRESS) 461 return error_with_message( 462 "Couldn't get valid load address or slide offset."); 463 464 if (slide != LLDB_INVALID_OFFSET) 465 load_addr += slide; 466 467 bool changed = false; 468 module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/, 469 changed); 470 471 if (!changed && !module_sp->GetObjectFile()) 472 return error_with_message("Couldn't set the load address for module."); 473 474 dict->GetValueForKeyAsString("path", value); 475 FileSpec objfile(value); 476 module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename()); 477 478 return module_list.AppendIfNeeded(module_sp); 479 }; 480 481 if (!loaded_images_sp->ForEach(reload_image)) 482 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>( 483 LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error); 484 485 target.ModulesDidLoad(module_list); 486 487 return loaded_images_sp; 488 } 489 490 lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() { 491 StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata(); 492 493 Status error; 494 if (!metadata_sp || !metadata_sp->GetSize()) 495 return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>( 496 LLVM_PRETTY_FUNCTION, "No metadata.", error); 497 498 return metadata_sp; 499 } 500 501 void ScriptedProcess::UpdateQueueListIfNeeded() { 502 CheckScriptedInterface(); 503 for (ThreadSP thread_sp : Threads()) { 504 if (const char *queue_name = thread_sp->GetQueueName()) { 505 QueueSP queue_sp = std::make_shared<Queue>( 506 m_process->shared_from_this(), thread_sp->GetQueueID(), queue_name); 507 m_queue_list.AddQueue(queue_sp); 508 } 509 } 510 } 511 512 ScriptedProcessInterface &ScriptedProcess::GetInterface() const { 513 CheckScriptedInterface(); 514 return *m_interface_up; 515 } 516 517 void *ScriptedProcess::GetImplementation() { 518 StructuredData::GenericSP object_instance_sp = 519 GetInterface().GetScriptObjectInstance(); 520 if (object_instance_sp && 521 object_instance_sp->GetType() == eStructuredDataTypeGeneric) 522 return object_instance_sp->GetAsGeneric()->GetValue(); 523 return nullptr; 524 } 525