Add the ability to capture the return value in a thread's stop info, and print it

as part of the thread format output.
Currently this is only done for the ThreadPlanStepOut.
Add a convenience API ABI::GetReturnValueObject.
Change the ValueObject::EvaluationPoint to BE an ExecutionContextScope, rather than
trying to hand out one of its subsidiary object's pointers.  That way this will always
be good.

llvm-svn: 146806
This commit is contained in:
Jim Ingham
2011-12-17 01:35:57 +00:00
parent 903231bc58
commit 73ca05a2a0
22 changed files with 316 additions and 40 deletions

View File

@@ -63,6 +63,9 @@ public:
size_t
GetStopDescription (char *dst, size_t dst_len);
SBValue
GetStopReturnValue ();
lldb::tid_t
GetThreadID () const;

View File

@@ -336,7 +336,7 @@ public:
};
class EvaluationPoint
class EvaluationPoint : public ExecutionContextScope
{
public:
@@ -348,9 +348,6 @@ public:
~EvaluationPoint ();
ExecutionContextScope *
GetExecutionContextScope ();
const lldb::TargetSP &
GetTargetSP () const
{
@@ -443,6 +440,20 @@ public:
}
// If this EvaluationPoint is created without a target, then we could have it
// hand out a NULL ExecutionContextScope. But then everybody would have to check that before
// calling through it, which is annoying. So instead, we make the EvaluationPoint BE an
// ExecutionContextScope, and it hands out the right things.
virtual Target *CalculateTarget ();
virtual Process *CalculateProcess ();
virtual Thread *CalculateThread ();
virtual StackFrame *CalculateStackFrame ();
virtual void CalculateExecutionContext (ExecutionContext &exe_ctx);
private:
bool
SyncWithProcessState ()
@@ -479,7 +490,7 @@ public:
ExecutionContextScope *
GetExecutionContextScope ()
{
return m_update_point.GetExecutionContextScope();
return &m_update_point;
}
void

View File

@@ -59,6 +59,12 @@ public:
AddressType address_type,
uint8_t addr_byte_size);
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope,
clang::ASTContext *clang_ast,
Value &value,
const ConstString &name);
// When an expression fails to evaluate, we return an error
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope,
@@ -180,6 +186,11 @@ private:
AddressType address_type,
uint8_t addr_byte_size);
ValueObjectConstResult (ExecutionContextScope *exe_scope,
clang::ASTContext *clang_ast,
const Value &value,
const ConstString &name);
ValueObjectConstResult (ExecutionContextScope *exe_scope,
const Error& error);

View File

@@ -48,6 +48,10 @@ public:
virtual bool
GetReturnValue (Thread &thread,
Value &value) const = 0;
virtual lldb::ValueObjectSP
GetReturnValueObject (Thread &thread,
ClangASTType &type) const;
virtual bool
CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) = 0;

View File

@@ -126,10 +126,13 @@ public:
CreateStopReasonToTrace (Thread &thread);
static lldb::StopInfoSP
CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan);
CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan, lldb::ValueObjectSP return_valobj_sp);
static lldb::StopInfoSP
CreateStopReasonWithException (Thread &thread, const char *description);
static lldb::ValueObjectSP
GetReturnValueObject (lldb::StopInfoSP &stop_info_sp);
protected:
//------------------------------------------------------------------

View File

@@ -604,7 +604,7 @@ private:
public:
//------------------------------------------------------------------
/// Gets the inner-most plan that was popped off the plan stack in the
/// Gets the outer-most plan that was popped off the plan stack in the
/// most recent stop. Useful for printing the stop reason accurately.
///
/// @return
@@ -613,6 +613,16 @@ public:
lldb::ThreadPlanSP
GetCompletedPlan ();
//------------------------------------------------------------------
/// Gets the outer-most return value from the completed plans
///
/// @return
/// A ValueObjectSP, either empty if there is no return value,
/// or containing the return value.
//------------------------------------------------------------------
lldb::ValueObjectSP
GetReturnValueObject ();
//------------------------------------------------------------------
/// Checks whether the given plan is in the completed plans for this
/// stop.

View File

@@ -387,6 +387,12 @@ public:
return m_thread.GetStopInfo ();
}
virtual lldb::ValueObjectSP
GetReturnValueObject ()
{
return lldb::ValueObjectSP();
}
protected:
//------------------------------------------------------------------
// Classes that inherit from ThreadPlan can see and modify these

View File

