1 //===-- ScriptedProcess.cpp -----------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "ScriptedProcess.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/PluginManager.h"
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"
30 LLDB_PLUGIN_DEFINE(ScriptedProcess)
33 using namespace lldb_private;
35 llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() {
36 return "Scripted Process plug-in.";
39 static constexpr lldb::ScriptLanguage g_supported_script_languages[] = {
40 ScriptLanguage::eScriptLanguagePython,
43 bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) {
44 llvm::ArrayRef<lldb::ScriptLanguage> supported_languages =
45 llvm::ArrayRef(g_supported_script_languages);
47 return llvm::is_contained(supported_languages, language);
50 lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
51 lldb::ListenerSP listener_sp,
55 !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage()))
58 ScriptedMetadata scripted_metadata(target_sp->GetProcessLaunchInfo());
61 auto process_sp = std::shared_ptr<ScriptedProcess>(
62 new ScriptedProcess(target_sp, listener_sp, scripted_metadata, error));
64 if (error.Fail() || !process_sp || !process_sp->m_interface_up) {
65 LLDB_LOGF(GetLog(LLDBLog::Process), "%s", error.AsCString());
72 bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
73 bool plugin_specified_by_name) {
77 ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp,
78 lldb::ListenerSP listener_sp,
79 const ScriptedMetadata &scripted_metadata,
81 : Process(target_sp, listener_sp), m_scripted_metadata(scripted_metadata) {
84 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
85 __FUNCTION__, "Invalid target");
89 ScriptInterpreter *interpreter =
90 target_sp->GetDebugger().GetScriptInterpreter();
93 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
95 "Debugger has no Script Interpreter");
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");
108 ExecutionContext exe_ctx(target_sp, /*get_process=*/false);
110 // Create process script object
111 StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject(
112 m_scripted_metadata.GetClassName(), exe_ctx,
113 m_scripted_metadata.GetArgsSP());
115 if (!object_sp || !object_sp->IsValid()) {
116 error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
118 "Failed to create valid script object");
123 ScriptedProcess::~ScriptedProcess() {
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.
132 void ScriptedProcess::Initialize() {
133 static llvm::once_flag g_once_flag;
135 llvm::call_once(g_once_flag, []() {
136 PluginManager::RegisterPlugin(GetPluginNameStatic(),
137 GetPluginDescriptionStatic(), CreateInstance);
141 void ScriptedProcess::Terminate() {
142 PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
145 Status ScriptedProcess::DoLoadCore() {
146 ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
148 return DoLaunch(nullptr, launch_info);
151 Status ScriptedProcess::DoLaunch(Module *exe_module,
152 ProcessLaunchInfo &launch_info) {
153 LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s launching process", __FUNCTION__);
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);
164 void ScriptedProcess::DidLaunch() { m_pid = GetInterface().GetProcessID(); }
166 void ScriptedProcess::DidResume() {
167 // Update the PID again, in case the user provided a placeholder pid at launch
168 m_pid = GetInterface().GetProcessID();
171 Status ScriptedProcess::DoResume() {
172 LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s resuming process", __FUNCTION__);
174 return GetInterface().Resume();
177 Status ScriptedProcess::DoAttach(const ProcessAttachInfo &attach_info) {
178 Status error = GetInterface().Attach(attach_info);
179 SetPrivateState(eStateRunning);
180 SetPrivateState(eStateStopped);
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.
191 ScriptedProcess::DoAttachToProcessWithID(lldb::pid_t pid,
192 const ProcessAttachInfo &attach_info) {
193 return DoAttach(attach_info);
196 Status ScriptedProcess::DoAttachToProcessWithName(
197 const char *process_name, const ProcessAttachInfo &attach_info) {
198 return DoAttach(attach_info);
201 void ScriptedProcess::DidAttach(ArchSpec &process_arch) {
202 process_arch = GetArchitecture();
205 Status ScriptedProcess::DoDestroy() { return Status(); }
207 bool ScriptedProcess::IsAlive() { return GetInterface().IsAlive(); }
209 size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
211 lldb::DataExtractorSP data_extractor_sp =
212 GetInterface().ReadMemoryAtAddress(addr, size, error);
214 if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
217 offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
218 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
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);
224 // FIXME: We should use the diagnostic system to report a warning if the
225 // `bytes_copied` is different from `size`.
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());
235 if (!data_extractor_sp || !data_extractor_sp->GetByteSize())
238 lldb::offset_t bytes_written =
239 GetInterface().WriteMemoryAtAddress(vm_addr, data_extractor_sp, error);
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);
245 // FIXME: We should use the diagnostic system to report a warning if the
246 // `bytes_written` is different from `size`.
248 return bytes_written;
251 Status ScriptedProcess::EnableBreakpointSite(BreakpointSite *bp_site) {
252 assert(bp_site != nullptr);
254 if (bp_site->IsEnabled()) {
258 if (bp_site->HardwareRequired()) {
259 return Status("Scripted Processes don't support hardware breakpoints");
263 GetInterface().CreateBreakpoint(bp_site->GetLoadAddress(), error);
268 ArchSpec ScriptedProcess::GetArchitecture() {
269 return GetTarget().GetArchitecture();
272 Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
273 MemoryRegionInfo ®ion) {
275 if (auto region_or_err =
276 GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
277 region = *region_or_err;
282 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) {
284 lldb::addr_t address = 0;
286 while (auto region_or_err =
287 GetInterface().GetMemoryRegionContainingAddress(address, error)) {
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);
300 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
302 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
303 ThreadList &new_thread_list) {
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();
311 StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo();
314 return ScriptedInterface::ErrorWithMessage<bool>(
315 LLVM_PRETTY_FUNCTION,
316 "Couldn't fetch thread list from Scripted Process.", error);
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.
324 StructuredData::ArraySP keys = thread_info_sp->GetKeys();
326 std::map<size_t, StructuredData::ObjectSP> sorted_threads;
327 auto sort_keys = [&sorted_threads,
328 &thread_info_sp](StructuredData::Object *item) -> bool {
332 llvm::StringRef key = item->GetStringValue();
335 // Make sure the provided index is actually an integer
336 if (!llvm::to_integer(key, idx))
339 sorted_threads[idx] = thread_info_sp->GetValueForKey(key);
343 size_t thread_count = thread_info_sp->GetSize();
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);
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;
357 return ScriptedInterface::ErrorWithMessage<bool>(
358 LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);
360 auto thread_or_error =
361 ScriptedThread::Create(*this, object_sp->GetAsGeneric());
363 if (!thread_or_error)
364 return ScriptedInterface::ErrorWithMessage<bool>(
365 LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error);
367 ThreadSP thread_sp = thread_or_error.get();
368 lldbassert(thread_sp && "Couldn't initialize scripted thread.");
370 RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
372 return ScriptedInterface::ErrorWithMessage<bool>(
373 LLVM_PRETTY_FUNCTION,
374 llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx))
378 new_thread_list.AddThread(thread_sp);
383 llvm::for_each(sorted_threads, create_scripted_thread);
385 return new_thread_list.GetSize(false) > 0;
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();
394 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
396 info.SetProcessID(GetID());
397 info.SetArchitecture(GetArchitecture());
398 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
400 const bool add_exe_file_as_first_arg = false;
401 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
402 add_exe_file_as_first_arg);
407 lldb_private::StructuredData::ObjectSP
408 ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
410 auto error_with_message = [&error](llvm::StringRef message) {
411 return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
412 message.data(), error);
415 StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages();
417 if (!loaded_images_sp || !loaded_images_sp->GetSize())
418 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
419 LLVM_PRETTY_FUNCTION, "No loaded images.", error);
421 ModuleList module_list;
422 Target &target = GetTarget();
424 auto reload_image = [&target, &module_list, &error_with_message](
425 StructuredData::Object *obj) -> bool {
426 StructuredData::Dictionary *dict = obj->GetAsDictionary();
429 return error_with_message("Couldn't cast image object into dictionary.");
431 ModuleSpec module_spec;
432 llvm::StringRef value;
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'");
442 dict->GetValueForKeyAsString("path", value);
443 module_spec.GetFileSpec().SetPath(value);
447 dict->GetValueForKeyAsString("uuid", value);
448 module_spec.GetUUID().SetFromStringRef(value);
450 module_spec.GetArchitecture() = target.GetArchitecture();
453 target.GetOrCreateModule(module_spec, true /* notify */);
456 return error_with_message("Couldn't create or get module.");
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.");
466 if (slide != LLDB_INVALID_OFFSET)
469 bool changed = false;
470 module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/,
473 if (!changed && !module_sp->GetObjectFile())
474 return error_with_message("Couldn't set the load address for module.");
476 dict->GetValueForKeyAsString("path", value);
477 FileSpec objfile(value);
478 module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename());
480 return module_list.AppendIfNeeded(module_sp);
483 if (!loaded_images_sp->ForEach(reload_image))
484 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
485 LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);
487 target.ModulesDidLoad(module_list);
489 return loaded_images_sp;
492 lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() {
493 StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata();
496 if (!metadata_sp || !metadata_sp->GetSize())
497 return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>(
498 LLVM_PRETTY_FUNCTION, "No metadata.", error);
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);
514 ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
515 CheckScriptedInterface();
516 return *m_interface_up;
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();