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 "Plugins/ObjectFile/Placeholder/ObjectFilePlaceholder.h"
29
30 #include <mutex>
31
32 LLDB_PLUGIN_DEFINE(ScriptedProcess)
33
34 using namespace lldb;
35 using namespace lldb_private;
36
GetPluginDescriptionStatic()37 llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() {
38 return "Scripted Process plug-in.";
39 }
40
41 static constexpr lldb::ScriptLanguage g_supported_script_languages[] = {
42 ScriptLanguage::eScriptLanguagePython,
43 };
44
IsScriptLanguageSupported(lldb::ScriptLanguage language)45 bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) {
46 llvm::ArrayRef<lldb::ScriptLanguage> supported_languages =
47 llvm::ArrayRef(g_supported_script_languages);
48
49 return llvm::is_contained(supported_languages, language);
50 }
51
CreateInstance(lldb::TargetSP target_sp,lldb::ListenerSP listener_sp,const FileSpec * file,bool can_connect)52 lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
53 lldb::ListenerSP listener_sp,
54 const FileSpec *file,
55 bool can_connect) {
56 if (!target_sp ||
57 !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage()))
58 return nullptr;
59
60 ScriptedMetadata scripted_metadata(target_sp->GetProcessLaunchInfo());
61
62 Status error;
63 auto process_sp = std::shared_ptr<ScriptedProcess>(
64 new ScriptedProcess(target_sp, listener_sp, scripted_metadata, error));
65
66 if (error.Fail() || !process_sp || !process_sp->m_interface_up) {
67 LLDB_LOGF(GetLog(LLDBLog::Process), "%s", error.AsCString());
68 return nullptr;
69 }
70
71 return process_sp;
72 }
73
CanDebug(lldb::TargetSP target_sp,bool plugin_specified_by_name)74 bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
75 bool plugin_specified_by_name) {
76 return true;
77 }
78
ScriptedProcess(lldb::TargetSP target_sp,lldb::ListenerSP listener_sp,const ScriptedMetadata & scripted_metadata,Status & error)79 ScriptedProcess::ScriptedProcess(lldb::TargetSP target_sp,
80 lldb::ListenerSP listener_sp,
81 const ScriptedMetadata &scripted_metadata,
82 Status &error)
83 : Process(target_sp, listener_sp), m_scripted_metadata(scripted_metadata) {
84
85 if (!target_sp) {
86 error = Status::FromErrorStringWithFormat(
87 "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__, "Invalid target");
88 return;
89 }
90
91 ScriptInterpreter *interpreter =
92 target_sp->GetDebugger().GetScriptInterpreter();
93
94 if (!interpreter) {
95 error = Status::FromErrorStringWithFormat(
96 "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__,
97 "Debugger has no Script Interpreter");
98 return;
99 }
100
101 // Create process instance interface
102 m_interface_up = interpreter->CreateScriptedProcessInterface();
103 if (!m_interface_up) {
104 error = Status::FromErrorStringWithFormat(
105 "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__,
106 "Script interpreter couldn't create Scripted Process Interface");
107 return;
108 }
109
110 ExecutionContext exe_ctx(target_sp, /*get_process=*/false);
111
112 // Create process script object
113 auto obj_or_err = GetInterface().CreatePluginObject(
114 m_scripted_metadata.GetClassName(), exe_ctx,
115 m_scripted_metadata.GetArgsSP());
116
117 if (!obj_or_err) {
118 llvm::consumeError(obj_or_err.takeError());
119 error = Status::FromErrorString("Failed to create script object.");
120 return;
121 }
122
123 StructuredData::GenericSP object_sp = *obj_or_err;
124
125 if (!object_sp || !object_sp->IsValid()) {
126 error = Status::FromErrorStringWithFormat(
127 "ScriptedProcess::%s () - ERROR: %s", __FUNCTION__,
128 "Failed to create valid script object");
129 return;
130 }
131 }
132
~ScriptedProcess()133 ScriptedProcess::~ScriptedProcess() {
134 Clear();
135 // If the interface is not valid, we can't call Finalize(). When that happens
136 // it means that the Scripted Process instanciation failed and the
137 // CreateProcess function returns a nullptr, so no one besides this class
138 // should have access to that bogus process object.
139 if (!m_interface_up)
140 return;
141 // We need to call finalize on the process before destroying ourselves to
142 // make sure all of the broadcaster cleanup goes as planned. If we destruct
143 // this class, then Process::~Process() might have problems trying to fully
144 // destroy the broadcaster.
145 Finalize(true /* destructing */);
146 }
147
Initialize()148 void ScriptedProcess::Initialize() {
149 static llvm::once_flag g_once_flag;
150
151 llvm::call_once(g_once_flag, []() {
152 PluginManager::RegisterPlugin(GetPluginNameStatic(),
153 GetPluginDescriptionStatic(), CreateInstance);
154 });
155 }
156
Terminate()157 void ScriptedProcess::Terminate() {
158 PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
159 }
160
DoLoadCore()161 Status ScriptedProcess::DoLoadCore() {
162 ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
163
164 return DoLaunch(nullptr, launch_info);
165 }
166
DoLaunch(Module * exe_module,ProcessLaunchInfo & launch_info)167 Status ScriptedProcess::DoLaunch(Module *exe_module,
168 ProcessLaunchInfo &launch_info) {
169 LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s launching process", __FUNCTION__);
170
171 /* MARK: This doesn't reflect how lldb actually launches a process.
172 In reality, it attaches to debugserver, then resume the process.
173 That's not true in all cases. If debugserver is remote, lldb
174 asks debugserver to launch the process for it. */
175 Status error = GetInterface().Launch();
176 SetPrivateState(eStateStopped);
177 return error;
178 }
179
DidLaunch()180 void ScriptedProcess::DidLaunch() { m_pid = GetInterface().GetProcessID(); }
181
DidResume()182 void ScriptedProcess::DidResume() {
183 // Update the PID again, in case the user provided a placeholder pid at launch
184 m_pid = GetInterface().GetProcessID();
185 }
186
DoResume(RunDirection direction)187 Status ScriptedProcess::DoResume(RunDirection direction) {
188 LLDB_LOGF(GetLog(LLDBLog::Process), "ScriptedProcess::%s resuming process", __FUNCTION__);
189
190 if (direction == RunDirection::eRunForward)
191 return GetInterface().Resume();
192 // FIXME: Pipe reverse continue through Scripted Processes
193 return Status::FromErrorStringWithFormatv(
194 "{0} does not support reverse execution of processes", GetPluginName());
195 }
196
DoAttach(const ProcessAttachInfo & attach_info)197 Status ScriptedProcess::DoAttach(const ProcessAttachInfo &attach_info) {
198 Status error = GetInterface().Attach(attach_info);
199 SetPrivateState(eStateRunning);
200 SetPrivateState(eStateStopped);
201 if (error.Fail())
202 return error;
203 // NOTE: We need to set the PID before finishing to attach otherwise we will
204 // hit an assert when calling the attach completion handler.
205 DidLaunch();
206
207 return {};
208 }
209
210 Status
DoAttachToProcessWithID(lldb::pid_t pid,const ProcessAttachInfo & attach_info)211 ScriptedProcess::DoAttachToProcessWithID(lldb::pid_t pid,
212 const ProcessAttachInfo &attach_info) {
213 return DoAttach(attach_info);
214 }
215
DoAttachToProcessWithName(const char * process_name,const ProcessAttachInfo & attach_info)216 Status ScriptedProcess::DoAttachToProcessWithName(
217 const char *process_name, const ProcessAttachInfo &attach_info) {
218 return DoAttach(attach_info);
219 }
220
DidAttach(ArchSpec & process_arch)221 void ScriptedProcess::DidAttach(ArchSpec &process_arch) {
222 process_arch = GetArchitecture();
223 }
224
DoDestroy()225 Status ScriptedProcess::DoDestroy() { return Status(); }
226
IsAlive()227 bool ScriptedProcess::IsAlive() { return GetInterface().IsAlive(); }
228
DoReadMemory(lldb::addr_t addr,void * buf,size_t size,Status & error)229 size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
230 Status &error) {
231 lldb::DataExtractorSP data_extractor_sp =
232 GetInterface().ReadMemoryAtAddress(addr, size, error);
233
234 if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
235 return 0;
236
237 offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
238 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
239
240 if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
241 return ScriptedInterface::ErrorWithMessage<size_t>(
242 LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error);
243
244 // FIXME: We should use the diagnostic system to report a warning if the
245 // `bytes_copied` is different from `size`.
246
247 return bytes_copied;
248 }
249
DoWriteMemory(lldb::addr_t vm_addr,const void * buf,size_t size,Status & error)250 size_t ScriptedProcess::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
251 size_t size, Status &error) {
252 lldb::DataExtractorSP data_extractor_sp = std::make_shared<DataExtractor>(
253 buf, size, GetByteOrder(), GetAddressByteSize());
254
255 if (!data_extractor_sp || !data_extractor_sp->GetByteSize())
256 return 0;
257
258 lldb::offset_t bytes_written =
259 GetInterface().WriteMemoryAtAddress(vm_addr, data_extractor_sp, error);
260
261 if (!bytes_written || bytes_written == LLDB_INVALID_OFFSET)
262 return ScriptedInterface::ErrorWithMessage<size_t>(
263 LLVM_PRETTY_FUNCTION, "Failed to copy write buffer to memory.", error);
264
265 // FIXME: We should use the diagnostic system to report a warning if the
266 // `bytes_written` is different from `size`.
267
268 return bytes_written;
269 }
270
EnableBreakpointSite(BreakpointSite * bp_site)271 Status ScriptedProcess::EnableBreakpointSite(BreakpointSite *bp_site) {
272 assert(bp_site != nullptr);
273
274 if (bp_site->IsEnabled()) {
275 return {};
276 }
277
278 if (bp_site->HardwareRequired()) {
279 return Status::FromErrorString(
280 "Scripted Processes don't support hardware breakpoints");
281 }
282
283 Status error;
284 GetInterface().CreateBreakpoint(bp_site->GetLoadAddress(), error);
285
286 return error;
287 }
288
GetArchitecture()289 ArchSpec ScriptedProcess::GetArchitecture() {
290 return GetTarget().GetArchitecture();
291 }
292
DoGetMemoryRegionInfo(lldb::addr_t load_addr,MemoryRegionInfo & region)293 Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
294 MemoryRegionInfo ®ion) {
295 Status error;
296 if (auto region_or_err =
297 GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
298 region = *region_or_err;
299
300 return error;
301 }
302
GetMemoryRegions(MemoryRegionInfos & region_list)303 Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) {
304 Status error;
305 lldb::addr_t address = 0;
306
307 while (auto region_or_err =
308 GetInterface().GetMemoryRegionContainingAddress(address, error)) {
309 if (error.Fail())
310 break;
311
312 MemoryRegionInfo &mem_region = *region_or_err;
313 auto range = mem_region.GetRange();
314 address += range.GetRangeBase() + range.GetByteSize();
315 region_list.push_back(mem_region);
316 }
317
318 return error;
319 }
320
Clear()321 void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
322
DoUpdateThreadList(ThreadList & old_thread_list,ThreadList & new_thread_list)323 bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
324 ThreadList &new_thread_list) {
325 // TODO: Implement
326 // This is supposed to get the current set of threads, if any of them are in
327 // old_thread_list then they get copied to new_thread_list, and then any
328 // actually new threads will get added to new_thread_list.
329 m_thread_plans.ClearThreadCache();
330
331 Status error;
332 StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo();
333
334 if (!thread_info_sp)
335 return ScriptedInterface::ErrorWithMessage<bool>(
336 LLVM_PRETTY_FUNCTION,
337 "Couldn't fetch thread list from Scripted Process.", error);
338
339 // Because `StructuredData::Dictionary` uses a `std::map<ConstString,
340 // ObjectSP>` for storage, each item is sorted based on the key alphabetical
341 // order. Since `GetThreadsInfo` provides thread indices as the key element,
342 // thread info comes ordered alphabetically, instead of numerically, so we
343 // need to sort the thread indices before creating thread.
344
345 StructuredData::ArraySP keys = thread_info_sp->GetKeys();
346
347 std::map<size_t, StructuredData::ObjectSP> sorted_threads;
348 auto sort_keys = [&sorted_threads,
349 &thread_info_sp](StructuredData::Object *item) -> bool {
350 if (!item)
351 return false;
352
353 llvm::StringRef key = item->GetStringValue();
354 size_t idx = 0;
355
356 // Make sure the provided index is actually an integer
357 if (!llvm::to_integer(key, idx))
358 return false;
359
360 sorted_threads[idx] = thread_info_sp->GetValueForKey(key);
361 return true;
362 };
363
364 size_t thread_count = thread_info_sp->GetSize();
365
366 if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count)
367 // Might be worth showing the unsorted thread list instead of return early.
368 return ScriptedInterface::ErrorWithMessage<bool>(
369 LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error);
370
371 auto create_scripted_thread =
372 [this, &error, &new_thread_list](
373 const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool {
374 size_t idx = pair.first;
375 StructuredData::ObjectSP object_sp = pair.second;
376
377 if (!object_sp)
378 return ScriptedInterface::ErrorWithMessage<bool>(
379 LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);
380
381 auto thread_or_error =
382 ScriptedThread::Create(*this, object_sp->GetAsGeneric());
383
384 if (!thread_or_error)
385 return ScriptedInterface::ErrorWithMessage<bool>(
386 LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error);
387
388 ThreadSP thread_sp = thread_or_error.get();
389 lldbassert(thread_sp && "Couldn't initialize scripted thread.");
390
391 RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
392 if (!reg_ctx_sp)
393 return ScriptedInterface::ErrorWithMessage<bool>(
394 LLVM_PRETTY_FUNCTION,
395 llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx))
396 .str(),
397 error);
398
399 new_thread_list.AddThread(thread_sp);
400
401 return true;
402 };
403
404 llvm::for_each(sorted_threads, create_scripted_thread);
405
406 return new_thread_list.GetSize(false) > 0;
407 }
408
RefreshStateAfterStop()409 void ScriptedProcess::RefreshStateAfterStop() {
410 // Let all threads recover from stopping and do any clean up based on the
411 // previous thread state (if any).
412 m_thread_list.RefreshStateAfterStop();
413 }
414
GetProcessInfo(ProcessInstanceInfo & info)415 bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
416 info.Clear();
417 info.SetProcessID(GetID());
418 info.SetArchitecture(GetArchitecture());
419 lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
420 if (module_sp) {
421 const bool add_exe_file_as_first_arg = false;
422 info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
423 add_exe_file_as_first_arg);
424 }
425 return true;
426 }
427
428 lldb_private::StructuredData::ObjectSP
GetLoadedDynamicLibrariesInfos()429 ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
430 Status error;
431 auto error_with_message = [&error](llvm::StringRef message) {
432 return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
433 message.data(), error);
434 };
435
436 StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages();
437
438 if (!loaded_images_sp || !loaded_images_sp->GetSize())
439 return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
440 LLVM_PRETTY_FUNCTION, "No loaded images.", error);
441
442 ModuleList module_list;
443 Target &target = GetTarget();
444
445 auto reload_image = [&target, &module_list, &error_with_message](
446 StructuredData::Object *obj) -> bool {
447 StructuredData::Dictionary *dict = obj->GetAsDictionary();
448
449 if (!dict)
450 return error_with_message("Couldn't cast image object into dictionary.");
451
452 ModuleSpec module_spec;
453
454 bool has_path = dict->HasKey("path");
455 bool has_uuid = dict->HasKey("uuid");
456 if (!has_path && !has_uuid)
457 return error_with_message("Dictionary should have key 'path' or 'uuid'");
458 if (!dict->HasKey("load_addr"))
459 return error_with_message("Dictionary is missing key 'load_addr'");
460
461 llvm::StringRef path = "";
462 if (has_path) {
463 dict->GetValueForKeyAsString("path", path);
464 module_spec.GetFileSpec().SetPath(path);
465 }
466
467 llvm::StringRef uuid = "";
468 if (has_uuid) {
469 dict->GetValueForKeyAsString("uuid", uuid);
470 module_spec.GetUUID().SetFromStringRef(uuid);
471 }
472
473 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
474 lldb::offset_t slide = LLDB_INVALID_OFFSET;
475 dict->GetValueForKeyAsInteger("load_addr", load_addr);
476 dict->GetValueForKeyAsInteger("slide", slide);
477 if (load_addr == LLDB_INVALID_ADDRESS)
478 return error_with_message(
479 "Couldn't get valid load address or slide offset.");
480
481 if (slide != LLDB_INVALID_OFFSET)
482 load_addr += slide;
483
484 module_spec.GetArchitecture() = target.GetArchitecture();
485
486 ModuleSP module_sp =
487 target.GetOrCreateModule(module_spec, true /* notify */);
488
489 bool is_placeholder_module = false;
490
491 if (!module_sp) {
492 // Create a placeholder module
493 LLDB_LOGF(
494 GetLog(LLDBLog::Process),
495 "ScriptedProcess::%s unable to locate the matching "
496 "object file path %s, creating a placeholder module at 0x%" PRIx64,
497 __FUNCTION__, path.str().c_str(), load_addr);
498
499 module_sp = Module::CreateModuleFromObjectFile<ObjectFilePlaceholder>(
500 module_spec, load_addr, module_spec.GetFileSpec().MemorySize());
501
502 is_placeholder_module = true;
503 }
504
505 bool changed = false;
506 module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/,
507 changed);
508
509 if (!changed && !module_sp->GetObjectFile())
510 return error_with_message("Couldn't set the load address for module.");
511
512 FileSpec objfile(path);
513 module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename());
514
515 if (is_placeholder_module) {
516 target.GetImages().AppendIfNeeded(module_sp, true /*notify=*/);
517 return true;
518 }
519
520 return module_list.AppendIfNeeded(module_sp);
521 };
522
523 size_t loaded_images_size = loaded_images_sp->GetSize();
524 bool print_error = true;
525 for (size_t idx = 0; idx < loaded_images_size; idx++) {
526 const auto &loaded_image = loaded_images_sp->GetItemAtIndex(idx);
527 if (!reload_image(loaded_image.get()) && print_error) {
528 print_error = false;
529 ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
530 LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);
531 }
532 }
533
534 target.ModulesDidLoad(module_list);
535
536 return loaded_images_sp;
537 }
538
GetMetadata()539 lldb_private::StructuredData::DictionarySP ScriptedProcess::GetMetadata() {
540 StructuredData::DictionarySP metadata_sp = GetInterface().GetMetadata();
541
542 Status error;
543 if (!metadata_sp || !metadata_sp->GetSize())
544 return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>(
545 LLVM_PRETTY_FUNCTION, "No metadata.", error);
546
547 return metadata_sp;
548 }
549
UpdateQueueListIfNeeded()550 void ScriptedProcess::UpdateQueueListIfNeeded() {
551 CheckScriptedInterface();
552 for (ThreadSP thread_sp : Threads()) {
553 if (const char *queue_name = thread_sp->GetQueueName()) {
554 QueueSP queue_sp = std::make_shared<Queue>(
555 m_process->shared_from_this(), thread_sp->GetQueueID(), queue_name);
556 m_queue_list.AddQueue(queue_sp);
557 }
558 }
559 }
560
GetInterface() const561 ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
562 CheckScriptedInterface();
563 return *m_interface_up;
564 }
565
GetImplementation()566 void *ScriptedProcess::GetImplementation() {
567 StructuredData::GenericSP object_instance_sp =
568 GetInterface().GetScriptObjectInstance();
569 if (object_instance_sp &&
570 object_instance_sp->GetType() == eStructuredDataTypeGeneric)
571 return object_instance_sp->GetAsGeneric()->GetValue();
572 return nullptr;
573 }
574