@@ -42,6 +42,11 @@ public:
virtual bool WillStop ();
virtual bool MischiefManaged ();
virtual void DidPush();
virtual lldb::ValueObjectSP GetReturnValueObject()
{
return m_return_valobj_sp;
}
protected:
bool QueueInlinedStepPlan (bool queue_now);
@@ -56,6 +61,8 @@ private:
bool m_stop_others;
lldb::ThreadPlanSP m_step_through_inline_plan_sp;
lldb::ThreadPlanSP m_step_out_plan_sp;
Function *m_immediate_step_from_function;
lldb::ValueObjectSP m_return_valobj_sp;
friend ThreadPlan *
Thread::QueueThreadPlanForStepOut (bool abort_other_plans,
@@ -69,6 +76,9 @@ private:
// Need an appropriate marker for the current stack so we can tell step out
// from step in.
void
CalculateReturnValue();
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOut);
};

View File

@@ -82,6 +82,9 @@ public:
size_t
GetStopDescription (char *dst, size_t dst_len);
SBValue
GetStopReturnValue ();
lldb::tid_t
GetThreadID () const;

View File

@@ -31,10 +31,10 @@
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBFrame.h"
// DONT THINK THIS IS NECESSARY: #include "lldb/API/SBSourceManager.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBValue.h"
using namespace lldb;
using namespace lldb_private;
@@ -316,6 +316,30 @@ SBThread::GetStopDescription (char *dst, size_t dst_len)
return 0;
}
SBValue
SBThread::GetStopReturnValue ()
{
ValueObjectSP return_valobj_sp;
if (m_opaque_sp)
{
Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex());
StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo ();
if (stop_info_sp)
{
return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
}
}
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBThread(%p)::GetStopReturnValue () => %s", m_opaque_sp.get(),
return_valobj_sp.get()
? return_valobj_sp->GetValueAsCString()
: "<no return value>");
return SBValue (return_valobj_sp);
}
void
SBThread::SetThread (const ThreadSP& lldb_object_sp)
{

View File

@@ -380,7 +380,7 @@ SBValue::CreateValueFromExpression (const char *name, const char* expression)
{
ValueObjectSP result_valobj_sp;
m_opaque_sp->GetUpdatePoint().GetTargetSP()->EvaluateExpression (expression,
m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateStackFrame(),
m_opaque_sp->GetExecutionContextScope()->CalculateStackFrame(),
eExecutionPolicyOnlyWhenNeeded,
true, // unwind on error
true, // keep in memory
@@ -410,7 +410,7 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType t
lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t)));
ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope(),
ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (m_opaque_sp->GetExecutionContextScope(),
real_type.m_opaque_sp->GetASTContext(),
real_type.m_opaque_sp->GetOpaqueQualType(),
ConstString(name),
@@ -871,9 +871,9 @@ SBValue::GetThread()
SBThread result;
if (m_opaque_sp)
{
if (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope())
if (m_opaque_sp->GetExecutionContextScope())
{
result = SBThread(m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateThread()->GetSP());
result = SBThread(m_opaque_sp->GetExecutionContextScope()->CalculateThread()->GetSP());
}
}
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -893,9 +893,9 @@ SBValue::GetFrame()
SBFrame result;
if (m_opaque_sp)
{
if (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope())
if (m_opaque_sp->GetExecutionContextScope())
{
result.SetFrame (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateStackFrame()->GetSP());
result.SetFrame (m_opaque_sp->GetExecutionContextScope()->CalculateStackFrame()->GetSP());
}
}
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

View File

@@ -1246,7 +1246,7 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
interpreter,
"thread step-out",
"Finish executing the current function and return to its call site in specified thread (current thread, if none specified).",
"Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
eStepTypeOut,

View File

@@ -1701,6 +1701,23 @@ Debugger::FormatPrompt
}
}
}
else if (::strncmp (var_name_begin, "return-value}", strlen("return-value}")) == 0)
{
StopInfoSP stop_info_sp = thread->GetStopInfo ();
if (stop_info_sp)
{
ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
if (return_valobj_sp)
{
cstr = return_valobj_sp->GetValueAsCString ();
if (cstr && cstr[0])
{
s.PutCString(cstr);
var_success = true;
}
}
}
}
}
}
}
@@ -2562,6 +2579,7 @@ Debugger::SettingsController::global_settings_table[] =
MODULE_WITH_FUNC\
FILE_AND_LINE\
"{, stop reason = ${thread.stop-reason}}"\
"{, return value = ${thread.return-value}}"\
"\\n"
//#define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\

