1312b43daSMed Ismail Bennani //===-- ScriptedProcess.cpp -----------------------------------------------===//
2312b43daSMed Ismail Bennani //
3312b43daSMed Ismail Bennani // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4312b43daSMed Ismail Bennani // See https://llvm.org/LICENSE.txt for license information.
5312b43daSMed Ismail Bennani // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6312b43daSMed Ismail Bennani //
7312b43daSMed Ismail Bennani //===----------------------------------------------------------------------===//
8312b43daSMed Ismail Bennani
9312b43daSMed Ismail Bennani #include "ScriptedProcess.h"
10312b43daSMed Ismail Bennani
11312b43daSMed Ismail Bennani #include "lldb/Core/Debugger.h"
12312b43daSMed Ismail Bennani #include "lldb/Core/Module.h"
13312b43daSMed Ismail Bennani #include "lldb/Core/PluginManager.h"
14312b43daSMed Ismail Bennani
15312b43daSMed Ismail Bennani #include "lldb/Host/OptionParser.h"
16312b43daSMed Ismail Bennani #include "lldb/Host/ThreadLauncher.h"
17312b43daSMed Ismail Bennani #include "lldb/Interpreter/CommandInterpreter.h"
18312b43daSMed Ismail Bennani #include "lldb/Interpreter/OptionArgParser.h"
19312b43daSMed Ismail Bennani #include "lldb/Interpreter/OptionGroupBoolean.h"
20312b43daSMed Ismail Bennani #include "lldb/Interpreter/ScriptInterpreter.h"
21312b43daSMed Ismail Bennani #include "lldb/Target/MemoryRegionInfo.h"
22312b43daSMed Ismail Bennani #include "lldb/Target/RegisterContext.h"
23c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
24312b43daSMed Ismail Bennani #include "lldb/Utility/State.h"
25312b43daSMed Ismail Bennani
26312b43daSMed Ismail Bennani #include <mutex>
27312b43daSMed Ismail Bennani
28312b43daSMed Ismail Bennani LLDB_PLUGIN_DEFINE(ScriptedProcess)
29312b43daSMed Ismail Bennani
30312b43daSMed Ismail Bennani using namespace lldb;
31312b43daSMed Ismail Bennani using namespace lldb_private;
32312b43daSMed Ismail Bennani
GetPluginDescriptionStatic()335f4980f0SPavel Labath llvm::StringRef ScriptedProcess::GetPluginDescriptionStatic() {
34312b43daSMed Ismail Bennani return "Scripted Process plug-in.";
35312b43daSMed Ismail Bennani }
36312b43daSMed Ismail Bennani
37312b43daSMed Ismail Bennani static constexpr lldb::ScriptLanguage g_supported_script_languages[] = {
38312b43daSMed Ismail Bennani ScriptLanguage::eScriptLanguagePython,
39312b43daSMed Ismail Bennani };
40312b43daSMed Ismail Bennani
IsScriptLanguageSupported(lldb::ScriptLanguage language)41312b43daSMed Ismail Bennani bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) {
42312b43daSMed Ismail Bennani llvm::ArrayRef<lldb::ScriptLanguage> supported_languages =
43312b43daSMed Ismail Bennani llvm::makeArrayRef(g_supported_script_languages);
44312b43daSMed Ismail Bennani
45312b43daSMed Ismail Bennani return llvm::is_contained(supported_languages, language);
46312b43daSMed Ismail Bennani }
47312b43daSMed Ismail Bennani
CheckInterpreterAndScriptObject() const48312b43daSMed Ismail Bennani void ScriptedProcess::CheckInterpreterAndScriptObject() const {
49312b43daSMed Ismail Bennani lldbassert(m_interpreter && "Invalid Script Interpreter.");
50312b43daSMed Ismail Bennani lldbassert(m_script_object_sp && "Invalid Script Object.");
51312b43daSMed Ismail Bennani }
52312b43daSMed Ismail Bennani
CreateInstance(lldb::TargetSP target_sp,lldb::ListenerSP listener_sp,const FileSpec * file,bool can_connect)53312b43daSMed Ismail Bennani lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
54312b43daSMed Ismail Bennani lldb::ListenerSP listener_sp,
55312b43daSMed Ismail Bennani const FileSpec *file,
56312b43daSMed Ismail Bennani bool can_connect) {
57312b43daSMed Ismail Bennani if (!target_sp ||
58312b43daSMed Ismail Bennani !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage()))
59312b43daSMed Ismail Bennani return nullptr;
60312b43daSMed Ismail Bennani
61312b43daSMed Ismail Bennani Status error;
62312b43daSMed Ismail Bennani ScriptedProcess::ScriptedProcessInfo scripted_process_info(
63312b43daSMed Ismail Bennani target_sp->GetProcessLaunchInfo());
64312b43daSMed Ismail Bennani
65312b43daSMed Ismail Bennani auto process_sp = std::make_shared<ScriptedProcess>(
66312b43daSMed Ismail Bennani target_sp, listener_sp, scripted_process_info, error);
67312b43daSMed Ismail Bennani
68312b43daSMed Ismail Bennani if (error.Fail() || !process_sp || !process_sp->m_script_object_sp ||
69312b43daSMed Ismail Bennani !process_sp->m_script_object_sp->IsValid()) {
70a007a6d8SPavel Labath LLDB_LOGF(GetLog(LLDBLog::Process), "%s", error.AsCString());
71312b43daSMed Ismail Bennani return nullptr;
72312b43daSMed Ismail Bennani }
73312b43daSMed Ismail Bennani
74312b43daSMed Ismail Bennani return process_sp;
75312b43daSMed Ismail Bennani }
76312b43daSMed Ismail Bennani
CanDebug(lldb::TargetSP target_sp,bool plugin_specified_by_name)77312b43daSMed Ismail Bennani bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
78312b43daSMed Ismail Bennani bool plugin_specified_by_name) {
79312b43daSMed Ismail Bennani return true;
80312b43daSMed Ismail Bennani }
81312b43daSMed Ismail Bennani
ScriptedProcess(lldb::TargetSP target_sp,lldb::ListenerSP listener_sp,const ScriptedProcess::ScriptedProcessInfo & scripted_process_info,Status & error)82312b43daSMed Ismail Bennani ScriptedProcess::ScriptedProcess(
83312b43daSMed Ismail Bennani lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
84312b43daSMed Ismail Bennani const ScriptedProcess::ScriptedProcessInfo &scripted_process_info,
85312b43daSMed Ismail Bennani Status &error)
86312b43daSMed Ismail Bennani : Process(target_sp, listener_sp),
87312b43daSMed Ismail Bennani m_scripted_process_info(scripted_process_info) {
88312b43daSMed Ismail Bennani
89312b43daSMed Ismail Bennani if (!target_sp) {
90312b43daSMed Ismail Bennani error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
91312b43daSMed Ismail Bennani __FUNCTION__, "Invalid target");
92312b43daSMed Ismail Bennani return;
93312b43daSMed Ismail Bennani }
94312b43daSMed Ismail Bennani
95312b43daSMed Ismail Bennani m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();
96312b43daSMed Ismail Bennani
97312b43daSMed Ismail Bennani if (!m_interpreter) {
98312b43daSMed Ismail Bennani error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
99312b43daSMed Ismail Bennani __FUNCTION__,
100312b43daSMed Ismail Bennani "Debugger has no Script Interpreter");
101312b43daSMed Ismail Bennani return;
102312b43daSMed Ismail Bennani }
103312b43daSMed Ismail Bennani
1043925204cSMed Ismail Bennani ExecutionContext exe_ctx(target_sp, /*get_process=*/false);
1053925204cSMed Ismail Bennani
1063925204cSMed Ismail Bennani StructuredData::GenericSP object_sp = GetInterface().CreatePluginObject(
1073925204cSMed Ismail Bennani m_scripted_process_info.GetClassName().c_str(), exe_ctx,
108ad0f7d3dSMed Ismail Bennani m_scripted_process_info.GetArgsSP());
109312b43daSMed Ismail Bennani
110312b43daSMed Ismail Bennani if (!object_sp || !object_sp->IsValid()) {
111312b43daSMed Ismail Bennani error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
112312b43daSMed Ismail Bennani __FUNCTION__,
113312b43daSMed Ismail Bennani "Failed to create valid script object");
114312b43daSMed Ismail Bennani return;
115312b43daSMed Ismail Bennani }
116312b43daSMed Ismail Bennani
117312b43daSMed Ismail Bennani m_script_object_sp = object_sp;
118312b43daSMed Ismail Bennani }
119312b43daSMed Ismail Bennani
~ScriptedProcess()120312b43daSMed Ismail Bennani ScriptedProcess::~ScriptedProcess() {
121312b43daSMed Ismail Bennani Clear();
122312b43daSMed Ismail Bennani // We need to call finalize on the process before destroying ourselves to
123312b43daSMed Ismail Bennani // make sure all of the broadcaster cleanup goes as planned. If we destruct
124312b43daSMed Ismail Bennani // this class, then Process::~Process() might have problems trying to fully
125312b43daSMed Ismail Bennani // destroy the broadcaster.
126312b43daSMed Ismail Bennani Finalize();
127312b43daSMed Ismail Bennani }
128312b43daSMed Ismail Bennani
Initialize()129312b43daSMed Ismail Bennani void ScriptedProcess::Initialize() {
130312b43daSMed Ismail Bennani static llvm::once_flag g_once_flag;
131312b43daSMed Ismail Bennani
132312b43daSMed Ismail Bennani llvm::call_once(g_once_flag, []() {
133312b43daSMed Ismail Bennani PluginManager::RegisterPlugin(GetPluginNameStatic(),
134312b43daSMed Ismail Bennani GetPluginDescriptionStatic(), CreateInstance);
135312b43daSMed Ismail Bennani });
136312b43daSMed Ismail Bennani }
137312b43daSMed Ismail Bennani
Terminate()138312b43daSMed Ismail Bennani void ScriptedProcess::Terminate() {
139312b43daSMed Ismail Bennani PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
140312b43daSMed Ismail Bennani }
141312b43daSMed Ismail Bennani
DoLoadCore()142312b43daSMed Ismail Bennani Status ScriptedProcess::DoLoadCore() {
143312b43daSMed Ismail Bennani ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
144312b43daSMed Ismail Bennani
145312b43daSMed Ismail Bennani return DoLaunch(nullptr, launch_info);
146312b43daSMed Ismail Bennani }
147312b43daSMed Ismail Bennani
DoLaunch(Module * exe_module,ProcessLaunchInfo & launch_info)148312b43daSMed Ismail Bennani Status ScriptedProcess::DoLaunch(Module *exe_module,
149312b43daSMed Ismail Bennani ProcessLaunchInfo &launch_info) {
150312b43daSMed Ismail Bennani CheckInterpreterAndScriptObject();
151312b43daSMed Ismail Bennani
152312b43daSMed Ismail Bennani /* FIXME: This doesn't reflect how lldb actually launches a process.
153312b43daSMed Ismail Bennani In reality, it attaches to debugserver, then resume the process. */
154312b43daSMed Ismail Bennani Status error = GetInterface().Launch();
155312b43daSMed Ismail Bennani SetPrivateState(eStateRunning);
156312b43daSMed Ismail Bennani
157312b43daSMed Ismail Bennani if (error.Fail())
158312b43daSMed Ismail Bennani return error;
159312b43daSMed Ismail Bennani
160312b43daSMed Ismail Bennani // TODO: Fetch next state from stopped event queue then send stop event
161312b43daSMed Ismail Bennani // const StateType state = SetThreadStopInfo(response);
162312b43daSMed Ismail Bennani // if (state != eStateInvalid) {
163312b43daSMed Ismail Bennani // SetPrivateState(state);
164312b43daSMed Ismail Bennani
165312b43daSMed Ismail Bennani SetPrivateState(eStateStopped);
166312b43daSMed Ismail Bennani
167312b43daSMed Ismail Bennani return {};
168312b43daSMed Ismail Bennani }
169312b43daSMed Ismail Bennani
DidLaunch()170312b43daSMed Ismail Bennani void ScriptedProcess::DidLaunch() {
171312b43daSMed Ismail Bennani CheckInterpreterAndScriptObject();
172312b43daSMed Ismail Bennani m_pid = GetInterface().GetProcessID();
173680ca7f2SMed Ismail Bennani GetLoadedDynamicLibrariesInfos();
174312b43daSMed Ismail Bennani }
175312b43daSMed Ismail Bennani
DoResume()176312b43daSMed Ismail Bennani Status ScriptedProcess::DoResume() {
177312b43daSMed Ismail Bennani CheckInterpreterAndScriptObject();
178312b43daSMed Ismail Bennani
179a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Process);
180312b43daSMed Ismail Bennani // FIXME: Fetch data from thread.
181312b43daSMed Ismail Bennani const StateType thread_resume_state = eStateRunning;
182312b43daSMed Ismail Bennani LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__,
183312b43daSMed Ismail Bennani StateAsCString(thread_resume_state));
184312b43daSMed Ismail Bennani
185312b43daSMed Ismail Bennani bool resume = (thread_resume_state == eStateRunning);
186312b43daSMed Ismail Bennani assert(thread_resume_state == eStateRunning && "invalid thread resume state");
187312b43daSMed Ismail Bennani
188312b43daSMed Ismail Bennani Status error;
189312b43daSMed Ismail Bennani if (resume) {
190312b43daSMed Ismail Bennani LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__);
191312b43daSMed Ismail Bennani
192312b43daSMed Ismail Bennani SetPrivateState(eStateRunning);
193312b43daSMed Ismail Bennani SetPrivateState(eStateStopped);
194312b43daSMed Ismail Bennani error = GetInterface().Resume();
195312b43daSMed Ismail Bennani }
196312b43daSMed Ismail Bennani
197312b43daSMed Ismail Bennani return error;
198312b43daSMed Ismail Bennani }
199312b43daSMed Ismail Bennani
DoStop()200312b43daSMed Ismail Bennani Status ScriptedProcess::DoStop() {
201312b43daSMed Ismail Bennani CheckInterpreterAndScriptObject();
202312b43daSMed Ismail Bennani
203a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Process);
204312b43daSMed Ismail Bennani
205312b43daSMed Ismail Bennani if (GetInterface().ShouldStop()) {
206312b43daSMed Ismail Bennani SetPrivateState(eStateStopped);
207312b43daSMed Ismail Bennani LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__);
208312b43daSMed Ismail Bennani return {};
209312b43daSMed Ismail Bennani }
210312b43daSMed Ismail Bennani
211312b43daSMed Ismail Bennani LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__);
212312b43daSMed Ismail Bennani return GetInterface().Stop();
213312b43daSMed Ismail Bennani }
214312b43daSMed Ismail Bennani
DoDestroy()215312b43daSMed Ismail Bennani Status ScriptedProcess::DoDestroy() { return Status(); }
216312b43daSMed Ismail Bennani
IsAlive()217312b43daSMed Ismail Bennani bool ScriptedProcess::IsAlive() {
218312b43daSMed Ismail Bennani if (m_interpreter && m_script_object_sp)
219312b43daSMed Ismail Bennani return GetInterface().IsAlive();
220312b43daSMed Ismail Bennani return false;
221312b43daSMed Ismail Bennani }
222312b43daSMed Ismail Bennani
DoReadMemory(lldb::addr_t addr,void * buf,size_t size,Status & error)223312b43daSMed Ismail Bennani size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
224312b43daSMed Ismail Bennani Status &error) {
225312b43daSMed Ismail Bennani if (!m_interpreter)
22691bb1161SMed Ismail Bennani return ScriptedInterface::ErrorWithMessage<size_t>(
22791bb1161SMed Ismail Bennani LLVM_PRETTY_FUNCTION, "No interpreter.", error);
228312b43daSMed Ismail Bennani
229312b43daSMed Ismail Bennani lldb::DataExtractorSP data_extractor_sp =
230312b43daSMed Ismail Bennani GetInterface().ReadMemoryAtAddress(addr, size, error);
231312b43daSMed Ismail Bennani
232a758c9f7SMed Ismail Bennani if (!data_extractor_sp || !data_extractor_sp->GetByteSize() || error.Fail())
233312b43daSMed Ismail Bennani return 0;
234312b43daSMed Ismail Bennani
235312b43daSMed Ismail Bennani offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
236312b43daSMed Ismail Bennani 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
237312b43daSMed Ismail Bennani
238312b43daSMed Ismail Bennani if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
23991bb1161SMed Ismail Bennani return ScriptedInterface::ErrorWithMessage<size_t>(
24088a941baSMed Ismail Bennani LLVM_PRETTY_FUNCTION, "Failed to copy read memory to buffer.", error);
241312b43daSMed Ismail Bennani
242312b43daSMed Ismail Bennani return size;
243312b43daSMed Ismail Bennani }
244312b43daSMed Ismail Bennani
GetArchitecture()245312b43daSMed Ismail Bennani ArchSpec ScriptedProcess::GetArchitecture() {
246312b43daSMed Ismail Bennani return GetTarget().GetArchitecture();
247312b43daSMed Ismail Bennani }
248312b43daSMed Ismail Bennani
DoGetMemoryRegionInfo(lldb::addr_t load_addr,MemoryRegionInfo & region)2492937b282SDavid Spickett Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
250312b43daSMed Ismail Bennani MemoryRegionInfo ®ion) {
251a758c9f7SMed Ismail Bennani CheckInterpreterAndScriptObject();
252a758c9f7SMed Ismail Bennani
253a758c9f7SMed Ismail Bennani Status error;
254a758c9f7SMed Ismail Bennani if (auto region_or_err =
255a758c9f7SMed Ismail Bennani GetInterface().GetMemoryRegionContainingAddress(load_addr, error))
256a758c9f7SMed Ismail Bennani region = *region_or_err;
257a758c9f7SMed Ismail Bennani
258a758c9f7SMed Ismail Bennani return error;
259312b43daSMed Ismail Bennani }
260312b43daSMed Ismail Bennani
GetMemoryRegions(MemoryRegionInfos & region_list)261312b43daSMed Ismail Bennani Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) {
262312b43daSMed Ismail Bennani CheckInterpreterAndScriptObject();
263312b43daSMed Ismail Bennani
264a758c9f7SMed Ismail Bennani Status error;
265312b43daSMed Ismail Bennani lldb::addr_t address = 0;
266312b43daSMed Ismail Bennani
267a758c9f7SMed Ismail Bennani while (auto region_or_err =
268a758c9f7SMed Ismail Bennani GetInterface().GetMemoryRegionContainingAddress(address, error)) {
269a758c9f7SMed Ismail Bennani if (error.Fail())
270a758c9f7SMed Ismail Bennani break;
271a758c9f7SMed Ismail Bennani
272a758c9f7SMed Ismail Bennani MemoryRegionInfo &mem_region = *region_or_err;
273a758c9f7SMed Ismail Bennani auto range = mem_region.GetRange();
274312b43daSMed Ismail Bennani address += range.GetRangeBase() + range.GetByteSize();
275a758c9f7SMed Ismail Bennani region_list.push_back(mem_region);
276312b43daSMed Ismail Bennani }
277312b43daSMed Ismail Bennani
278a758c9f7SMed Ismail Bennani return error;
279312b43daSMed Ismail Bennani }
280312b43daSMed Ismail Bennani
Clear()281312b43daSMed Ismail Bennani void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
282312b43daSMed Ismail Bennani
DoUpdateThreadList(ThreadList & old_thread_list,ThreadList & new_thread_list)283312b43daSMed Ismail Bennani bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
284312b43daSMed Ismail Bennani ThreadList &new_thread_list) {
285312b43daSMed Ismail Bennani // TODO: Implement
286312b43daSMed Ismail Bennani // This is supposed to get the current set of threads, if any of them are in
287312b43daSMed Ismail Bennani // old_thread_list then they get copied to new_thread_list, and then any
288312b43daSMed Ismail Bennani // actually new threads will get added to new_thread_list.
28959d8dd79SMed Ismail Bennani
29059d8dd79SMed Ismail Bennani CheckInterpreterAndScriptObject();
291676576b6SMed Ismail Bennani m_thread_plans.ClearThreadCache();
29259d8dd79SMed Ismail Bennani
29359d8dd79SMed Ismail Bennani Status error;
29459d8dd79SMed Ismail Bennani ScriptLanguage language = m_interpreter->GetLanguage();
29559d8dd79SMed Ismail Bennani
29659d8dd79SMed Ismail Bennani if (language != eScriptLanguagePython)
29791bb1161SMed Ismail Bennani return ScriptedInterface::ErrorWithMessage<bool>(
29888a941baSMed Ismail Bennani LLVM_PRETTY_FUNCTION,
29959d8dd79SMed Ismail Bennani llvm::Twine("ScriptInterpreter language (" +
30059d8dd79SMed Ismail Bennani llvm::Twine(m_interpreter->LanguageToString(language)) +
30159d8dd79SMed Ismail Bennani llvm::Twine(") not supported."))
30259d8dd79SMed Ismail Bennani .str(),
30359d8dd79SMed Ismail Bennani error);
30459d8dd79SMed Ismail Bennani
305d3e0f7e1SMed Ismail Bennani StructuredData::DictionarySP thread_info_sp = GetInterface().GetThreadsInfo();
306d3e0f7e1SMed Ismail Bennani
307d3e0f7e1SMed Ismail Bennani if (!thread_info_sp)
30891bb1161SMed Ismail Bennani return ScriptedInterface::ErrorWithMessage<bool>(
309d3e0f7e1SMed Ismail Bennani LLVM_PRETTY_FUNCTION,
310d3e0f7e1SMed Ismail Bennani "Couldn't fetch thread list from Scripted Process.", error);
311d3e0f7e1SMed Ismail Bennani
312*150db43eSMed Ismail Bennani // Because `StructuredData::Dictionary` uses a `std::map<ConstString,
313*150db43eSMed Ismail Bennani // ObjectSP>` for storage, each item is sorted based on the key alphabetical
314*150db43eSMed Ismail Bennani // order. Since `GetThreadsInfo` provides thread indices as the key element,
315*150db43eSMed Ismail Bennani // thread info comes ordered alphabetically, instead of numerically, so we
316*150db43eSMed Ismail Bennani // need to sort the thread indices before creating thread.
317*150db43eSMed Ismail Bennani
318*150db43eSMed Ismail Bennani StructuredData::ArraySP keys = thread_info_sp->GetKeys();
319*150db43eSMed Ismail Bennani
320*150db43eSMed Ismail Bennani std::map<size_t, StructuredData::ObjectSP> sorted_threads;
321*150db43eSMed Ismail Bennani auto sort_keys = [&sorted_threads,
322*150db43eSMed Ismail Bennani &thread_info_sp](StructuredData::Object *item) -> bool {
323*150db43eSMed Ismail Bennani if (!item)
324*150db43eSMed Ismail Bennani return false;
325*150db43eSMed Ismail Bennani
326*150db43eSMed Ismail Bennani llvm::StringRef key = item->GetStringValue();
327*150db43eSMed Ismail Bennani size_t idx = 0;
328*150db43eSMed Ismail Bennani
329*150db43eSMed Ismail Bennani // Make sure the provided index is actually an integer
330*150db43eSMed Ismail Bennani if (!llvm::to_integer(key, idx))
331*150db43eSMed Ismail Bennani return false;
332*150db43eSMed Ismail Bennani
333*150db43eSMed Ismail Bennani sorted_threads[idx] = thread_info_sp->GetValueForKey(key);
334*150db43eSMed Ismail Bennani return true;
335*150db43eSMed Ismail Bennani };
336*150db43eSMed Ismail Bennani
337*150db43eSMed Ismail Bennani size_t thread_count = thread_info_sp->GetSize();
338*150db43eSMed Ismail Bennani
339*150db43eSMed Ismail Bennani if (!keys->ForEach(sort_keys) || sorted_threads.size() != thread_count)
340*150db43eSMed Ismail Bennani // Might be worth showing the unsorted thread list instead of return early.
341*150db43eSMed Ismail Bennani return ScriptedInterface::ErrorWithMessage<bool>(
342*150db43eSMed Ismail Bennani LLVM_PRETTY_FUNCTION, "Couldn't sort thread list.", error);
343*150db43eSMed Ismail Bennani
344d3e0f7e1SMed Ismail Bennani auto create_scripted_thread =
345*150db43eSMed Ismail Bennani [this, &error, &new_thread_list](
346*150db43eSMed Ismail Bennani const std::pair<size_t, StructuredData::ObjectSP> pair) -> bool {
347*150db43eSMed Ismail Bennani size_t idx = pair.first;
348*150db43eSMed Ismail Bennani StructuredData::ObjectSP object_sp = pair.second;
349*150db43eSMed Ismail Bennani
350*150db43eSMed Ismail Bennani if (!object_sp)
35191bb1161SMed Ismail Bennani return ScriptedInterface::ErrorWithMessage<bool>(
352d3e0f7e1SMed Ismail Bennani LLVM_PRETTY_FUNCTION, "Invalid thread info object", error);
353d3e0f7e1SMed Ismail Bennani
354*150db43eSMed Ismail Bennani auto thread_or_error =
355*150db43eSMed Ismail Bennani ScriptedThread::Create(*this, object_sp->GetAsGeneric());
35659d8dd79SMed Ismail Bennani
35745148bfeSMed Ismail Bennani if (!thread_or_error)
35891bb1161SMed Ismail Bennani return ScriptedInterface::ErrorWithMessage<bool>(
35945148bfeSMed Ismail Bennani LLVM_PRETTY_FUNCTION, toString(thread_or_error.takeError()), error);
36045148bfeSMed Ismail Bennani
36145148bfeSMed Ismail Bennani ThreadSP thread_sp = thread_or_error.get();
36245148bfeSMed Ismail Bennani lldbassert(thread_sp && "Couldn't initialize scripted thread.");
36359d8dd79SMed Ismail Bennani
364caea440aSMed Ismail Bennani RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
365caea440aSMed Ismail Bennani if (!reg_ctx_sp)
36691bb1161SMed Ismail Bennani return ScriptedInterface::ErrorWithMessage<bool>(
367d3e0f7e1SMed Ismail Bennani LLVM_PRETTY_FUNCTION,
368*150db43eSMed Ismail Bennani llvm::Twine("Invalid Register Context for thread " + llvm::Twine(idx))
369d3e0f7e1SMed Ismail Bennani .str(),
370d3e0f7e1SMed Ismail Bennani error);
371caea440aSMed Ismail Bennani
37259d8dd79SMed Ismail Bennani new_thread_list.AddThread(thread_sp);
37359d8dd79SMed Ismail Bennani
374d3e0f7e1SMed Ismail Bennani return true;
375d3e0f7e1SMed Ismail Bennani };
376d3e0f7e1SMed Ismail Bennani
377*150db43eSMed Ismail Bennani llvm::for_each(sorted_threads, create_scripted_thread);
378d3e0f7e1SMed Ismail Bennani
379312b43daSMed Ismail Bennani return new_thread_list.GetSize(false) > 0;
380312b43daSMed Ismail Bennani }
381312b43daSMed Ismail Bennani
RefreshStateAfterStop()382676576b6SMed Ismail Bennani void ScriptedProcess::RefreshStateAfterStop() {
383676576b6SMed Ismail Bennani // Let all threads recover from stopping and do any clean up based on the
384676576b6SMed Ismail Bennani // previous thread state (if any).
38570665844SMed Ismail Bennani m_thread_list.RefreshStateAfterStop();
386676576b6SMed Ismail Bennani }
387676576b6SMed Ismail Bennani
GetProcessInfo(ProcessInstanceInfo & info)388312b43daSMed Ismail Bennani bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
389312b43daSMed Ismail Bennani info.Clear();
390312b43daSMed Ismail Bennani info.SetProcessID(GetID());
391312b43daSMed Ismail Bennani info.SetArchitecture(GetArchitecture());
392312b43daSMed Ismail Bennani lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
393312b43daSMed Ismail Bennani if (module_sp) {
394312b43daSMed Ismail Bennani const bool add_exe_file_as_first_arg = false;
395312b43daSMed Ismail Bennani info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
396312b43daSMed Ismail Bennani add_exe_file_as_first_arg);
397312b43daSMed Ismail Bennani }
398312b43daSMed Ismail Bennani return true;
399312b43daSMed Ismail Bennani }
400312b43daSMed Ismail Bennani
401680ca7f2SMed Ismail Bennani lldb_private::StructuredData::ObjectSP
GetLoadedDynamicLibrariesInfos()402680ca7f2SMed Ismail Bennani ScriptedProcess::GetLoadedDynamicLibrariesInfos() {
403680ca7f2SMed Ismail Bennani CheckInterpreterAndScriptObject();
404680ca7f2SMed Ismail Bennani
405680ca7f2SMed Ismail Bennani Status error;
406680ca7f2SMed Ismail Bennani auto error_with_message = [&error](llvm::StringRef message) {
407680ca7f2SMed Ismail Bennani return ScriptedInterface::ErrorWithMessage<bool>(LLVM_PRETTY_FUNCTION,
408680ca7f2SMed Ismail Bennani message.data(), error);
409680ca7f2SMed Ismail Bennani };
410680ca7f2SMed Ismail Bennani
411680ca7f2SMed Ismail Bennani StructuredData::ArraySP loaded_images_sp = GetInterface().GetLoadedImages();
412680ca7f2SMed Ismail Bennani
413680ca7f2SMed Ismail Bennani if (!loaded_images_sp || !loaded_images_sp->GetSize())
414680ca7f2SMed Ismail Bennani return GetInterface().ErrorWithMessage<StructuredData::ObjectSP>(
415680ca7f2SMed Ismail Bennani LLVM_PRETTY_FUNCTION, "No loaded images.", error);
416680ca7f2SMed Ismail Bennani
417680ca7f2SMed Ismail Bennani ModuleList module_list;
418680ca7f2SMed Ismail Bennani Target &target = GetTarget();
419680ca7f2SMed Ismail Bennani
420680ca7f2SMed Ismail Bennani auto reload_image = [&target, &module_list, &error_with_message](
421680ca7f2SMed Ismail Bennani StructuredData::Object *obj) -> bool {
422680ca7f2SMed Ismail Bennani StructuredData::Dictionary *dict = obj->GetAsDictionary();
423680ca7f2SMed Ismail Bennani
424680ca7f2SMed Ismail Bennani if (!dict)
425680ca7f2SMed Ismail Bennani return error_with_message("Couldn't cast image object into dictionary.");
426680ca7f2SMed Ismail Bennani
427680ca7f2SMed Ismail Bennani ModuleSpec module_spec;
428680ca7f2SMed Ismail Bennani llvm::StringRef value;
429680ca7f2SMed Ismail Bennani
430680ca7f2SMed Ismail Bennani bool has_path = dict->HasKey("path");
431680ca7f2SMed Ismail Bennani bool has_uuid = dict->HasKey("uuid");
432680ca7f2SMed Ismail Bennani if (!has_path && !has_uuid)
433680ca7f2SMed Ismail Bennani return error_with_message("Dictionary should have key 'path' or 'uuid'");
434680ca7f2SMed Ismail Bennani if (!dict->HasKey("load_addr"))
435680ca7f2SMed Ismail Bennani return error_with_message("Dictionary is missing key 'load_addr'");
436680ca7f2SMed Ismail Bennani
437680ca7f2SMed Ismail Bennani if (has_path) {
438680ca7f2SMed Ismail Bennani dict->GetValueForKeyAsString("path", value);
439680ca7f2SMed Ismail Bennani module_spec.GetFileSpec().SetPath(value);
440680ca7f2SMed Ismail Bennani }
441680ca7f2SMed Ismail Bennani
442680ca7f2SMed Ismail Bennani if (has_uuid) {
443680ca7f2SMed Ismail Bennani dict->GetValueForKeyAsString("uuid", value);
444680ca7f2SMed Ismail Bennani module_spec.GetUUID().SetFromStringRef(value);
445680ca7f2SMed Ismail Bennani }
446680ca7f2SMed Ismail Bennani module_spec.GetArchitecture() = target.GetArchitecture();
447680ca7f2SMed Ismail Bennani
448680ca7f2SMed Ismail Bennani ModuleSP module_sp =
449680ca7f2SMed Ismail Bennani target.GetOrCreateModule(module_spec, true /* notify */);
450680ca7f2SMed Ismail Bennani
451680ca7f2SMed Ismail Bennani if (!module_sp)
452680ca7f2SMed Ismail Bennani return error_with_message("Couldn't create or get module.");
453680ca7f2SMed Ismail Bennani
454680ca7f2SMed Ismail Bennani lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
455680ca7f2SMed Ismail Bennani lldb::addr_t slide = LLDB_INVALID_OFFSET;
456680ca7f2SMed Ismail Bennani dict->GetValueForKeyAsInteger("load_addr", load_addr);
457680ca7f2SMed Ismail Bennani dict->GetValueForKeyAsInteger("slide", slide);
458680ca7f2SMed Ismail Bennani if (load_addr == LLDB_INVALID_ADDRESS)
459680ca7f2SMed Ismail Bennani return error_with_message(
460680ca7f2SMed Ismail Bennani "Couldn't get valid load address or slide offset.");
461680ca7f2SMed Ismail Bennani
462680ca7f2SMed Ismail Bennani if (slide != LLDB_INVALID_OFFSET)
463680ca7f2SMed Ismail Bennani load_addr += slide;
464680ca7f2SMed Ismail Bennani
465680ca7f2SMed Ismail Bennani bool changed = false;
466680ca7f2SMed Ismail Bennani module_sp->SetLoadAddress(target, load_addr, false /*=value_is_offset*/,
467680ca7f2SMed Ismail Bennani changed);
468680ca7f2SMed Ismail Bennani
469680ca7f2SMed Ismail Bennani if (!changed && !module_sp->GetObjectFile())
470680ca7f2SMed Ismail Bennani return error_with_message("Couldn't set the load address for module.");
471680ca7f2SMed Ismail Bennani
472680ca7f2SMed Ismail Bennani dict->GetValueForKeyAsString("path", value);
473680ca7f2SMed Ismail Bennani FileSpec objfile(value);
474680ca7f2SMed Ismail Bennani module_sp->SetFileSpecAndObjectName(objfile, objfile.GetFilename());
475680ca7f2SMed Ismail Bennani
476680ca7f2SMed Ismail Bennani return module_list.AppendIfNeeded(module_sp);
477680ca7f2SMed Ismail Bennani };
478680ca7f2SMed Ismail Bennani
479680ca7f2SMed Ismail Bennani if (!loaded_images_sp->ForEach(reload_image))
480680ca7f2SMed Ismail Bennani return GetInterface().ErrorWithMessage<StructuredData::ObjectSP>(
481680ca7f2SMed Ismail Bennani LLVM_PRETTY_FUNCTION, "Couldn't reload all images.", error);
482680ca7f2SMed Ismail Bennani
483680ca7f2SMed Ismail Bennani target.ModulesDidLoad(module_list);
484680ca7f2SMed Ismail Bennani
485680ca7f2SMed Ismail Bennani return loaded_images_sp;
486680ca7f2SMed Ismail Bennani }
487680ca7f2SMed Ismail Bennani
GetInterface() const488312b43daSMed Ismail Bennani ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
489312b43daSMed Ismail Bennani return m_interpreter->GetScriptedProcessInterface();
490312b43daSMed Ismail Bennani }
491