1c0981da4SDimitry Andric //===-- ScriptedThread.cpp ------------------------------------------------===//
2c0981da4SDimitry Andric //
3c0981da4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c0981da4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5c0981da4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c0981da4SDimitry Andric //
7c0981da4SDimitry Andric //===----------------------------------------------------------------------===//
8c0981da4SDimitry Andric
9c0981da4SDimitry Andric #include "ScriptedThread.h"
10c0981da4SDimitry Andric
11c0981da4SDimitry Andric #include "Plugins/Process/Utility/RegisterContextThreadMemory.h"
12e3b55780SDimitry Andric #include "Plugins/Process/Utility/StopInfoMachException.h"
13c0981da4SDimitry Andric #include "lldb/Target/OperatingSystem.h"
14c0981da4SDimitry Andric #include "lldb/Target/Process.h"
15c0981da4SDimitry Andric #include "lldb/Target/RegisterContext.h"
16c0981da4SDimitry Andric #include "lldb/Target/StopInfo.h"
17c0981da4SDimitry Andric #include "lldb/Target/Unwind.h"
18c0981da4SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
19145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
20c0981da4SDimitry Andric #include <memory>
21e3b55780SDimitry Andric #include <optional>
22c0981da4SDimitry Andric
23c0981da4SDimitry Andric using namespace lldb;
24c0981da4SDimitry Andric using namespace lldb_private;
25c0981da4SDimitry Andric
CheckInterpreterAndScriptObject() const26c0981da4SDimitry Andric void ScriptedThread::CheckInterpreterAndScriptObject() const {
27c0981da4SDimitry Andric lldbassert(m_script_object_sp && "Invalid Script Object.");
28c0981da4SDimitry Andric lldbassert(GetInterface() && "Invalid Scripted Thread Interface.");
29c0981da4SDimitry Andric }
30c0981da4SDimitry Andric
316f8fc217SDimitry Andric llvm::Expected<std::shared_ptr<ScriptedThread>>
Create(ScriptedProcess & process,StructuredData::Generic * script_object)326f8fc217SDimitry Andric ScriptedThread::Create(ScriptedProcess &process,
336f8fc217SDimitry Andric StructuredData::Generic *script_object) {
346f8fc217SDimitry Andric if (!process.IsValid())
356f8fc217SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(),
366f8fc217SDimitry Andric "Invalid scripted process.");
37c0981da4SDimitry Andric
387fa27ce4SDimitry Andric process.CheckScriptedInterface();
39c0981da4SDimitry Andric
406f8fc217SDimitry Andric auto scripted_thread_interface =
416f8fc217SDimitry Andric process.GetInterface().CreateScriptedThreadInterface();
426f8fc217SDimitry Andric if (!scripted_thread_interface)
436f8fc217SDimitry Andric return llvm::createStringError(
446f8fc217SDimitry Andric llvm::inconvertibleErrorCode(),
456f8fc217SDimitry Andric "Failed to create scripted thread interface.");
46c0981da4SDimitry Andric
476f8fc217SDimitry Andric llvm::StringRef thread_class_name;
486f8fc217SDimitry Andric if (!script_object) {
49e3b55780SDimitry Andric std::optional<std::string> class_name =
50c0981da4SDimitry Andric process.GetInterface().GetScriptedThreadPluginName();
516f8fc217SDimitry Andric if (!class_name || class_name->empty())
526f8fc217SDimitry Andric return llvm::createStringError(
536f8fc217SDimitry Andric llvm::inconvertibleErrorCode(),
546f8fc217SDimitry Andric "Failed to get scripted thread class name.");
556f8fc217SDimitry Andric thread_class_name = *class_name;
56c0981da4SDimitry Andric }
57c0981da4SDimitry Andric
58c0981da4SDimitry Andric ExecutionContext exe_ctx(process);
59b1c73532SDimitry Andric auto obj_or_err = scripted_thread_interface->CreatePluginObject(
60e3b55780SDimitry Andric thread_class_name, exe_ctx, process.m_scripted_metadata.GetArgsSP(),
61e3b55780SDimitry Andric script_object);
626f8fc217SDimitry Andric
63b1c73532SDimitry Andric if (!obj_or_err) {
64b1c73532SDimitry Andric llvm::consumeError(obj_or_err.takeError());
656f8fc217SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(),
666f8fc217SDimitry Andric "Failed to create script object.");
67b1c73532SDimitry Andric }
68b1c73532SDimitry Andric
69b1c73532SDimitry Andric StructuredData::GenericSP owned_script_object_sp = *obj_or_err;
70b1c73532SDimitry Andric
716f8fc217SDimitry Andric if (!owned_script_object_sp->IsValid())
726f8fc217SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(),
736f8fc217SDimitry Andric "Created script object is invalid.");
746f8fc217SDimitry Andric
756f8fc217SDimitry Andric lldb::tid_t tid = scripted_thread_interface->GetThreadID();
766f8fc217SDimitry Andric
776f8fc217SDimitry Andric return std::make_shared<ScriptedThread>(process, scripted_thread_interface,
786f8fc217SDimitry Andric tid, owned_script_object_sp);
79c0981da4SDimitry Andric }
80c0981da4SDimitry Andric
ScriptedThread(ScriptedProcess & process,ScriptedThreadInterfaceSP interface_sp,lldb::tid_t tid,StructuredData::GenericSP script_object_sp)816f8fc217SDimitry Andric ScriptedThread::ScriptedThread(ScriptedProcess &process,
826f8fc217SDimitry Andric ScriptedThreadInterfaceSP interface_sp,
836f8fc217SDimitry Andric lldb::tid_t tid,
846f8fc217SDimitry Andric StructuredData::GenericSP script_object_sp)
856f8fc217SDimitry Andric : Thread(process, tid), m_scripted_process(process),
866f8fc217SDimitry Andric m_scripted_thread_interface_sp(interface_sp),
876f8fc217SDimitry Andric m_script_object_sp(script_object_sp) {}
88c0981da4SDimitry Andric
~ScriptedThread()89c0981da4SDimitry Andric ScriptedThread::~ScriptedThread() { DestroyThread(); }
90c0981da4SDimitry Andric
GetName()91c0981da4SDimitry Andric const char *ScriptedThread::GetName() {
92c0981da4SDimitry Andric CheckInterpreterAndScriptObject();
93e3b55780SDimitry Andric std::optional<std::string> thread_name = GetInterface()->GetName();
94c0981da4SDimitry Andric if (!thread_name)
95c0981da4SDimitry Andric return nullptr;
96c0981da4SDimitry Andric return ConstString(thread_name->c_str()).AsCString();
97c0981da4SDimitry Andric }
98c0981da4SDimitry Andric
GetQueueName()99c0981da4SDimitry Andric const char *ScriptedThread::GetQueueName() {
100c0981da4SDimitry Andric CheckInterpreterAndScriptObject();
101e3b55780SDimitry Andric std::optional<std::string> queue_name = GetInterface()->GetQueue();
102c0981da4SDimitry Andric if (!queue_name)
103c0981da4SDimitry Andric return nullptr;
104c0981da4SDimitry Andric return ConstString(queue_name->c_str()).AsCString();
105c0981da4SDimitry Andric }
106c0981da4SDimitry Andric
WillResume(StateType resume_state)107c0981da4SDimitry Andric void ScriptedThread::WillResume(StateType resume_state) {}
108c0981da4SDimitry Andric
ClearStackFrames()109c0981da4SDimitry Andric void ScriptedThread::ClearStackFrames() { Thread::ClearStackFrames(); }
110c0981da4SDimitry Andric
GetRegisterContext()111c0981da4SDimitry Andric RegisterContextSP ScriptedThread::GetRegisterContext() {
112c0981da4SDimitry Andric if (!m_reg_context_sp)
113c0981da4SDimitry Andric m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
114c0981da4SDimitry Andric return m_reg_context_sp;
115c0981da4SDimitry Andric }
116c0981da4SDimitry Andric
117c0981da4SDimitry Andric RegisterContextSP
CreateRegisterContextForFrame(StackFrame * frame)118c0981da4SDimitry Andric ScriptedThread::CreateRegisterContextForFrame(StackFrame *frame) {
119c0981da4SDimitry Andric const uint32_t concrete_frame_idx =
120c0981da4SDimitry Andric frame ? frame->GetConcreteFrameIndex() : 0;
121c0981da4SDimitry Andric
122c0981da4SDimitry Andric if (concrete_frame_idx)
123c0981da4SDimitry Andric return GetUnwinder().CreateRegisterContextForFrame(frame);
124c0981da4SDimitry Andric
125c0981da4SDimitry Andric lldb::RegisterContextSP reg_ctx_sp;
126c0981da4SDimitry Andric Status error;
127c0981da4SDimitry Andric
128e3b55780SDimitry Andric std::optional<std::string> reg_data = GetInterface()->GetRegisterContext();
129c0981da4SDimitry Andric if (!reg_data)
130145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<lldb::RegisterContextSP>(
131c0981da4SDimitry Andric LLVM_PRETTY_FUNCTION, "Failed to get scripted thread registers data.",
132145449b1SDimitry Andric error, LLDBLog::Thread);
133c0981da4SDimitry Andric
134c0981da4SDimitry Andric DataBufferSP data_sp(
135c0981da4SDimitry Andric std::make_shared<DataBufferHeap>(reg_data->c_str(), reg_data->size()));
136c0981da4SDimitry Andric
137c0981da4SDimitry Andric if (!data_sp->GetByteSize())
138145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<lldb::RegisterContextSP>(
139c0981da4SDimitry Andric LLVM_PRETTY_FUNCTION, "Failed to copy raw registers data.", error,
140145449b1SDimitry Andric LLDBLog::Thread);
141c0981da4SDimitry Andric
142c0981da4SDimitry Andric std::shared_ptr<RegisterContextMemory> reg_ctx_memory =
143c0981da4SDimitry Andric std::make_shared<RegisterContextMemory>(
144c0981da4SDimitry Andric *this, 0, *GetDynamicRegisterInfo(), LLDB_INVALID_ADDRESS);
145c0981da4SDimitry Andric if (!reg_ctx_memory)
146145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<lldb::RegisterContextSP>(
147c0981da4SDimitry Andric LLVM_PRETTY_FUNCTION, "Failed to create a register context.", error,
148145449b1SDimitry Andric LLDBLog::Thread);
149c0981da4SDimitry Andric
150c0981da4SDimitry Andric reg_ctx_memory->SetAllRegisterData(data_sp);
151c0981da4SDimitry Andric m_reg_context_sp = reg_ctx_memory;
152c0981da4SDimitry Andric
153c0981da4SDimitry Andric return m_reg_context_sp;
154c0981da4SDimitry Andric }
155c0981da4SDimitry Andric
LoadArtificialStackFrames()156145449b1SDimitry Andric bool ScriptedThread::LoadArtificialStackFrames() {
157145449b1SDimitry Andric StructuredData::ArraySP arr_sp = GetInterface()->GetStackFrames();
158145449b1SDimitry Andric
159145449b1SDimitry Andric Status error;
160145449b1SDimitry Andric if (!arr_sp)
161145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>(
162145449b1SDimitry Andric LLVM_PRETTY_FUNCTION, "Failed to get scripted thread stackframes.",
163145449b1SDimitry Andric error, LLDBLog::Thread);
164145449b1SDimitry Andric
165145449b1SDimitry Andric size_t arr_size = arr_sp->GetSize();
166145449b1SDimitry Andric if (arr_size > std::numeric_limits<uint32_t>::max())
167145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>(
168145449b1SDimitry Andric LLVM_PRETTY_FUNCTION,
169145449b1SDimitry Andric llvm::Twine(
170145449b1SDimitry Andric "StackFrame array size (" + llvm::Twine(arr_size) +
171145449b1SDimitry Andric llvm::Twine(
172e3b55780SDimitry Andric ") is greater than maximum authorized for a StackFrameList."))
173145449b1SDimitry Andric .str(),
174145449b1SDimitry Andric error, LLDBLog::Thread);
175145449b1SDimitry Andric
176145449b1SDimitry Andric StackFrameListSP frames = GetStackFrameList();
177145449b1SDimitry Andric
178145449b1SDimitry Andric for (size_t idx = 0; idx < arr_size; idx++) {
179b1c73532SDimitry Andric std::optional<StructuredData::Dictionary *> maybe_dict =
180b1c73532SDimitry Andric arr_sp->GetItemAtIndexAsDictionary(idx);
181b1c73532SDimitry Andric if (!maybe_dict)
182145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>(
183145449b1SDimitry Andric LLVM_PRETTY_FUNCTION,
184145449b1SDimitry Andric llvm::Twine(
185145449b1SDimitry Andric "Couldn't get artificial stackframe dictionary at index (" +
186145449b1SDimitry Andric llvm::Twine(idx) + llvm::Twine(") from stackframe array."))
187145449b1SDimitry Andric .str(),
188145449b1SDimitry Andric error, LLDBLog::Thread);
189b1c73532SDimitry Andric StructuredData::Dictionary *dict = *maybe_dict;
190145449b1SDimitry Andric
191145449b1SDimitry Andric lldb::addr_t pc;
192145449b1SDimitry Andric if (!dict->GetValueForKeyAsInteger("pc", pc))
193145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>(
194145449b1SDimitry Andric LLVM_PRETTY_FUNCTION,
195145449b1SDimitry Andric "Couldn't find value for key 'pc' in stackframe dictionary.", error,
196145449b1SDimitry Andric LLDBLog::Thread);
197145449b1SDimitry Andric
198145449b1SDimitry Andric Address symbol_addr;
199145449b1SDimitry Andric symbol_addr.SetLoadAddress(pc, &this->GetProcess()->GetTarget());
200145449b1SDimitry Andric
201145449b1SDimitry Andric lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
202145449b1SDimitry Andric bool cfa_is_valid = false;
203145449b1SDimitry Andric const bool behaves_like_zeroth_frame = false;
204145449b1SDimitry Andric SymbolContext sc;
205145449b1SDimitry Andric symbol_addr.CalculateSymbolContext(&sc);
206145449b1SDimitry Andric
207145449b1SDimitry Andric StackFrameSP synth_frame_sp = std::make_shared<StackFrame>(
208145449b1SDimitry Andric this->shared_from_this(), idx, idx, cfa, cfa_is_valid, pc,
209145449b1SDimitry Andric StackFrame::Kind::Artificial, behaves_like_zeroth_frame, &sc);
210145449b1SDimitry Andric
211145449b1SDimitry Andric if (!frames->SetFrameAtIndex(static_cast<uint32_t>(idx), synth_frame_sp))
212145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>(
213145449b1SDimitry Andric LLVM_PRETTY_FUNCTION,
214145449b1SDimitry Andric llvm::Twine("Couldn't add frame (" + llvm::Twine(idx) +
215145449b1SDimitry Andric llvm::Twine(") to ScriptedThread StackFrameList."))
216145449b1SDimitry Andric .str(),
217145449b1SDimitry Andric error, LLDBLog::Thread);
218145449b1SDimitry Andric }
219145449b1SDimitry Andric
220145449b1SDimitry Andric return true;
221145449b1SDimitry Andric }
222145449b1SDimitry Andric
CalculateStopInfo()223c0981da4SDimitry Andric bool ScriptedThread::CalculateStopInfo() {
224c0981da4SDimitry Andric StructuredData::DictionarySP dict_sp = GetInterface()->GetStopReason();
225c0981da4SDimitry Andric
226c0981da4SDimitry Andric Status error;
2276f8fc217SDimitry Andric if (!dict_sp)
228145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>(
2296f8fc217SDimitry Andric LLVM_PRETTY_FUNCTION, "Failed to get scripted thread stop info.", error,
230145449b1SDimitry Andric LLDBLog::Thread);
2316f8fc217SDimitry Andric
232c0981da4SDimitry Andric lldb::StopInfoSP stop_info_sp;
233c0981da4SDimitry Andric lldb::StopReason stop_reason_type;
234c0981da4SDimitry Andric
235c0981da4SDimitry Andric if (!dict_sp->GetValueForKeyAsInteger("type", stop_reason_type))
236145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>(
237c0981da4SDimitry Andric LLVM_PRETTY_FUNCTION,
238c0981da4SDimitry Andric "Couldn't find value for key 'type' in stop reason dictionary.", error,
239145449b1SDimitry Andric LLDBLog::Thread);
240c0981da4SDimitry Andric
241c0981da4SDimitry Andric StructuredData::Dictionary *data_dict;
242c0981da4SDimitry Andric if (!dict_sp->GetValueForKeyAsDictionary("data", data_dict))
243145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>(
244c0981da4SDimitry Andric LLVM_PRETTY_FUNCTION,
2456f8fc217SDimitry Andric "Couldn't find value for key 'data' in stop reason dictionary.", error,
246145449b1SDimitry Andric LLDBLog::Thread);
247c0981da4SDimitry Andric
248c0981da4SDimitry Andric switch (stop_reason_type) {
249c0981da4SDimitry Andric case lldb::eStopReasonNone:
2506f8fc217SDimitry Andric return true;
251c0981da4SDimitry Andric case lldb::eStopReasonBreakpoint: {
252c0981da4SDimitry Andric lldb::break_id_t break_id;
253c0981da4SDimitry Andric data_dict->GetValueForKeyAsInteger("break_id", break_id,
254c0981da4SDimitry Andric LLDB_INVALID_BREAK_ID);
255c0981da4SDimitry Andric stop_info_sp =
256c0981da4SDimitry Andric StopInfo::CreateStopReasonWithBreakpointSiteID(*this, break_id);
257c0981da4SDimitry Andric } break;
258c0981da4SDimitry Andric case lldb::eStopReasonSignal: {
2597fa27ce4SDimitry Andric uint32_t signal;
260c0981da4SDimitry Andric llvm::StringRef description;
2617fa27ce4SDimitry Andric if (!data_dict->GetValueForKeyAsInteger("signal", signal)) {
2627fa27ce4SDimitry Andric signal = LLDB_INVALID_SIGNAL_NUMBER;
2637fa27ce4SDimitry Andric return false;
2647fa27ce4SDimitry Andric }
265c0981da4SDimitry Andric data_dict->GetValueForKeyAsString("desc", description);
266c0981da4SDimitry Andric stop_info_sp =
267c0981da4SDimitry Andric StopInfo::CreateStopReasonWithSignal(*this, signal, description.data());
268c0981da4SDimitry Andric } break;
2697fa27ce4SDimitry Andric case lldb::eStopReasonTrace: {
2707fa27ce4SDimitry Andric stop_info_sp = StopInfo::CreateStopReasonToTrace(*this);
2717fa27ce4SDimitry Andric } break;
2726f8fc217SDimitry Andric case lldb::eStopReasonException: {
273e3b55780SDimitry Andric #if defined(__APPLE__)
274e3b55780SDimitry Andric StructuredData::Dictionary *mach_exception;
275e3b55780SDimitry Andric if (data_dict->GetValueForKeyAsDictionary("mach_exception",
276e3b55780SDimitry Andric mach_exception)) {
277e3b55780SDimitry Andric llvm::StringRef value;
278e3b55780SDimitry Andric mach_exception->GetValueForKeyAsString("type", value);
279e3b55780SDimitry Andric auto exc_type =
280e3b55780SDimitry Andric StopInfoMachException::MachException::ExceptionCode(value.data());
2816f8fc217SDimitry Andric
282e3b55780SDimitry Andric if (!exc_type)
283e3b55780SDimitry Andric return false;
284e3b55780SDimitry Andric
285e3b55780SDimitry Andric uint32_t exc_data_size = 0;
286e3b55780SDimitry Andric llvm::SmallVector<uint64_t, 3> raw_codes;
287e3b55780SDimitry Andric
288e3b55780SDimitry Andric StructuredData::Array *exc_rawcodes;
289e3b55780SDimitry Andric mach_exception->GetValueForKeyAsArray("rawCodes", exc_rawcodes);
290e3b55780SDimitry Andric if (exc_rawcodes) {
291e3b55780SDimitry Andric auto fetch_data = [&raw_codes](StructuredData::Object *obj) {
292e3b55780SDimitry Andric if (!obj)
293e3b55780SDimitry Andric return false;
2947fa27ce4SDimitry Andric raw_codes.push_back(obj->GetUnsignedIntegerValue());
295e3b55780SDimitry Andric return true;
296e3b55780SDimitry Andric };
297e3b55780SDimitry Andric
298e3b55780SDimitry Andric exc_rawcodes->ForEach(fetch_data);
299e3b55780SDimitry Andric exc_data_size = raw_codes.size();
300e3b55780SDimitry Andric }
301e3b55780SDimitry Andric
302e3b55780SDimitry Andric stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException(
303e3b55780SDimitry Andric *this, *exc_type, exc_data_size,
304e3b55780SDimitry Andric exc_data_size >= 1 ? raw_codes[0] : 0,
305e3b55780SDimitry Andric exc_data_size >= 2 ? raw_codes[1] : 0,
306e3b55780SDimitry Andric exc_data_size >= 3 ? raw_codes[2] : 0);
307e3b55780SDimitry Andric
308e3b55780SDimitry Andric break;
309e3b55780SDimitry Andric }
310e3b55780SDimitry Andric #endif
3116f8fc217SDimitry Andric stop_info_sp =
312e3b55780SDimitry Andric StopInfo::CreateStopReasonWithException(*this, "EXC_BAD_ACCESS");
3136f8fc217SDimitry Andric } break;
314c0981da4SDimitry Andric default:
315145449b1SDimitry Andric return ScriptedInterface::ErrorWithMessage<bool>(
316c0981da4SDimitry Andric LLVM_PRETTY_FUNCTION,
317c0981da4SDimitry Andric llvm::Twine("Unsupported stop reason type (" +
318c0981da4SDimitry Andric llvm::Twine(stop_reason_type) + llvm::Twine(")."))
319c0981da4SDimitry Andric .str(),
320145449b1SDimitry Andric error, LLDBLog::Thread);
321c0981da4SDimitry Andric }
322c0981da4SDimitry Andric
3236f8fc217SDimitry Andric if (!stop_info_sp)
3246f8fc217SDimitry Andric return false;
3256f8fc217SDimitry Andric
326c0981da4SDimitry Andric SetStopInfo(stop_info_sp);
327c0981da4SDimitry Andric return true;
328c0981da4SDimitry Andric }
329c0981da4SDimitry Andric
RefreshStateAfterStop()330c0981da4SDimitry Andric void ScriptedThread::RefreshStateAfterStop() {
331c0981da4SDimitry Andric GetRegisterContext()->InvalidateIfNeeded(/*force=*/false);
332145449b1SDimitry Andric LoadArtificialStackFrames();
333c0981da4SDimitry Andric }
334c0981da4SDimitry Andric
GetInterface() const335c0981da4SDimitry Andric lldb::ScriptedThreadInterfaceSP ScriptedThread::GetInterface() const {
3366f8fc217SDimitry Andric return m_scripted_thread_interface_sp;
337c0981da4SDimitry Andric }
338c0981da4SDimitry Andric
GetDynamicRegisterInfo()339c0981da4SDimitry Andric std::shared_ptr<DynamicRegisterInfo> ScriptedThread::GetDynamicRegisterInfo() {
340c0981da4SDimitry Andric CheckInterpreterAndScriptObject();
341c0981da4SDimitry Andric
342c0981da4SDimitry Andric if (!m_register_info_sp) {
343c0981da4SDimitry Andric StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo();
34477fc4c14SDimitry Andric
34577fc4c14SDimitry Andric Status error;
346c0981da4SDimitry Andric if (!reg_info)
347e3b55780SDimitry Andric return ScriptedInterface::ErrorWithMessage<
348e3b55780SDimitry Andric std::shared_ptr<DynamicRegisterInfo>>(
349e3b55780SDimitry Andric LLVM_PRETTY_FUNCTION, "Failed to get scripted thread registers info.",
350e3b55780SDimitry Andric error, LLDBLog::Thread);
351c0981da4SDimitry Andric
3527fa27ce4SDimitry Andric m_register_info_sp = DynamicRegisterInfo::Create(
353c0981da4SDimitry Andric *reg_info, m_scripted_process.GetTarget().GetArchitecture());
354c0981da4SDimitry Andric }
355c0981da4SDimitry Andric
356c0981da4SDimitry Andric return m_register_info_sp;
357c0981da4SDimitry Andric }
358e3b55780SDimitry Andric
FetchThreadExtendedInfo()359e3b55780SDimitry Andric StructuredData::ObjectSP ScriptedThread::FetchThreadExtendedInfo() {
360e3b55780SDimitry Andric CheckInterpreterAndScriptObject();
361e3b55780SDimitry Andric
362e3b55780SDimitry Andric Status error;
363e3b55780SDimitry Andric StructuredData::ArraySP extended_info_sp = GetInterface()->GetExtendedInfo();
364e3b55780SDimitry Andric
365e3b55780SDimitry Andric if (!extended_info_sp || !extended_info_sp->GetSize())
366e3b55780SDimitry Andric return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
367e3b55780SDimitry Andric LLVM_PRETTY_FUNCTION, "No extended information found", error);
368e3b55780SDimitry Andric
369e3b55780SDimitry Andric return extended_info_sp;
370e3b55780SDimitry Andric }
371