View File

@@ -707,7 +707,7 @@ ValueObject::GetPointeeData (DataExtractor& data,
AddressType addr_type;
lldb::addr_t addr = IsPointerType() ? GetPointerValue(&addr_type) : GetAddressOf(true, &addr_type);
ExecutionContextScope *exe_scope = m_update_point.GetExecutionContextScope();
ExecutionContextScope *exe_scope = GetExecutionContextScope();
switch (addr_type)
@@ -3428,12 +3428,14 @@ ValueObject::CastPointerType (const char *name, TypeSP &type_sp)
}
ValueObject::EvaluationPoint::EvaluationPoint () :
ExecutionContextScope(),
m_thread_id (LLDB_INVALID_UID),
m_mod_id ()
{
}
ValueObject::EvaluationPoint::EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected):
ExecutionContextScope (),
m_needs_update (true),
m_first_update (true),
m_thread_id (LLDB_INVALID_THREAD_ID),
@@ -3500,14 +3502,47 @@ ValueObject::EvaluationPoint::~EvaluationPoint ()
{
}
ExecutionContextScope *
ValueObject::EvaluationPoint::GetExecutionContextScope ()
Target *
ValueObject::EvaluationPoint::CalculateTarget ()
{
// We have to update before giving out the scope, or we could be handing out stale pointers.
ExecutionContextScope *exe_scope;
return m_target_sp.get();
}
Process *
ValueObject::EvaluationPoint::CalculateProcess ()
{
return m_process_sp.get();
}
Thread *
ValueObject::EvaluationPoint::CalculateThread ()
{
ExecutionContextScope *exe_scope;
SyncWithProcessState(exe_scope);
return exe_scope;
if (exe_scope)
return exe_scope->CalculateThread();
else
return NULL;
}
StackFrame *
ValueObject::EvaluationPoint::CalculateStackFrame ()
{
ExecutionContextScope *exe_scope;
SyncWithProcessState(exe_scope);
if (exe_scope)
return exe_scope->CalculateStackFrame();
else
return NULL;
}
void
ValueObject::EvaluationPoint::CalculateExecutionContext (ExecutionContext &exe_ctx)
{
ExecutionContextScope *exe_scope;
SyncWithProcessState(exe_scope);
if (exe_scope)
return exe_scope->CalculateExecutionContext (exe_ctx);
}
// This function checks the EvaluationPoint against the current process state. If the current
@@ -3520,12 +3555,18 @@ ValueObject::EvaluationPoint::GetExecutionContextScope ()
bool
ValueObject::EvaluationPoint::SyncWithProcessState(ExecutionContextScope *&exe_scope)
{
// Start with the target, if it is NULL, then we're obviously not going to get any further:
exe_scope = m_target_sp.get();
if (exe_scope == NULL)
return false;
// If we don't have a process nothing can change.
if (!m_process_sp)
{
exe_scope = m_target_sp.get();
return false;
}
exe_scope = m_process_sp.get();
// If our stop id is the current stop ID, nothing has changed:
ProcessModID current_mod_id = m_process_sp->GetModID();
@@ -3533,10 +3574,7 @@ ValueObject::EvaluationPoint::SyncWithProcessState(ExecutionContextScope *&exe_s
// If the current stop id is 0, either we haven't run yet, or the process state has been cleared.
// In either case, we aren't going to be able to sync with the process state.
if (current_mod_id.GetStopID() == 0)
{
exe_scope = m_target_sp.get();
return false;
}
bool changed;
@@ -3555,10 +3593,10 @@ ValueObject::EvaluationPoint::SyncWithProcessState(ExecutionContextScope *&exe_s
changed = true;
}
}
exe_scope = m_process_sp.get();
// Something has changed, so we will return true. Now make sure the thread & frame still exist, and if either
// doesn't, mark ourselves as invalid.
// Now re-look up the thread and frame in case the underlying objects have gone away & been recreated.
// That way we'll be sure to return a valid exe_scope.
// If we used to have a thread or a frame but can't find it anymore, then mark ourselves as invalid.
if (m_thread_id != LLDB_INVALID_THREAD_ID)
{

View File

@@ -130,6 +130,15 @@ ValueObjectConstResult::Create
address))->GetSP();
}
ValueObjectSP
ValueObjectConstResult::Create (ExecutionContextScope *exe_scope,
clang::ASTContext *clang_ast,
Value &value,
const ConstString &name)
{
return (new ValueObjectConstResult (exe_scope, clang_ast, value, name))->GetSP();
}
ValueObjectConstResult::ValueObjectConstResult
(
ExecutionContextScope *exe_scope,
@@ -239,6 +248,21 @@ ValueObjectConstResult::ValueObjectConstResult (
SetIsConstant ();
}
ValueObjectConstResult::ValueObjectConstResult (
ExecutionContextScope *exe_scope,
clang::ASTContext *clang_ast,
const Value &value,
const ConstString &name) :
ValueObject (exe_scope),
m_type_name (),
m_byte_size (0),
m_clang_ast (clang_ast),
m_impl(this)
{
m_value = value;
m_value.GetData(m_data);
}
ValueObjectConstResult::~ValueObjectConstResult()
{
}

View File

@@ -185,7 +185,7 @@ ValueObjectConstResultImpl::AddressOf (Error &error)
std::string new_name("&");
new_name.append(m_impl_backend->GetName().AsCString(""));
m_address_of_backend = ValueObjectConstResult::Create(m_impl_backend->GetUpdatePoint().GetExecutionContextScope(),
m_address_of_backend = ValueObjectConstResult::Create(m_impl_backend->GetExecutionContextScope(),
type.GetASTContext(),
type.GetPointerType(),
ConstString(new_name.c_str()),

View File

@@ -309,7 +309,7 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
// If the class address didn't point into the binary, or
// it points into the right section but there wasn't a symbol
// there, try to look it up by calling the class method in the target.
ExecutionContextScope *exe_scope = in_value.GetUpdatePoint().GetExecutionContextScope();
ExecutionContextScope *exe_scope = in_value.GetExecutionContextScope();
Thread *thread_to_use;
if (exe_scope)
thread_to_use = exe_scope->CalculateThread();

View File

@@ -9,6 +9,10 @@
#include "lldb/Target/ABI.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
@@ -97,3 +101,28 @@ ABI::GetRegisterInfoByKind (RegisterKind reg_kind, uint32_t reg_num, RegisterInf
}
return false;
}
ValueObjectSP
ABI::GetReturnValueObject (Thread &thread,
ClangASTType &ast_type) const
{
if (!ast_type.IsValid())
return ValueObjectSP();
Value ret_value;
ret_value.SetContext(Value::eContextTypeClangType,
ast_type.GetOpaqueQualType());
if (GetReturnValue (thread, ret_value))
{
return ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(),
ast_type.GetASTContext(),
ret_value,
ConstString("FunctionReturn"));
}
else
return ValueObjectSP();
}

View File

@@ -722,9 +722,10 @@ class StopInfoThreadPlan : public StopInfo
{
public:
StopInfoThreadPlan (ThreadPlanSP &plan_sp) :
StopInfoThreadPlan (ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp) :
StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID),
m_plan_sp (plan_sp)
m_plan_sp (plan_sp),
m_return_valobj_sp (return_valobj_sp)
{
}
@@ -749,9 +750,16 @@ public:
}
return m_description.c_str();
}
ValueObjectSP
GetReturnValueObject()
{
return m_return_valobj_sp;
}
private:
ThreadPlanSP m_plan_sp;
ValueObjectSP m_return_valobj_sp;
};
} // namespace lldb_private
@@ -786,9 +794,9 @@ StopInfo::CreateStopReasonToTrace (Thread &thread)
}
StopInfoSP
StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp)
StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp, ValueObjectSP return_valobj_sp)
{
return StopInfoSP (new StopInfoThreadPlan (plan_sp));
return StopInfoSP (new StopInfoThreadPlan (plan_sp, return_valobj_sp));
}
StopInfoSP
@@ -796,3 +804,15 @@ StopInfo::CreateStopReasonWithException (Thread &thread, const char *description
{
return StopInfoSP (new StopInfoException (thread, description));
}
ValueObjectSP
StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp)
{
if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonPlanComplete)
{
StopInfoThreadPlan *plan_stop_info = static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
return plan_stop_info->GetReturnValueObject();
}
else
return ValueObjectSP();
}

