LLDB  mainline
ScriptedThread.cpp
Go to the documentation of this file.
1 //===-- ScriptedThread.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 "ScriptedThread.h"
10 
13 #include "lldb/Target/Process.h"
15 #include "lldb/Target/StopInfo.h"
16 #include "lldb/Target/Unwind.h"
18 #include "lldb/Utility/LLDBLog.h"
19 #include <memory>
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 
24 void ScriptedThread::CheckInterpreterAndScriptObject() const {
25  lldbassert(m_script_object_sp && "Invalid Script Object.");
26  lldbassert(GetInterface() && "Invalid Scripted Thread Interface.");
27 }
28 
29 llvm::Expected<std::shared_ptr<ScriptedThread>>
30 ScriptedThread::Create(ScriptedProcess &process,
31  StructuredData::Generic *script_object) {
32  if (!process.IsValid())
33  return llvm::createStringError(llvm::inconvertibleErrorCode(),
34  "Invalid scripted process.");
35 
37 
38  auto scripted_thread_interface =
40  if (!scripted_thread_interface)
41  return llvm::createStringError(
42  llvm::inconvertibleErrorCode(),
43  "Failed to create scripted thread interface.");
44 
45  llvm::StringRef thread_class_name;
46  if (!script_object) {
47  llvm::Optional<std::string> class_name =
49  if (!class_name || class_name->empty())
50  return llvm::createStringError(
51  llvm::inconvertibleErrorCode(),
52  "Failed to get scripted thread class name.");
53  thread_class_name = *class_name;
54  }
55 
56  ExecutionContext exe_ctx(process);
57  StructuredData::GenericSP owned_script_object_sp =
58  scripted_thread_interface->CreatePluginObject(
59  thread_class_name, exe_ctx,
60  process.m_scripted_process_info.GetArgsSP(), script_object);
61 
62  if (!owned_script_object_sp)
63  return llvm::createStringError(llvm::inconvertibleErrorCode(),
64  "Failed to create script object.");
65  if (!owned_script_object_sp->IsValid())
66  return llvm::createStringError(llvm::inconvertibleErrorCode(),
67  "Created script object is invalid.");
68 
69  lldb::tid_t tid = scripted_thread_interface->GetThreadID();
70 
71  return std::make_shared<ScriptedThread>(process, scripted_thread_interface,
72  tid, owned_script_object_sp);
73 }
74 
75 ScriptedThread::ScriptedThread(ScriptedProcess &process,
76  ScriptedThreadInterfaceSP interface_sp,
77  lldb::tid_t tid,
78  StructuredData::GenericSP script_object_sp)
79  : Thread(process, tid), m_scripted_process(process),
80  m_scripted_thread_interface_sp(interface_sp),
81  m_script_object_sp(script_object_sp) {}
82 
84 
85 const char *ScriptedThread::GetName() {
87  llvm::Optional<std::string> thread_name = GetInterface()->GetName();
88  if (!thread_name)
89  return nullptr;
90  return ConstString(thread_name->c_str()).AsCString();
91 }
92 
95  llvm::Optional<std::string> queue_name = GetInterface()->GetQueue();
96  if (!queue_name)
97  return nullptr;
98  return ConstString(queue_name->c_str()).AsCString();
99 }
100 
102 
104 
106  if (!m_reg_context_sp)
108  return m_reg_context_sp;
109 }
110 
111 RegisterContextSP
113  const uint32_t concrete_frame_idx =
114  frame ? frame->GetConcreteFrameIndex() : 0;
115 
116  if (concrete_frame_idx)
118 
119  lldb::RegisterContextSP reg_ctx_sp;
120  Status error;
121 
122  llvm::Optional<std::string> reg_data = GetInterface()->GetRegisterContext();
123  if (!reg_data)
124  return ScriptedInterface::ErrorWithMessage<lldb::RegisterContextSP>(
125  LLVM_PRETTY_FUNCTION, "Failed to get scripted thread registers data.",
127 
128  DataBufferSP data_sp(
129  std::make_shared<DataBufferHeap>(reg_data->c_str(), reg_data->size()));
130 
131  if (!data_sp->GetByteSize())
132  return ScriptedInterface::ErrorWithMessage<lldb::RegisterContextSP>(
133  LLVM_PRETTY_FUNCTION, "Failed to copy raw registers data.", error,
135 
136  std::shared_ptr<RegisterContextMemory> reg_ctx_memory =
137  std::make_shared<RegisterContextMemory>(
139  if (!reg_ctx_memory)
140  return ScriptedInterface::ErrorWithMessage<lldb::RegisterContextSP>(
141  LLVM_PRETTY_FUNCTION, "Failed to create a register context.", error,
143 
144  reg_ctx_memory->SetAllRegisterData(data_sp);
145  m_reg_context_sp = reg_ctx_memory;
146 
147  return m_reg_context_sp;
148 }
149 
151  StructuredData::ArraySP arr_sp = GetInterface()->GetStackFrames();
152 
153  Status error;
154  if (!arr_sp)
155  return ScriptedInterface::ErrorWithMessage<bool>(
156  LLVM_PRETTY_FUNCTION, "Failed to get scripted thread stackframes.",
158 
159  size_t arr_size = arr_sp->GetSize();
160  if (arr_size > std::numeric_limits<uint32_t>::max())
161  return ScriptedInterface::ErrorWithMessage<bool>(
162  LLVM_PRETTY_FUNCTION,
163  llvm::Twine(
164  "StackFrame array size (" + llvm::Twine(arr_size) +
165  llvm::Twine(
166  ") is greater than maximum autorized for a StackFrameList."))
167  .str(),
169 
170  StackFrameListSP frames = GetStackFrameList();
171 
172  for (size_t idx = 0; idx < arr_size; idx++) {
173 
175 
176  if (!arr_sp->GetItemAtIndexAsDictionary(idx, dict) || !dict)
177  return ScriptedInterface::ErrorWithMessage<bool>(
178  LLVM_PRETTY_FUNCTION,
179  llvm::Twine(
180  "Couldn't get artificial stackframe dictionary at index (" +
181  llvm::Twine(idx) + llvm::Twine(") from stackframe array."))
182  .str(),
184 
186  if (!dict->GetValueForKeyAsInteger("pc", pc))
187  return ScriptedInterface::ErrorWithMessage<bool>(
188  LLVM_PRETTY_FUNCTION,
189  "Couldn't find value for key 'pc' in stackframe dictionary.", error,
191 
192  Address symbol_addr;
193  symbol_addr.SetLoadAddress(pc, &this->GetProcess()->GetTarget());
194 
196  bool cfa_is_valid = false;
197  const bool behaves_like_zeroth_frame = false;
198  SymbolContext sc;
199  symbol_addr.CalculateSymbolContext(&sc);
200 
201  StackFrameSP synth_frame_sp = std::make_shared<StackFrame>(
202  this->shared_from_this(), idx, idx, cfa, cfa_is_valid, pc,
203  StackFrame::Kind::Artificial, behaves_like_zeroth_frame, &sc);
204 
205  if (!frames->SetFrameAtIndex(static_cast<uint32_t>(idx), synth_frame_sp))
206  return ScriptedInterface::ErrorWithMessage<bool>(
207  LLVM_PRETTY_FUNCTION,
208  llvm::Twine("Couldn't add frame (" + llvm::Twine(idx) +
209  llvm::Twine(") to ScriptedThread StackFrameList."))
210  .str(),
212  }
213 
214  return true;
215 }
216 
218  StructuredData::DictionarySP dict_sp = GetInterface()->GetStopReason();
219 
220  Status error;
221  if (!dict_sp)
222  return ScriptedInterface::ErrorWithMessage<bool>(
223  LLVM_PRETTY_FUNCTION, "Failed to get scripted thread stop info.", error,
225 
226  lldb::StopInfoSP stop_info_sp;
227  lldb::StopReason stop_reason_type;
228 
229  if (!dict_sp->GetValueForKeyAsInteger("type", stop_reason_type))
230  return ScriptedInterface::ErrorWithMessage<bool>(
231  LLVM_PRETTY_FUNCTION,
232  "Couldn't find value for key 'type' in stop reason dictionary.", error,
234 
235  StructuredData::Dictionary *data_dict;
236  if (!dict_sp->GetValueForKeyAsDictionary("data", data_dict))
237  return ScriptedInterface::ErrorWithMessage<bool>(
238  LLVM_PRETTY_FUNCTION,
239  "Couldn't find value for key 'data' in stop reason dictionary.", error,
241 
242  switch (stop_reason_type) {
244  return true;
246  lldb::break_id_t break_id;
247  data_dict->GetValueForKeyAsInteger("break_id", break_id,
249  stop_info_sp =
251  } break;
253  int signal;
254  llvm::StringRef description;
255  data_dict->GetValueForKeyAsInteger("signal", signal,
257  data_dict->GetValueForKeyAsString("desc", description);
258  stop_info_sp =
259  StopInfo::CreateStopReasonWithSignal(*this, signal, description.data());
260  } break;
262  llvm::StringRef description;
263  data_dict->GetValueForKeyAsString("desc", description);
264 
265  stop_info_sp =
266  StopInfo::CreateStopReasonWithException(*this, description.data());
267  } break;
268  default:
269  return ScriptedInterface::ErrorWithMessage<bool>(
270  LLVM_PRETTY_FUNCTION,
271  llvm::Twine("Unsupported stop reason type (" +
272  llvm::Twine(stop_reason_type) + llvm::Twine(")."))
273  .str(),
275  }
276 
277  if (!stop_info_sp)
278  return false;
279 
280  SetStopInfo(stop_info_sp);
281  return true;
282 }
283 
285  GetRegisterContext()->InvalidateIfNeeded(/*force=*/false);
287 }
288 
289 lldb::ScriptedThreadInterfaceSP ScriptedThread::GetInterface() const {
291 }
292 
293 std::shared_ptr<DynamicRegisterInfo> ScriptedThread::GetDynamicRegisterInfo() {
295 
296  if (!m_register_info_sp) {
297  StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo();
298 
299  Status error;
300  if (!reg_info)
301  return GetInterface()
302  ->ErrorWithMessage<std::shared_ptr<DynamicRegisterInfo>>(
303  LLVM_PRETTY_FUNCTION,
304  "Failed to get scripted thread registers info.", error,
306 
307  m_register_info_sp = std::make_shared<DynamicRegisterInfo>(
309  }
310 
311  return m_register_info_sp;
312 }
lldb_private::Address::SetLoadAddress
bool SetLoadAddress(lldb::addr_t load_addr, Target *target, bool allow_section_end=false)
Set the address to represent load_addr.
Definition: Address.cpp:1040
lldb_private::Process::IsValid
bool IsValid() const
Return whether this object is valid (i.e.
Definition: Process.h:567
lldb_private::ExecutionContext
Definition: ExecutionContext.h:292
lldb_private::StructuredData::Dictionary
Definition: StructuredData.h:352
lldb_private::ScriptedThread::CheckInterpreterAndScriptObject
void CheckInterpreterAndScriptObject() const
Definition: ScriptedThread.cpp:24
lldb_private::ScriptedThread::CalculateStopInfo
bool CalculateStopInfo() override
Definition: ScriptedThread.cpp:217
lldb_private::ScriptedThread::m_register_info_sp
std::shared_ptr< DynamicRegisterInfo > m_register_info_sp
Definition: ScriptedThread.h:73
lldb_private::StructuredData::GenericSP
std::shared_ptr< Generic > GenericSP
Definition: StructuredData.h:68
lldb_private::Thread::GetUnwinder
virtual Unwind & GetUnwinder()
Definition: Thread.cpp:1855
lldb_private::ScriptedProcess::GetInterface
ScriptedProcessInterface & GetInterface() const
Definition: ScriptedProcess.cpp:488
lldb_private::ScriptedProcessInterface::GetScriptedThreadPluginName
virtual llvm::Optional< std::string > GetScriptedThreadPluginName()
Definition: ScriptedProcessInterface.h:65
lldb_private::Thread::ClearStackFrames
virtual void ClearStackFrames()
Definition: Thread.cpp:1411
Unwind.h
lldb_private::Process::GetTarget
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1206
lldb_private::StopInfo::CreateStopReasonWithSignal
static lldb::StopInfoSP CreateStopReasonWithSignal(Thread &thread, int signo, const char *description=nullptr)
Definition: StopInfo.cpp:1266
lldb::StopReason
StopReason
Thread stop reasons.
Definition: lldb-enumerations.h:239
lldb_private::ConstString::AsCString
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:193
lldb::eStopReasonException
@ eStopReasonException
Definition: lldb-enumerations.h:246
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
pc
@ pc
Definition: CompactUnwindInfo.cpp:1251
lldb_private::ScriptedThread::GetName
const char * GetName() override
Definition: ScriptedThread.cpp:85
lldb_private::SymbolContext
Definition: SymbolContext.h:33
lldb_private::ScriptedThread::~ScriptedThread
~ScriptedThread() override
Definition: ScriptedThread.cpp:83
Process.h
lldb_private::StructuredData::Dictionary::GetValueForKeyAsInteger
bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const
Definition: StructuredData.h:413
lldb_private::ScriptedThread::LoadArtificialStackFrames
bool LoadArtificialStackFrames()
Definition: ScriptedThread.cpp:150
lldb_private::ScriptedThread::ClearStackFrames
void ClearStackFrames() override
Definition: ScriptedThread.cpp:103
lldb_private::ScriptedThread::RefreshStateAfterStop
void RefreshStateAfterStop() override
Definition: ScriptedThread.cpp:284
lldb_private::StackFrame::GetConcreteFrameIndex
uint32_t GetConcreteFrameIndex() const
Query this frame to find what frame it is in this Thread's StackFrameList, not counting inlined frame...
Definition: StackFrame.h:407
lldb_private::Thread::GetProcess
lldb::ProcessSP GetProcess() const
Definition: Thread.h:153
lldb_private::Thread::DestroyThread
virtual void DestroyThread()
Definition: Thread.cpp:249
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
LLDB_INVALID_SIGNAL_NUMBER
#define LLDB_INVALID_SIGNAL_NUMBER
Definition: lldb-defines.h:84
lldb_private::ScriptedThread::CreateRegisterContextForFrame
lldb::RegisterContextSP CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override
Definition: ScriptedThread.cpp:112
lldb_private::Thread
Definition: Thread.h:61
lldb_private::ScriptedThread::GetRegisterContext
lldb::RegisterContextSP GetRegisterContext() override
Definition: ScriptedThread.cpp:105
lldb::eStopReasonNone
@ eStopReasonNone
Definition: lldb-enumerations.h:241
lldb_private::LLDBLog::Thread
@ Thread
lldb::break_id_t
int32_t break_id_t
Definition: lldb-types.h:88
OperatingSystem.h
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::Thread::SetStopInfo
void SetStopInfo(const lldb::StopInfoSP &stop_info_sp)
Definition: Thread.cpp:435
lldb_private::StructuredData::DictionarySP
std::shared_ptr< Dictionary > DictionarySP
Definition: StructuredData.h:67
lldb_private::StructuredData::Generic
Definition: StructuredData.h:543
lldb_private::ScriptedThread::m_scripted_thread_interface_sp
lldb::ScriptedThreadInterfaceSP m_scripted_thread_interface_sp
Definition: ScriptedThread.h:71
lldb_private::ScriptedProcessInterface::CreateScriptedThreadInterface
virtual lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface()
Definition: ScriptedProcessInterface.h:71
LLDB_INVALID_BREAK_ID
#define LLDB_INVALID_BREAK_ID
Definition: lldb-defines.h:37
lldb_private::Unwind::CreateRegisterContextForFrame
lldb::RegisterContextSP CreateRegisterContextForFrame(StackFrame *frame)
Definition: Unwind.h:56
lldbassert
#define lldbassert(x)
Definition: LLDBAssert.h:15
lldb_private::ScriptedProcess::m_scripted_process_info
const ScriptedProcessInfo m_scripted_process_info
Definition: ScriptedProcess.h:114
lldb::eStopReasonSignal
@ eStopReasonSignal
Definition: lldb-enumerations.h:245
lldb_private::Target::GetArchitecture
const ArchSpec & GetArchitecture() const
Definition: Target.h:980
lldb_private::Thread::GetStackFrameList
lldb::StackFrameListSP GetStackFrameList()
Definition: Thread.cpp:1401
lldb_private::Status
Definition: Status.h:44
lldb_private::Thread::m_reg_context_sp
lldb::RegisterContextSP m_reg_context_sp
The register context for this thread's current register state.
Definition: Thread.h:1259
uint32_t
lldb_private::ScriptedThread::GetInterface
lldb::ScriptedThreadInterfaceSP GetInterface() const
Definition: ScriptedThread.cpp:289
lldb_private::ScriptedThread::m_scripted_process
const ScriptedProcess & m_scripted_process
Definition: ScriptedThread.h:70
lldb_private::Address
Definition: Address.h:59
lldb_private::ScriptedProcess
Definition: ScriptedProcess.h:22
ScriptedThread.h
StopInfo.h
lldb::eStopReasonBreakpoint
@ eStopReasonBreakpoint
Definition: lldb-enumerations.h:243
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
RegisterContextThreadMemory.h
lldb_private::StackFrame::Kind::Artificial
@ Artificial
An artificial stack frame (e.g.
lldb_private::ScriptedThread::WillResume
void WillResume(lldb::StateType resume_state) override
Definition: ScriptedThread.cpp:101
lldb_private::ScriptedThread::GetDynamicRegisterInfo
std::shared_ptr< DynamicRegisterInfo > GetDynamicRegisterInfo()
Definition: ScriptedThread.cpp:293
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::ScriptedProcess::ScriptedProcessInfo::GetArgsSP
StructuredData::DictionarySP GetArgsSP() const
Definition: ScriptedProcess.h:32
lldb::StateType
StateType
Process and Thread States.
Definition: lldb-enumerations.h:73
lldb_private::StopInfo::CreateStopReasonWithBreakpointSiteID
static lldb::StopInfoSP CreateStopReasonWithBreakpointSiteID(Thread &thread, lldb::break_id_t break_id)
Definition: StopInfo.cpp:1249
lldb_private::StructuredData::ArraySP
std::shared_ptr< Array > ArraySP
Definition: StructuredData.h:62
lldb_private::StructuredData::Dictionary::GetValueForKeyAsString
bool GetValueForKeyAsString(llvm::StringRef key, llvm::StringRef &result) const
Definition: StructuredData.h:433
lldb_private::ScriptedThread::GetQueueName
const char * GetQueueName() override
Retrieve the Queue name for the queue currently using this Thread.
Definition: ScriptedThread.cpp:93
lldb_private::StackFrame
Definition: StackFrame.h:40
lldb_private::StopInfo::CreateStopReasonWithException
static lldb::StopInfoSP CreateStopReasonWithException(Thread &thread, const char *description)
Definition: StopInfo.cpp:1283
lldb_private::ScriptedProcess::CheckInterpreterAndScriptObject
void CheckInterpreterAndScriptObject() const
Definition: ScriptedProcess.cpp:48
lldb
Definition: SBAddress.h:15
RegisterContext.h
LLDBLog.h
lldb_private::Address::CalculateSymbolContext
uint32_t CalculateSymbolContext(SymbolContext *sc, lldb::SymbolContextItem resolve_scope=lldb::eSymbolContextEverything) const
Reconstruct a symbol context from an address.
Definition: Address.cpp:825
DataBufferHeap.h
lldb::tid_t
uint64_t tid_t
Definition: lldb-types.h:86