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