View File

@@ -95,7 +95,7 @@ Thread::GetStopInfo ()
{
ThreadPlanSP plan_sp (GetCompletedPlan());
if (plan_sp)
return StopInfo::CreateStopReasonWithPlan (plan_sp);
return StopInfo::CreateStopReasonWithPlan (plan_sp, GetReturnValueObject());
else
{
if (m_actual_stop_info_sp
@@ -551,6 +551,22 @@ Thread::GetCompletedPlan ()
return empty_plan_sp;
}
ValueObjectSP
Thread::GetReturnValueObject ()
{
if (!m_completed_plan_stack.empty())
{
for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
{
ValueObjectSP return_valobj_sp;
return_valobj_sp = m_completed_plan_stack[i]->GetReturnValueObject();
if (return_valobj_sp)
return return_valobj_sp;
}
}
return ValueObjectSP();
}
bool
Thread::IsThreadPlanDone (ThreadPlan *plan)
{

View File

@@ -16,6 +16,8 @@
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/lldb-private-log.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
@@ -47,7 +49,8 @@ ThreadPlanStepOut::ThreadPlanStepOut
m_first_insn (first_insn),
m_stop_others (stop_others),
m_step_through_inline_plan_sp(),
m_step_out_plan_sp ()
m_step_out_plan_sp (),
m_immediate_step_from_function(NULL)
{
m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
@@ -88,6 +91,15 @@ ThreadPlanStepOut::ThreadPlanStepOut
return_bp->SetThreadID(m_thread.GetID());
m_return_bp_id = return_bp->GetID();
}
if (immediate_return_from_sp)
{
const SymbolContext &sc = immediate_return_from_sp->GetSymbolContext(eSymbolContextFunction);
if (sc.function)
{
m_immediate_step_from_function = sc.function;
}
}
}
}
@@ -152,6 +164,7 @@ ThreadPlanStepOut::PlanExplainsStop ()
if (m_step_out_plan_sp->MischiefManaged())
{
// If this one is done, then we are all done.
CalculateReturnValue();
SetPlanComplete();
return true;
}
@@ -183,7 +196,10 @@ ThreadPlanStepOut::PlanExplainsStop ()
{
const uint32_t num_frames = m_thread.GetStackFrameCount();
if (m_stack_depth > num_frames)
{
CalculateReturnValue();
SetPlanComplete();
}
// If there was only one owner, then we're done. But if we also hit some
// user breakpoint on our way out, we should mark ourselves as done, but
@@ -217,6 +233,7 @@ ThreadPlanStepOut::ShouldStop (Event *event_ptr)
}
else if (m_stack_depth > m_thread.GetStackFrameCount())
{
CalculateReturnValue();
SetPlanComplete();
return true;
}
@@ -233,6 +250,7 @@ ThreadPlanStepOut::ShouldStop (Event *event_ptr)
}
else
{
CalculateReturnValue();
SetPlanComplete ();
return true;
}
@@ -244,6 +262,10 @@ ThreadPlanStepOut::ShouldStop (Event *event_ptr)
{
if (m_step_through_inline_plan_sp->MischiefManaged())
{
// We don't calculate the return value here because we don't know how to.
// But in case we had a return value sitting around from our process in
// getting here, let's clear it out.
m_return_valobj_sp.reset();
SetPlanComplete();
return true;
}
@@ -387,3 +409,26 @@ ThreadPlanStepOut::QueueInlinedStepPlan (bool queue_now)
return false;
}
void
ThreadPlanStepOut::CalculateReturnValue ()
{
if (m_return_valobj_sp)
return;
if (m_immediate_step_from_function != NULL)
{
Type *return_type = m_immediate_step_from_function->GetType();
lldb::clang_type_t return_clang_type = m_immediate_step_from_function->GetReturnClangType();
if (return_type && return_clang_type)
{
ClangASTType ast_type (return_type->GetClangAST(), return_clang_type);
lldb::ABISP abi_sp = m_thread.GetProcess().GetABI();
if (abi_sp)
{
m_return_valobj_sp = abi_sp->GetReturnValueObject(m_thread, ast_type);
}
}
}
}

View File

@@ -97,6 +97,7 @@
<tr valign=top><td><b>thread.name</b></td><td>The name of the thread if the target OS supports naming threads</td></tr>
<tr valign=top><td><b>thread.queue</b></td><td>The queue name of the thread if the target OS supports dispatch queues</td></tr>
<tr valign=top><td><b>thread.stop-reason</b></td><td>A textual reason each thread stopped</td></tr>
<tr valign=top><td><b>thread.return-value</b></td><td>The return value of the latest step operation (currently only for step-out.)</td></tr>
<tr valign=top><td><b>target.arch</b></td><td>The architecture of the current target</td></tr>
</table>