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 
14 #include "lldb/Target/Process.h"
16 #include "lldb/Target/StopInfo.h"
17 #include "lldb/Target/Unwind.h"
19 #include "lldb/Utility/LLDBLog.h"
20 #include <memory>
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 void ScriptedThread::CheckInterpreterAndScriptObject() const {
26  lldbassert(m_script_object_sp && "Invalid Script Object.");
27  lldbassert(GetInterface() && "Invalid Scripted Thread Interface.");
28 }
29 
30 llvm::Expected<std::shared_ptr<ScriptedThread>>
31 ScriptedThread::Create(ScriptedProcess &process,
32  StructuredData::Generic *script_object) {
33  if (!process.IsValid())
34  return llvm::createStringError(llvm::inconvertibleErrorCode(),
35  "Invalid scripted process.");
36 
38 
39  auto scripted_thread_interface =
41  if (!scripted_thread_interface)
42  return llvm::createStringError(
43  llvm::inconvertibleErrorCode(),
44  "Failed to create scripted thread interface.");
45 
46  llvm::StringRef thread_class_name;
47  if (!script_object) {
48  llvm::Optional<std::string> class_name =
50  if (!class_name || class_name->empty())
51  return llvm::createStringError(
52  llvm::inconvertibleErrorCode(),
53  "Failed to get scripted thread class name.");
54  thread_class_name = *class_name;
55  }
56 
57  ExecutionContext exe_ctx(process);
58  StructuredData::GenericSP owned_script_object_sp =
59  scripted_thread_interface->CreatePluginObject(
60  thread_class_name, exe_ctx,
61  process.m_scripted_process_info.GetArgsSP(), script_object);
62 
63  if (!owned_script_object_sp)
64  return llvm::createStringError(llvm::inconvertibleErrorCode(),
65  "Failed to create script object.");
66  if (!owned_script_object_sp->IsValid())
67  return llvm::createStringError(llvm::inconvertibleErrorCode(),
68  "Created script object is invalid.");
69 
70  lldb::tid_t tid = scripted_thread_interface->GetThreadID();
71 
72  return std::make_shared<ScriptedThread>(process, scripted_thread_interface,
73  tid, owned_script_object_sp);
74 }
75 
76 ScriptedThread::ScriptedThread(ScriptedProcess &process,
77  ScriptedThreadInterfaceSP interface_sp,
78  lldb::tid_t tid,
79  StructuredData::GenericSP script_object_sp)
80  : Thread(process, tid), m_scripted_process(process),
81  m_scripted_thread_interface_sp(interface_sp),
82  m_script_object_sp(script_object_sp) {}
83 
85 
86 const char *ScriptedThread::GetName() {
88  llvm::Optional<std::string> thread_name = GetInterface()->GetName();
89  if (!thread_name)
90  return nullptr;
91  return ConstString(thread_name->c_str()).AsCString();
92 }
93 
96  llvm::Optional<std::string> queue_name = GetInterface()->GetQueue();
97  if (!queue_name)
98  return nullptr;
99  return ConstString(queue_name->c_str()).AsCString();
100 }
101 
103 
105 
107  if (!m_reg_context_sp)
109  return m_reg_context_sp;
110 }
111 
112 RegisterContextSP
114  const uint32_t concrete_frame_idx =
115  frame ? frame->GetConcreteFrameIndex() : 0;
116 
117  if (concrete_frame_idx)
119 
120  lldb::RegisterContextSP reg_ctx_sp;
121  Status error;
122 
123  llvm::Optional<std::string> reg_data = GetInterface()->GetRegisterContext();
124  if (!reg_data)
125  return ScriptedInterface::ErrorWithMessage<lldb::RegisterContextSP>(
126  LLVM_PRETTY_FUNCTION, "Failed to get scripted thread registers data.",
128 
129  DataBufferSP data_sp(
130  std::make_shared<DataBufferHeap>(reg_data->c_str(), reg_data->size()));
131 
132  if (!data_sp->GetByteSize())
133  return ScriptedInterface::ErrorWithMessage<lldb::RegisterContextSP>(
134  LLVM_PRETTY_FUNCTION, "Failed to copy raw registers data.", error,
136 
137  std::shared_ptr<RegisterContextMemory> reg_ctx_memory =
138  std::make_shared<RegisterContextMemory>(
140  if (!reg_ctx_memory)
141  return ScriptedInterface::ErrorWithMessage<lldb::RegisterContextSP>(
142  LLVM_PRETTY_FUNCTION, "Failed to create a register context.", error,
144 
145  reg_ctx_memory->SetAllRegisterData(data_sp);
146  m_reg_context_sp = reg_ctx_memory;
147 
148  return m_reg_context_sp;
149 }
150 
152  StructuredData::ArraySP arr_sp = GetInterface()->GetStackFrames();
153 
154  Status error;
155  if (!arr_sp)
156  return ScriptedInterface::ErrorWithMessage<bool>(
157  LLVM_PRETTY_FUNCTION, "Failed to get scripted thread stackframes.",
159 
160  size_t arr_size = arr_sp->GetSize();
161  if (arr_size > std::numeric_limits<uint32_t>::max())
162  return ScriptedInterface::ErrorWithMessage<bool>(
163  LLVM_PRETTY_FUNCTION,
164  llvm::Twine(
165  "StackFrame array size (" + llvm::Twine(arr_size) +
166  llvm::Twine(
167  ") is greater than maximum authorized for a StackFrameList."))
168  .str(),
170 
171  StackFrameListSP frames = GetStackFrameList();
172 
173  for (size_t idx = 0; idx < arr_size; idx++) {
175  if (!arr_sp->GetItemAtIndexAsDictionary(idx, dict) || !dict)
176  return ScriptedInterface::ErrorWithMessage<bool>(
177  LLVM_PRETTY_FUNCTION,
178  llvm::Twine(
179  "Couldn't get artificial stackframe dictionary at index (" +
180  llvm::Twine(idx) + llvm::Twine(") from stackframe array."))
181  .str(),
183 
185  if (!dict->GetValueForKeyAsInteger("pc", pc))
186  return ScriptedInterface::ErrorWithMessage<bool>(
187  LLVM_PRETTY_FUNCTION,
188  "Couldn't find value for key 'pc' in stackframe dictionary.", error,
190 
191  Address symbol_addr;
192  symbol_addr.SetLoadAddress(pc, &this->GetProcess()->GetTarget());
193 
195  bool cfa_is_valid = false;
196  const bool behaves_like_zeroth_frame = false;
197  SymbolContext sc;
198  symbol_addr.CalculateSymbolContext(&sc);
199 
200  StackFrameSP synth_frame_sp = std::make_shared<StackFrame>(
201  this->shared_from_this(), idx, idx, cfa, cfa_is_valid, pc,
202  StackFrame::Kind::Artificial, behaves_like_zeroth_frame, &sc);
203 
204  if (!frames->SetFrameAtIndex(static_cast<uint32_t>(idx), synth_frame_sp))
205  return ScriptedInterface::ErrorWithMessage<bool>(
206  LLVM_PRETTY_FUNCTION,
207  llvm::Twine("Couldn't add frame (" + llvm::Twine(idx) +
208  llvm::Twine(") to ScriptedThread StackFrameList."))
209  .str(),
211  }
212 
213  return true;
214 }
215 
217  StructuredData::DictionarySP dict_sp = GetInterface()->GetStopReason();
218 
219  Status error;
220  if (!dict_sp)
221  return ScriptedInterface::ErrorWithMessage<bool>(
222  LLVM_PRETTY_FUNCTION, "Failed to get scripted thread stop info.", error,
224 
225  lldb::StopInfoSP stop_info_sp;
226  lldb::StopReason stop_reason_type;
227 
228  if (!dict_sp->GetValueForKeyAsInteger("type", stop_reason_type))
229  return ScriptedInterface::ErrorWithMessage<bool>(
230  LLVM_PRETTY_FUNCTION,
231  "Couldn't find value for key 'type' in stop reason dictionary.", error,
233 
234  StructuredData::Dictionary *data_dict;
235  if (!dict_sp->GetValueForKeyAsDictionary("data", data_dict))
236  return ScriptedInterface::ErrorWithMessage<bool>(
237  LLVM_PRETTY_FUNCTION,
238  "Couldn't find value for key 'data' in stop reason dictionary.", error,
240 
241  switch (stop_reason_type) {
243  return true;
245  lldb::break_id_t break_id;
246  data_dict->GetValueForKeyAsInteger("break_id", break_id,
248  stop_info_sp =
250  } break;
252  int signal;
253  llvm::StringRef description;
254  data_dict->GetValueForKeyAsInteger("signal", signal,
256  data_dict->GetValueForKeyAsString("desc", description);
257  stop_info_sp =
258  StopInfo::CreateStopReasonWithSignal(*this, signal, description.data());
259  } break;
261 #if defined(__APPLE__)
262  StructuredData::Dictionary *mach_exception;
263  if (data_dict->GetValueForKeyAsDictionary("mach_exception",
264  mach_exception)) {
265  llvm::StringRef value;
266  mach_exception->GetValueForKeyAsString("type", value);
267  auto exc_type =
268  StopInfoMachException::MachException::ExceptionCode(value.data());
269 
270  if (!exc_type)
271  return false;
272 
273  uint32_t exc_data_size = 0;
274  llvm::SmallVector<uint64_t, 3> raw_codes;
275 
276  StructuredData::Array *exc_rawcodes;
277  mach_exception->GetValueForKeyAsArray("rawCodes", exc_rawcodes);
278  if (exc_rawcodes) {
279  auto fetch_data = [&raw_codes](StructuredData::Object *obj) {
280  if (!obj)
281  return false;
282  raw_codes.push_back(obj->GetIntegerValue());
283  return true;
284  };
285 
286  exc_rawcodes->ForEach(fetch_data);
287  exc_data_size = raw_codes.size();
288  }
289 
291  *this, *exc_type, exc_data_size,
292  exc_data_size >= 1 ? raw_codes[0] : 0,
293  exc_data_size >= 2 ? raw_codes[1] : 0,
294  exc_data_size >= 3 ? raw_codes[2] : 0);
295 
296  break;
297  }
298 #endif
299  stop_info_sp =
300  StopInfo::CreateStopReasonWithException(*this, "EXC_BAD_ACCESS");
301  } break;
302  default:
303  return ScriptedInterface::ErrorWithMessage<bool>(
304  LLVM_PRETTY_FUNCTION,
305  llvm::Twine("Unsupported stop reason type (" +
306  llvm::Twine(stop_reason_type) + llvm::Twine(")."))
307  .str(),
309  }
310 
311  if (!stop_info_sp)
312  return false;
313 
314  SetStopInfo(stop_info_sp);
315  return true;
316 }
317 
319  GetRegisterContext()->InvalidateIfNeeded(/*force=*/false);
321 }
322 
323 lldb::ScriptedThreadInterfaceSP ScriptedThread::GetInterface() const {
325 }
326 
327 std::shared_ptr<DynamicRegisterInfo> ScriptedThread::GetDynamicRegisterInfo() {
329 
330  if (!m_register_info_sp) {
331  StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo();
332 
333  Status error;
334  if (!reg_info)
336  std::shared_ptr<DynamicRegisterInfo>>(
337  LLVM_PRETTY_FUNCTION, "Failed to get scripted thread registers info.",
339 
340  m_register_info_sp = std::make_shared<DynamicRegisterInfo>(
342  }
343 
344  return m_register_info_sp;
345 }
346 
349 
350  Status error;
351  StructuredData::ArraySP extended_info_sp = GetInterface()->GetExtendedInfo();
352 
353  if (!extended_info_sp || !extended_info_sp->GetSize())
354  return ScriptedInterface::ErrorWithMessage<StructuredData::ObjectSP>(
355  LLVM_PRETTY_FUNCTION, "No extended information found", error);
356 
357  return extended_info_sp;
358 }
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:558
lldb_private::ExecutionContext
Definition: ExecutionContext.h:292
lldb_private::StructuredData::Dictionary
Definition: StructuredData.h:368
lldb_private::ScriptedThread::CheckInterpreterAndScriptObject
void CheckInterpreterAndScriptObject() const
Definition: ScriptedThread.cpp:25
lldb_private::ScriptedThread::CalculateStopInfo
bool CalculateStopInfo() override
Definition: ScriptedThread.cpp:216
lldb_private::ScriptedThread::m_register_info_sp
std::shared_ptr< DynamicRegisterInfo > m_register_info_sp
Definition: ScriptedThread.h:75
lldb_private::StructuredData::Array
Definition: StructuredData.h:171
lldb_private::StructuredData::GenericSP
std::shared_ptr< Generic > GenericSP
Definition: StructuredData.h:68
lldb_private::Thread::GetUnwinder
virtual Unwind & GetUnwinder()
Definition: Thread.cpp:1877
lldb_private::ScriptedProcess::GetInterface
ScriptedProcessInterface & GetInterface() const
Definition: ScriptedProcess.cpp:501
lldb_private::ScriptedProcessInterface::GetScriptedThreadPluginName
virtual llvm::Optional< std::string > GetScriptedThreadPluginName()
Definition: ScriptedProcessInterface.h:65
lldb_private::Thread::ClearStackFrames
virtual void ClearStackFrames()
Definition: Thread.cpp:1433
Unwind.h
StopInfoMachException.h
lldb_private::Process::GetTarget
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1219
lldb_private::StopInfo::CreateStopReasonWithSignal
static lldb::StopInfoSP CreateStopReasonWithSignal(Thread &thread, int signo, const char *description=nullptr)
Definition: StopInfo.cpp:1375
lldb::StopReason
StopReason
Thread stop reasons.
Definition: lldb-enumerations.h:240
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:192
lldb::eStopReasonException
@ eStopReasonException
Definition: lldb-enumerations.h:247
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:86
lldb_private::SymbolContext
Definition: SymbolContext.h:33
lldb_private::ScriptedThread::~ScriptedThread
~ScriptedThread() override
Definition: ScriptedThread.cpp:84
Process.h
lldb_private::StructuredData::Dictionary::GetValueForKeyAsInteger
bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const
Definition: StructuredData.h:429
lldb_private::ScriptedThread::LoadArtificialStackFrames
bool LoadArtificialStackFrames()
Definition: ScriptedThread.cpp:151
lldb_private::ScriptedThread::ClearStackFrames
void ClearStackFrames() override
Definition: ScriptedThread.cpp:104
lldb_private::ScriptedThread::RefreshStateAfterStop
void RefreshStateAfterStop() override
Definition: ScriptedThread.cpp:318
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:412
lldb_private::Thread::GetProcess
lldb::ProcessSP GetProcess() const
Definition: Thread.h:153
lldb_private::Thread::DestroyThread
virtual void DestroyThread()
Definition: Thread.cpp:250
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:113
lldb_private::Thread
Definition: Thread.h:61
lldb_private::ScriptedThread::GetRegisterContext
lldb::RegisterContextSP GetRegisterContext() override
Definition: ScriptedThread.cpp:106
lldb::eStopReasonNone
@ eStopReasonNone
Definition: lldb-enumerations.h:242
lldb_private::StructuredData::ObjectSP
std::shared_ptr< Object > ObjectSP
Definition: StructuredData.h:59
lldb_private::ScriptedThread::FetchThreadExtendedInfo
StructuredData::ObjectSP FetchThreadExtendedInfo() override
Definition: ScriptedThread.cpp:347
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:39
lldb_private::Thread::SetStopInfo
void SetStopInfo(const lldb::StopInfoSP &stop_info_sp)
Definition: Thread.cpp:445
lldb_private::StructuredData::DictionarySP
std::shared_ptr< Dictionary > DictionarySP
Definition: StructuredData.h:67
lldb_private::StructuredData::Generic
Definition: StructuredData.h:563
lldb_private::ScriptedThread::m_scripted_thread_interface_sp
lldb::ScriptedThreadInterfaceSP m_scripted_thread_interface_sp
Definition: ScriptedThread.h:73
lldb_private::ScriptedProcessInterface::CreateScriptedThreadInterface
virtual lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface()
Definition: ScriptedProcessInterface.h:73
lldb_private::ScriptedInterface::ErrorWithMessage
static Ret ErrorWithMessage(llvm::StringRef caller_name, llvm::StringRef error_msg, Status &error, LLDBLog log_caterogy=LLDBLog::Process)
Definition: ScriptedInterface.h:34
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:246
lldb_private::Target::GetArchitecture
const ArchSpec & GetArchitecture() const
Definition: Target.h:989
lldb_private::Thread::GetStackFrameList
lldb::StackFrameListSP GetStackFrameList()
Definition: Thread.cpp:1423
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:1271
uint32_t
lldb_private::ScriptedThread::GetInterface
lldb::ScriptedThreadInterfaceSP GetInterface() const
Definition: ScriptedThread.cpp:323
lldb_private::ScriptedThread::m_scripted_process
const ScriptedProcess & m_scripted_process
Definition: ScriptedThread.h:72
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:244
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:102
lldb_private::ScriptedThread::GetDynamicRegisterInfo
std::shared_ptr< DynamicRegisterInfo > GetDynamicRegisterInfo()
Definition: ScriptedThread.cpp:327
lldb_private::StopInfoMachException::CreateStopReasonWithMachException
static lldb::StopInfoSP CreateStopReasonWithMachException(Thread &thread, uint32_t exc_type, uint32_t exc_data_count, uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code, bool pc_already_adjusted=true, bool adjust_pc_if_needed=false)
Definition: StopInfoMachException.cpp:597
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::StructuredData::Dictionary::GetValueForKeyAsDictionary
bool GetValueForKeyAsDictionary(llvm::StringRef key, Dictionary *&result) const
Definition: StructuredData.h:493
lldb_private::ScriptedProcess::ScriptedProcessInfo::GetArgsSP
StructuredData::DictionarySP GetArgsSP() const
Definition: ScriptedProcess.h:32
lldb::StateType
StateType
Process and Thread States.
Definition: lldb-enumerations.h:74
lldb_private::StopInfo::CreateStopReasonWithBreakpointSiteID
static lldb::StopInfoSP CreateStopReasonWithBreakpointSiteID(Thread &thread, lldb::break_id_t break_id)
Definition: StopInfo.cpp:1358
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:449
lldb_private::StructuredData::Dictionary::GetValueForKeyAsArray
bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const
Definition: StructuredData.h:504
lldb_private::ScriptedThread::GetQueueName
const char * GetQueueName() override
Retrieve the Queue name for the queue currently using this Thread.
Definition: ScriptedThread.cpp:94
lldb_private::StackFrame
Definition: StackFrame.h:40
lldb_private::StopInfo::CreateStopReasonWithException
static lldb::StopInfoSP CreateStopReasonWithException(Thread &thread, const char *description)
Definition: StopInfo.cpp:1392
lldb_private::ScriptedProcess::CheckInterpreterAndScriptObject
void CheckInterpreterAndScriptObject() const
Definition: ScriptedProcess.cpp:48
lldb_private::StructuredData::Object
Definition: StructuredData.h:70
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
lldb_private::StructuredData::Array::ForEach
bool ForEach(std::function< bool(Object *object)> const &foreach_callback) const
Definition: StructuredData.h:178
DataBufferHeap.h
lldb::tid_t
uint64_t tid_t
Definition: lldb-types.h:86