forked from OSchip/llvm-project
Add the ability to set timeout & "run all threads" options both from the "expr" command and from
the SB API's that evaluate expressions. <rdar://problem/12457211> llvm-svn: 166062
This commit is contained in:
parent
02a1141e5a
commit
35e1bda695
|
@ -41,6 +41,7 @@ class SBDeclaration;
|
|||
class SBError;
|
||||
class SBEvent;
|
||||
class SBEventList;
|
||||
class SBExpressionOptions;
|
||||
class SBFileSpec;
|
||||
class SBFileSpecList;
|
||||
class SBFrame;
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
//===-- SBEvent.h -----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLDB_SBExpressionOptions_h_
|
||||
#define LLDB_SBExpressionOptions_h_
|
||||
|
||||
#include "lldb/API/SBDefines.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace lldb {
|
||||
|
||||
|
||||
class SBExpressionOptions
|
||||
{
|
||||
friend class SBFrame;
|
||||
friend class SBValue;
|
||||
|
||||
public:
|
||||
SBExpressionOptions();
|
||||
|
||||
SBExpressionOptions (const lldb::SBExpressionOptions &rhs);
|
||||
|
||||
SBExpressionOptions (bool coerce_to_id,
|
||||
bool unwind_on_error,
|
||||
bool keep_in_memory,
|
||||
bool run_others,
|
||||
DynamicValueType use_dynamic,
|
||||
uint32_t timeout_usec);
|
||||
|
||||
~SBExpressionOptions();
|
||||
|
||||
const SBExpressionOptions &
|
||||
operator = (const lldb::SBExpressionOptions &rhs);
|
||||
|
||||
bool
|
||||
DoesCoerceToId () const;
|
||||
|
||||
void
|
||||
SetCoerceToId (bool coerce = true);
|
||||
|
||||
bool
|
||||
DoesUnwindOnError () const;
|
||||
|
||||
void
|
||||
SetUnwindOnError (bool unwind = false);
|
||||
|
||||
bool
|
||||
DoesKeepInMemory () const;
|
||||
|
||||
void
|
||||
SetKeepInMemory (bool keep = true);
|
||||
|
||||
lldb::DynamicValueType
|
||||
GetUseDynamic () const;
|
||||
|
||||
void
|
||||
SetUseDynamic (lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget);
|
||||
|
||||
uint32_t
|
||||
GetTimeoutUsec () const;
|
||||
|
||||
void
|
||||
SetTimeoutUsec (uint32_t timeout = 0);
|
||||
|
||||
bool
|
||||
GetRunOthers () const;
|
||||
|
||||
void
|
||||
SetRunOthers (bool run_others = true);
|
||||
|
||||
protected:
|
||||
|
||||
SBExpressionOptions (lldb_private::EvaluateExpressionOptions &expression_options);
|
||||
|
||||
lldb_private::EvaluateExpressionOptions *
|
||||
get () const;
|
||||
|
||||
lldb_private::EvaluateExpressionOptions &
|
||||
ref () const;
|
||||
|
||||
private:
|
||||
// This auto_pointer is made in the constructor and is always valid.
|
||||
mutable std::auto_ptr<lldb_private::EvaluateExpressionOptions> m_opaque_ap;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_SBExpressionOptions_h_
|
|
@ -105,6 +105,9 @@ public:
|
|||
|
||||
lldb::SBValue
|
||||
EvaluateExpression (const char *expr, lldb::DynamicValueType use_dynamic, bool unwind_on_error);
|
||||
|
||||
lldb::SBValue
|
||||
EvaluateExpression (const char *expr, const SBExpressionOptions &options);
|
||||
|
||||
/// Gets the lexical block that defines the stack frame. Another way to think
|
||||
/// of this is it will return the block that contains all of the variables
|
||||
|
|
|
@ -136,6 +136,9 @@ public:
|
|||
lldb::SBValue
|
||||
CreateValueFromExpression (const char *name, const char* expression);
|
||||
|
||||
lldb::SBValue
|
||||
CreateValueFromExpression (const char *name, const char* expression, SBExpressionOptions &options);
|
||||
|
||||
lldb::SBValue
|
||||
CreateValueFromAddress (const char* name,
|
||||
lldb::addr_t address,
|
||||
|
|
|
@ -251,9 +251,10 @@ public:
|
|||
/// function call, and return the program state to what it was before the
|
||||
/// execution. If false, we leave the program in the stopped state.
|
||||
///
|
||||
/// @param[in] single_thread_timeout_usec
|
||||
/// If stop_others is true, the length of time to wait before
|
||||
/// concluding that the system is deadlocked.
|
||||
/// @param[in] timeout_usec
|
||||
/// Timeout value (0 for no timeout). If try_all_threads is true, then we
|
||||
/// will try on one thread for the lesser of .25 sec and half the total timeout.
|
||||
/// then switch to running all threads, otherwise this will be the total timeout.
|
||||
///
|
||||
/// @param[in] errors
|
||||
/// The stream to write errors to.
|
||||
|
@ -272,7 +273,7 @@ public:
|
|||
bool stop_others,
|
||||
bool try_all_threads,
|
||||
bool discard_on_error,
|
||||
uint32_t single_thread_timeout_usec,
|
||||
uint32_t timeout_usec,
|
||||
Stream &errors,
|
||||
lldb::addr_t* this_arg = 0);
|
||||
|
||||
|
@ -329,7 +330,7 @@ public:
|
|||
//------------------------------------------------------------------
|
||||
/// Run the function this ClangFunction was created with.
|
||||
///
|
||||
/// This simple version will run the function on one thread. If \a single_thread_timeout_usec
|
||||
/// This simple version will run the function on one thread. If \a timeout_usec
|
||||
/// is not zero, we time out after that timeout. If \a try_all_threads is true, then we will
|
||||
/// resume with all threads on, otherwise we halt the process, and eExecutionInterrupted will be returned.
|
||||
///
|
||||
|
@ -339,8 +340,10 @@ public:
|
|||
/// @param[in] errors
|
||||
/// Errors will be written here if there are any.
|
||||
///
|
||||
/// @param[in] single_thread_timeout_usec
|
||||
/// If \b true, run only this thread, if \b false let all threads run.
|
||||
/// @param[in] timeout_usec
|
||||
/// Timeout value (0 for no timeout). If try_all_threads is true, then we
|
||||
/// will try on one thread for the lesser of .25 sec and half the total timeout.
|
||||
/// then switch to running all threads, otherwise this will be the total timeout.
|
||||
///
|
||||
/// @param[in] try_all_threads
|
||||
/// If \b true, run only this thread, if \b false let all threads run.
|
||||
|
@ -379,8 +382,11 @@ public:
|
|||
/// @param[in] stop_others
|
||||
/// If \b true, run only this thread, if \b false let all threads run.
|
||||
///
|
||||
/// @param[in] single_thread_timeout_usec
|
||||
/// If \b true, run only this thread, if \b false let all threads run.
|
||||
/// @param[in] timeout_usec
|
||||
/// Timeout value (0 for no timeout). If try_all_threads is true, then we
|
||||
/// will try on one thread for the lesser of .25 sec and half the total timeout.
|
||||
/// then switch to running all threads, otherwise this will be the total timeout.
|
||||
///
|
||||
///
|
||||
/// @param[in] try_all_threads
|
||||
/// If \b true, run only this thread, if \b false let all threads run.
|
||||
|
@ -396,7 +402,7 @@ public:
|
|||
lldb::addr_t *args_addr_ptr,
|
||||
Stream &errors,
|
||||
bool stop_others,
|
||||
uint32_t single_thread_timeout_usec,
|
||||
uint32_t timeout_usec,
|
||||
bool try_all_threads,
|
||||
bool discard_on_error,
|
||||
Value &results);
|
||||
|
|
|
@ -132,9 +132,16 @@ public:
|
|||
/// A pointer to direct at the persistent variable in which the
|
||||
/// expression's result is stored.
|
||||
///
|
||||
/// @param[in] single_thread_timeout_usec
|
||||
/// The amount of time (in usec) that we are willing to wait for this
|
||||
/// expression to complete, before assuming that we are blocked and giving up
|
||||
/// @param[in] try_all_threads
|
||||
/// If true, then we will try to run all threads if the function doesn't complete on
|
||||
/// one thread. See timeout_usec for the interaction of this variable and
|
||||
/// the timeout.
|
||||
///
|
||||
/// @param[in] timeout_usec
|
||||
/// Timeout value (0 for no timeout). If try_all_threads is true, then we
|
||||
/// will try on one thread for the lesser of .25 sec and half the total timeout.
|
||||
/// then switch to running all threads, otherwise this will be the total timeout.
|
||||
///
|
||||
///
|
||||
/// @return
|
||||
/// A Process::Execution results value.
|
||||
|
@ -145,7 +152,8 @@ public:
|
|||
bool discard_on_error,
|
||||
ClangUserExpressionSP &shared_ptr_to_me,
|
||||
lldb::ClangExpressionVariableSP &result,
|
||||
uint32_t single_thread_timeout_usec = 500000);
|
||||
bool try_all_threads = true,
|
||||
uint32_t timeout_usec = 500000);
|
||||
|
||||
ThreadPlan *
|
||||
GetThreadPlanToExecuteJITExpression (Stream &error_stream,
|
||||
|
@ -314,9 +322,15 @@ public:
|
|||
/// @param[in/out] result_valobj_sp
|
||||
/// If execution is successful, the result valobj is placed here.
|
||||
///
|
||||
/// @param[in] single_thread_timeout_usec
|
||||
/// The amount of time (in usec) that we are willing to wait for this
|
||||
/// expression to complete, before assuming that we are blocked and giving up
|
||||
/// @param[in] try_all_threads
|
||||
/// If true, then we will try to run all threads if the function doesn't complete on
|
||||
/// one thread. See timeout_usec for the interaction of this variable and
|
||||
/// the timeout.
|
||||
///
|
||||
/// @param[in] timeout_usec
|
||||
/// Timeout value (0 for no timeout). If try_all_threads is true, then we
|
||||
/// will try on one thread for the lesser of .25 sec and half the total timeout.
|
||||
/// then switch to running all threads, otherwise this will be the total timeout.
|
||||
///
|
||||
/// @result
|
||||
/// A Process::ExecutionResults value. eExecutionCompleted for success.
|
||||
|
@ -330,7 +344,8 @@ public:
|
|||
const char *expr_cstr,
|
||||
const char *expr_prefix,
|
||||
lldb::ValueObjectSP &result_valobj_sp,
|
||||
uint32_t single_thread_timeout_usec = 500000);
|
||||
bool try_all_threads = true,
|
||||
uint32_t timeout_usec = 500000);
|
||||
|
||||
static ExecutionResults
|
||||
EvaluateWithError (ExecutionContext &exe_ctx,
|
||||
|
@ -342,7 +357,8 @@ public:
|
|||
const char *expr_prefix,
|
||||
lldb::ValueObjectSP &result_valobj_sp,
|
||||
Error &error,
|
||||
uint32_t single_thread_timeout_usec = 500000);
|
||||
bool try_all_threads = true,
|
||||
uint32_t timeout_usec = 500000);
|
||||
|
||||
static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression.
|
||||
private:
|
||||
|
|
|
@ -2363,9 +2363,9 @@ public:
|
|||
RunThreadPlan (ExecutionContext &exe_ctx,
|
||||
lldb::ThreadPlanSP &thread_plan_sp,
|
||||
bool stop_others,
|
||||
bool try_all_threads,
|
||||
bool run_others,
|
||||
bool discard_on_error,
|
||||
uint32_t single_thread_timeout_usec,
|
||||
uint32_t timeout_usec,
|
||||
Stream &errors);
|
||||
|
||||
static const char *
|
||||
|
|
|
@ -137,6 +137,121 @@ public:
|
|||
|
||||
typedef STD_SHARED_PTR(TargetProperties) TargetPropertiesSP;
|
||||
|
||||
class EvaluateExpressionOptions
|
||||
{
|
||||
public:
|
||||
static const uint32_t default_timeout = 500000;
|
||||
EvaluateExpressionOptions() :
|
||||
m_execution_policy(eExecutionPolicyOnlyWhenNeeded),
|
||||
m_coerce_to_id(false),
|
||||
m_unwind_on_error(true),
|
||||
m_keep_in_memory(false),
|
||||
m_run_others(true),
|
||||
m_use_dynamic(lldb::eNoDynamicValues),
|
||||
m_timeout_usec(default_timeout)
|
||||
{}
|
||||
|
||||
ExecutionPolicy
|
||||
GetExecutionPolicy () const
|
||||
{
|
||||
return m_execution_policy;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetExecutionPolicy (ExecutionPolicy policy = eExecutionPolicyAlways)
|
||||
{
|
||||
m_execution_policy = policy;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
DoesCoerceToId () const
|
||||
{
|
||||
return m_coerce_to_id;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetCoerceToId (bool coerce = true)
|
||||
{
|
||||
m_coerce_to_id = coerce;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
DoesUnwindOnError () const
|
||||
{
|
||||
return m_unwind_on_error;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetUnwindOnError (bool unwind = false)
|
||||
{
|
||||
m_unwind_on_error = unwind;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
DoesKeepInMemory () const
|
||||
{
|
||||
return m_keep_in_memory;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetKeepInMemory (bool keep = true)
|
||||
{
|
||||
m_keep_in_memory = keep;
|
||||
return *this;
|
||||
}
|
||||
|
||||
lldb::DynamicValueType
|
||||
GetUseDynamic () const
|
||||
{
|
||||
return m_use_dynamic;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetUseDynamic (lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget)
|
||||
{
|
||||
m_use_dynamic = dynamic;
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetTimeoutUsec () const
|
||||
{
|
||||
return m_timeout_usec;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetTimeoutUsec (uint32_t timeout = 0)
|
||||
{
|
||||
m_timeout_usec = timeout;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
GetRunOthers () const
|
||||
{
|
||||
return m_run_others;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetRunOthers (bool run_others = true)
|
||||
{
|
||||
m_run_others = run_others;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
ExecutionPolicy m_execution_policy;
|
||||
bool m_coerce_to_id;
|
||||
bool m_unwind_on_error;
|
||||
bool m_keep_in_memory;
|
||||
bool m_run_others;
|
||||
lldb::DynamicValueType m_use_dynamic;
|
||||
uint32_t m_timeout_usec;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Target
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -760,104 +875,6 @@ public:
|
|||
ClangASTImporter *
|
||||
GetClangASTImporter();
|
||||
|
||||
class EvaluateExpressionOptions
|
||||
{
|
||||
public:
|
||||
EvaluateExpressionOptions() :
|
||||
m_execution_policy(eExecutionPolicyOnlyWhenNeeded),
|
||||
m_coerce_to_id(false),
|
||||
m_unwind_on_error(true),
|
||||
m_keep_in_memory(false),
|
||||
m_use_dynamic(lldb::eNoDynamicValues),
|
||||
m_single_thread_timeout_usec(500000)
|
||||
{}
|
||||
|
||||
ExecutionPolicy
|
||||
GetExecutionPolicy () const
|
||||
{
|
||||
return m_execution_policy;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetExecutionPolicy (ExecutionPolicy policy = eExecutionPolicyAlways)
|
||||
{
|
||||
m_execution_policy = policy;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
DoesCoerceToId () const
|
||||
{
|
||||
return m_coerce_to_id;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetCoerceToId (bool coerce = true)
|
||||
{
|
||||
m_coerce_to_id = coerce;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
DoesUnwindOnError () const
|
||||
{
|
||||
return m_unwind_on_error;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetUnwindOnError (bool unwind = false)
|
||||
{
|
||||
m_unwind_on_error = unwind;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
DoesKeepInMemory () const
|
||||
{
|
||||
return m_keep_in_memory;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetKeepInMemory (bool keep = true)
|
||||
{
|
||||
m_keep_in_memory = keep;
|
||||
return *this;
|
||||
}
|
||||
|
||||
lldb::DynamicValueType
|
||||
GetUseDynamic () const
|
||||
{
|
||||
return m_use_dynamic;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetUseDynamic (lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget)
|
||||
{
|
||||
m_use_dynamic = dynamic;
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetSingleThreadTimeoutUsec () const
|
||||
{
|
||||
return m_single_thread_timeout_usec;
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions&
|
||||
SetSingleThreadTimeoutUsec (uint32_t timeout = 0)
|
||||
{
|
||||
m_single_thread_timeout_usec = timeout;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
ExecutionPolicy m_execution_policy;
|
||||
bool m_coerce_to_id;
|
||||
bool m_unwind_on_error;
|
||||
bool m_keep_in_memory;
|
||||
lldb::DynamicValueType m_use_dynamic;
|
||||
uint32_t m_single_thread_timeout_usec;
|
||||
};
|
||||
|
||||
// Since expressions results can persist beyond the lifetime of a process,
|
||||
// and the const expression results are available after a process is gone,
|
||||
|
|
|
@ -98,6 +98,7 @@ class DynamicLibrary;
|
|||
class DynamicLoader;
|
||||
class EmulateInstruction;
|
||||
class Error;
|
||||
class EvaluateExpressionOptions;
|
||||
class Event;
|
||||
class EventData;
|
||||
class ExecutionContext;
|
||||
|
|
|
@ -505,6 +505,8 @@
|
|||
4CCA645613B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644813B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp */; };
|
||||
4CCA645813B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644A13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp */; };
|
||||
4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */; };
|
||||
4CE4F673162C971A00F75CB3 /* SBExpressionOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CE4F672162C971A00F75CB3 /* SBExpressionOptions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4CE4F675162C973F00F75CB3 /* SBExpressionOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F674162C973F00F75CB3 /* SBExpressionOptions.cpp */; };
|
||||
4CF3D80C15AF4DC800845BF3 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDB919B414F6F10D008FF64B /* Security.framework */; };
|
||||
4CF52AF51428291E0051E832 /* SBFileSpecList.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF52AF41428291E0051E832 /* SBFileSpecList.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4CF52AF8142829390051E832 /* SBFileSpecList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF52AF7142829390051E832 /* SBFileSpecList.cpp */; };
|
||||
|
@ -1492,6 +1494,9 @@
|
|||
4CCA644B13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleThreadPlanStepThroughObjCTrampoline.h; sourceTree = "<group>"; };
|
||||
4CD0BD0C134BFAB600CB44D4 /* ValueObjectDynamicValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectDynamicValue.h; path = include/lldb/Core/ValueObjectDynamicValue.h; sourceTree = "<group>"; };
|
||||
4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectDynamicValue.cpp; path = source/Core/ValueObjectDynamicValue.cpp; sourceTree = "<group>"; };
|
||||
4CE4F672162C971A00F75CB3 /* SBExpressionOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBExpressionOptions.h; path = include/lldb/API/SBExpressionOptions.h; sourceTree = "<group>"; };
|
||||
4CE4F674162C973F00F75CB3 /* SBExpressionOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBExpressionOptions.cpp; path = source/API/SBExpressionOptions.cpp; sourceTree = "<group>"; };
|
||||
4CE4F676162CE1E100F75CB3 /* SBExpressionOptions.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBExpressionOptions.i; sourceTree = "<group>"; };
|
||||
4CEDAED311754F5E00E875A6 /* ThreadPlanStepUntil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepUntil.h; path = include/lldb/Target/ThreadPlanStepUntil.h; sourceTree = "<group>"; };
|
||||
4CF52AF41428291E0051E832 /* SBFileSpecList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBFileSpecList.h; path = include/lldb/API/SBFileSpecList.h; sourceTree = "<group>"; };
|
||||
4CF52AF7142829390051E832 /* SBFileSpecList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBFileSpecList.cpp; path = source/API/SBFileSpecList.cpp; sourceTree = "<group>"; };
|
||||
|
@ -2028,6 +2033,7 @@
|
|||
2611FEFC142D83060017FEA3 /* SBFileSpec.i */,
|
||||
2611FEFD142D83060017FEA3 /* SBFileSpecList.i */,
|
||||
2611FEFE142D83060017FEA3 /* SBFrame.i */,
|
||||
4CE4F676162CE1E100F75CB3 /* SBExpressionOptions.i */,
|
||||
2611FEFF142D83060017FEA3 /* SBFunction.i */,
|
||||
2611FF00142D83060017FEA3 /* SBHostOS.i */,
|
||||
2611FF01142D83060017FEA3 /* SBInputReader.i */,
|
||||
|
@ -2118,6 +2124,8 @@
|
|||
2682F284115EF3A700CCFF99 /* SBError.cpp */,
|
||||
9A9830FE1125FC5800A56CB0 /* SBEvent.h */,
|
||||
9A9830FD1125FC5800A56CB0 /* SBEvent.cpp */,
|
||||
4CE4F672162C971A00F75CB3 /* SBExpressionOptions.h */,
|
||||
4CE4F674162C973F00F75CB3 /* SBExpressionOptions.cpp */,
|
||||
26022531115F27FA00A601A2 /* SBFileSpec.h */,
|
||||
26022532115F281400A601A2 /* SBFileSpec.cpp */,
|
||||
4CF52AF41428291E0051E832 /* SBFileSpecList.h */,
|
||||
|
@ -3381,6 +3389,7 @@
|
|||
B2A58722143119810092BFBA /* SBWatchpoint.h in Headers */,
|
||||
26D265A2136B40EE002EEE45 /* SharingPtr.h in Headers */,
|
||||
26D265BC136B4269002EEE45 /* lldb-public.h in Headers */,
|
||||
4CE4F673162C971A00F75CB3 /* SBExpressionOptions.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -3773,6 +3782,7 @@
|
|||
9475C18814E5E9FA001BFC6D /* SBTypeCategory.cpp in Sources */,
|
||||
9475C18E14E5F834001BFC6D /* SBTypeNameSpecifier.cpp in Sources */,
|
||||
9452573A16262D0200325455 /* SBDeclaration.cpp in Sources */,
|
||||
4CE4F675162C973F00F75CB3 /* SBExpressionOptions.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -76,6 +76,7 @@ HEADER_FILES="${SRC_ROOT}/include/lldb/lldb.h"\
|
|||
" ${SRC_ROOT}/include/lldb/API/SBDebugger.h"\
|
||||
" ${SRC_ROOT}/include/lldb/API/SBError.h"\
|
||||
" ${SRC_ROOT}/include/lldb/API/SBEvent.h"\
|
||||
" ${SRC_ROOT}/include/lldb/API/SBExpressionOptions.h"\
|
||||
" ${SRC_ROOT}/include/lldb/API/SBFileSpec.h"\
|
||||
" ${SRC_ROOT}/include/lldb/API/SBFrame.h"\
|
||||
" ${SRC_ROOT}/include/lldb/API/SBFunction.h"\
|
||||
|
@ -120,6 +121,7 @@ INTERFACE_FILES="${SRC_ROOT}/scripts/Python/interface/SBAddress.i"\
|
|||
" ${SRC_ROOT}/scripts/Python/interface/SBDeclaration.i"\
|
||||
" ${SRC_ROOT}/scripts/Python/interface/SBError.i"\
|
||||
" ${SRC_ROOT}/scripts/Python/interface/SBEvent.i"\
|
||||
" ${SRC_ROOT}/scripts/Python/interface/SBExpressionOptions.i"\
|
||||
" ${SRC_ROOT}/scripts/Python/interface/SBFileSpec.i"\
|
||||
" ${SRC_ROOT}/scripts/Python/interface/SBFrame.i"\
|
||||
" ${SRC_ROOT}/scripts/Python/interface/SBFunction.i"\
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
//===-- SWIG interface for SBExpressionOptions -----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace lldb {
|
||||
|
||||
%feature("docstring",
|
||||
"A container for options to use when evaluating expressions."
|
||||
) SBExpressionOptions;
|
||||
|
||||
class SBExpressionOptions
|
||||
{
|
||||
friend class SBFrame;
|
||||
friend class SBValue;
|
||||
|
||||
public:
|
||||
SBExpressionOptions();
|
||||
|
||||
SBExpressionOptions (const lldb::SBExpressionOptions &rhs);
|
||||
|
||||
SBExpressionOptions (bool coerce_to_id,
|
||||
bool unwind_on_error,
|
||||
bool keep_in_memory,
|
||||
bool run_others,
|
||||
DynamicValueType use_dynamic,
|
||||
uint32_t timeout_usec);
|
||||
|
||||
~SBExpressionOptions();
|
||||
|
||||
bool
|
||||
DoesCoerceToId () const;
|
||||
|
||||
%feature("docstring",
|
||||
"Sets whether to coerce the expression result to ObjC id type after evaluation."
|
||||
) SetCoerceToId;
|
||||
void
|
||||
SetCoerceToId (bool coerce = true);
|
||||
|
||||
bool
|
||||
DoesUnwindOnError () const;
|
||||
|
||||
%feature("docstring",
|
||||
"Sets whether to unwind the expression stack on error."
|
||||
) SetUnwindOnError;
|
||||
void
|
||||
SetUnwindOnError (bool unwind = false);
|
||||
|
||||
bool
|
||||
DoesKeepInMemory () const;
|
||||
|
||||
%feature("docstring",
|
||||
"Sets whether to keep the expression result in the target program's memory - forced to true when creating SBValues."
|
||||
) SetKeepInMemory;
|
||||
void
|
||||
SetKeepInMemory (bool keep = true);
|
||||
|
||||
lldb::DynamicValueType
|
||||
GetUseDynamic () const;
|
||||
|
||||
%feature("docstring",
|
||||
"Sets whether to cast the expression result to its dynamic type."
|
||||
) SetUseDynamic;
|
||||
void
|
||||
SetUseDynamic (lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget);
|
||||
|
||||
uint32_t
|
||||
GetTimeoutUsec () const;
|
||||
|
||||
%feature("docstring",
|
||||
"Sets the duration we will wait before cancelling expression evaluation. 0 means wait forever."
|
||||
) SetTimeoutUsec;
|
||||
void
|
||||
SetTimeoutUsec (uint32_t timeout = 0);
|
||||
|
||||
bool
|
||||
GetRunOthers () const;
|
||||
|
||||
%feature("docstring",
|
||||
"Sets whether to run all threads if the expression does not complete on one thread."
|
||||
) SetRunOthers;
|
||||
void
|
||||
SetRunOthers (bool run_others = true);
|
||||
|
||||
protected:
|
||||
|
||||
SBExpressionOptions (lldb_private::EvaluateExpressionOptions &expression_options);
|
||||
|
||||
lldb_private::EvaluateExpressionOptions *
|
||||
get () const;
|
||||
|
||||
lldb_private::EvaluateExpressionOptions &
|
||||
ref () const;
|
||||
|
||||
private:
|
||||
// This auto_pointer is made in the constructor and is always valid.
|
||||
mutable std::auto_ptr<lldb_private::EvaluateExpressionOptions> m_opaque_ap;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
|
@ -139,6 +139,9 @@ public:
|
|||
|
||||
lldb::SBValue
|
||||
EvaluateExpression (const char *expr, lldb::DynamicValueType use_dynamic, bool unwind_on_error);
|
||||
|
||||
lldb::SBValue
|
||||
EvaluateExpression (const char *expr, SBExpressionOptions &options);
|
||||
|
||||
%feature("docstring", "
|
||||
/// Gets the lexical block that defines the stack frame. Another way to think
|
||||
|
|
|
@ -222,6 +222,9 @@ public:
|
|||
|
||||
lldb::SBValue
|
||||
CreateValueFromExpression (const char *name, const char* expression);
|
||||
|
||||
lldb::SBValue
|
||||
CreateValueFromExpression (const char *name, const char* expression, SBExpressionOptions &options);
|
||||
|
||||
lldb::SBValue
|
||||
CreateValueFromAddress(const char* name, lldb::addr_t address, lldb::SBType type);
|
||||
|
|
|
@ -66,6 +66,7 @@ import os
|
|||
#include "lldb/API/SBDeclaration.h"
|
||||
#include "lldb/API/SBError.h"
|
||||
#include "lldb/API/SBEvent.h"
|
||||
#include "lldb/API/SBExpressionOptions.h"
|
||||
#include "lldb/API/SBFileSpec.h"
|
||||
#include "lldb/API/SBFileSpecList.h"
|
||||
#include "lldb/API/SBFrame.h"
|
||||
|
@ -125,6 +126,7 @@ import os
|
|||
%include "./Python/interface/SBDeclaration.i"
|
||||
%include "./Python/interface/SBError.i"
|
||||
%include "./Python/interface/SBEvent.i"
|
||||
%include "./Python/interface/SBExpressionOptions.i"
|
||||
%include "./Python/interface/SBFileSpec.i"
|
||||
%include "./Python/interface/SBFileSpecList.i"
|
||||
%include "./Python/interface/SBFrame.i"
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
//===-- SBExpressionOptions.cpp ---------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/API/SBExpressionOptions.h"
|
||||
#include "lldb/API/SBStream.h"
|
||||
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
|
||||
SBExpressionOptions::SBExpressionOptions ()
|
||||
{
|
||||
m_opaque_ap.reset(new EvaluateExpressionOptions());
|
||||
}
|
||||
|
||||
SBExpressionOptions::SBExpressionOptions (bool coerce_to_id,
|
||||
bool unwind_on_error,
|
||||
bool keep_in_memory,
|
||||
bool run_others,
|
||||
DynamicValueType use_dynamic,
|
||||
uint32_t timeout_usec)
|
||||
{
|
||||
m_opaque_ap.reset(new EvaluateExpressionOptions());
|
||||
m_opaque_ap->SetCoerceToId(coerce_to_id);
|
||||
m_opaque_ap->SetUnwindOnError(unwind_on_error);
|
||||
m_opaque_ap->SetKeepInMemory(keep_in_memory);
|
||||
m_opaque_ap->SetRunOthers(run_others);
|
||||
m_opaque_ap->SetUseDynamic (use_dynamic);
|
||||
m_opaque_ap->SetTimeoutUsec (timeout_usec);
|
||||
}
|
||||
|
||||
SBExpressionOptions::SBExpressionOptions (const SBExpressionOptions &rhs)
|
||||
{
|
||||
m_opaque_ap.reset(new EvaluateExpressionOptions());
|
||||
*(m_opaque_ap.get()) = rhs.ref();
|
||||
}
|
||||
|
||||
const SBExpressionOptions &
|
||||
SBExpressionOptions::operator = (const SBExpressionOptions &rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
this->ref() = rhs.ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SBExpressionOptions::~SBExpressionOptions()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
SBExpressionOptions::DoesCoerceToId () const
|
||||
{
|
||||
return m_opaque_ap->DoesCoerceToId ();
|
||||
}
|
||||
|
||||
void
|
||||
SBExpressionOptions::SetCoerceToId (bool coerce)
|
||||
{
|
||||
m_opaque_ap->SetCoerceToId (coerce);
|
||||
}
|
||||
|
||||
bool
|
||||
SBExpressionOptions::DoesUnwindOnError () const
|
||||
{
|
||||
return m_opaque_ap->DoesUnwindOnError ();
|
||||
}
|
||||
|
||||
void
|
||||
SBExpressionOptions::SetUnwindOnError (bool unwind)
|
||||
{
|
||||
m_opaque_ap->SetUnwindOnError (unwind);
|
||||
}
|
||||
|
||||
bool
|
||||
SBExpressionOptions::DoesKeepInMemory () const
|
||||
{
|
||||
return m_opaque_ap->DoesKeepInMemory ();
|
||||
}
|
||||
|
||||
void
|
||||
SBExpressionOptions::SetKeepInMemory (bool keep)
|
||||
{
|
||||
m_opaque_ap->SetKeepInMemory (keep);
|
||||
}
|
||||
|
||||
lldb::DynamicValueType
|
||||
SBExpressionOptions::GetUseDynamic () const
|
||||
{
|
||||
return m_opaque_ap->GetUseDynamic ();
|
||||
}
|
||||
|
||||
void
|
||||
SBExpressionOptions::SetUseDynamic (lldb::DynamicValueType dynamic)
|
||||
{
|
||||
m_opaque_ap->SetUseDynamic (dynamic);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SBExpressionOptions::GetTimeoutUsec () const
|
||||
{
|
||||
return m_opaque_ap->GetTimeoutUsec ();
|
||||
}
|
||||
|
||||
void
|
||||
SBExpressionOptions::SetTimeoutUsec (uint32_t timeout)
|
||||
{
|
||||
m_opaque_ap->SetTimeoutUsec (timeout);
|
||||
}
|
||||
|
||||
bool
|
||||
SBExpressionOptions::GetRunOthers () const
|
||||
{
|
||||
return m_opaque_ap->GetRunOthers ();
|
||||
}
|
||||
|
||||
void
|
||||
SBExpressionOptions::SetRunOthers (bool run_others)
|
||||
{
|
||||
m_opaque_ap->SetRunOthers (run_others);
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions *
|
||||
SBExpressionOptions::get() const
|
||||
{
|
||||
return m_opaque_ap.get();
|
||||
}
|
||||
|
||||
EvaluateExpressionOptions &
|
||||
SBExpressionOptions::ref () const
|
||||
{
|
||||
return *(m_opaque_ap.get());
|
||||
}
|
|
@ -40,6 +40,7 @@
|
|||
#include "lldb/API/SBDebugger.h"
|
||||
#include "lldb/API/SBValue.h"
|
||||
#include "lldb/API/SBAddress.h"
|
||||
#include "lldb/API/SBExpressionOptions.h"
|
||||
#include "lldb/API/SBStream.h"
|
||||
#include "lldb/API/SBSymbolContext.h"
|
||||
#include "lldb/API/SBThread.h"
|
||||
|
@ -1040,8 +1041,11 @@ SBFrame::EvaluateExpression (const char *expr)
|
|||
Target *target = exe_ctx.GetTargetPtr();
|
||||
if (frame && target)
|
||||
{
|
||||
lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue();
|
||||
result = EvaluateExpression (expr, use_dynamic);
|
||||
SBExpressionOptions options;
|
||||
lldb::DynamicValueType fetch_dynamic_value = frame->CalculateTarget()->GetPreferDynamicValue();
|
||||
options.SetUseDynamic (fetch_dynamic_value);
|
||||
options.SetUnwindOnError (true);
|
||||
return EvaluateExpression (expr, options);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1049,11 +1053,23 @@ SBFrame::EvaluateExpression (const char *expr)
|
|||
SBValue
|
||||
SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dynamic_value)
|
||||
{
|
||||
return EvaluateExpression (expr, fetch_dynamic_value, true);
|
||||
SBExpressionOptions options;
|
||||
options.SetUseDynamic (fetch_dynamic_value);
|
||||
options.SetUnwindOnError (true);
|
||||
return EvaluateExpression (expr, options);
|
||||
}
|
||||
|
||||
SBValue
|
||||
SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dynamic_value, bool unwind_on_error)
|
||||
{
|
||||
SBExpressionOptions options;
|
||||
options.SetUseDynamic (fetch_dynamic_value);
|
||||
options.SetUnwindOnError (unwind_on_error);
|
||||
return EvaluateExpression (expr, options);
|
||||
}
|
||||
|
||||
lldb::SBValue
|
||||
SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &options)
|
||||
{
|
||||
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
||||
|
||||
|
@ -1080,16 +1096,12 @@ SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dyna
|
|||
StreamString frame_description;
|
||||
frame->DumpUsingSettingsFormat (&frame_description);
|
||||
Host::SetCrashDescriptionWithFormat ("SBFrame::EvaluateExpression (expr = \"%s\", fetch_dynamic_value = %u) %s",
|
||||
expr, fetch_dynamic_value, frame_description.GetString().c_str());
|
||||
expr, options.GetUseDynamic(), frame_description.GetString().c_str());
|
||||
#endif
|
||||
Target::EvaluateExpressionOptions options;
|
||||
options.SetUnwindOnError(unwind_on_error)
|
||||
.SetUseDynamic(fetch_dynamic_value);
|
||||
|
||||
exe_results = target->EvaluateExpression (expr,
|
||||
frame,
|
||||
expr_value_sp,
|
||||
options);
|
||||
options.ref());
|
||||
expr_result.SetSP(expr_value_sp);
|
||||
#ifdef LLDB_CONFIGURATION_DEBUG
|
||||
Host::SetCrashDescription (NULL);
|
||||
|
|
|
@ -40,11 +40,12 @@
|
|||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Target/Thread.h"
|
||||
|
||||
#include "lldb/API/SBDebugger.h"
|
||||
#include "lldb/API/SBExpressionOptions.h"
|
||||
#include "lldb/API/SBFrame.h"
|
||||
#include "lldb/API/SBProcess.h"
|
||||
#include "lldb/API/SBTarget.h"
|
||||
#include "lldb/API/SBThread.h"
|
||||
#include "lldb/API/SBFrame.h"
|
||||
#include "lldb/API/SBDebugger.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
@ -694,9 +695,12 @@ SBValue::CreateChildAtOffset (const char *name, uint32_t offset, SBType type)
|
|||
if (log)
|
||||
{
|
||||
if (new_value_sp)
|
||||
log->Printf ("SBValue(%p)::CreateChildAtOffset => \"%s\"", value_sp.get(), new_value_sp->GetName().AsCString());
|
||||
log->Printf ("SBValue(%p)::CreateChildAtOffset => \"%s\"",
|
||||
value_sp.get(),
|
||||
new_value_sp->GetName().AsCString());
|
||||
else
|
||||
log->Printf ("SBValue(%p)::CreateChildAtOffset => NULL", value_sp.get());
|
||||
log->Printf ("SBValue(%p)::CreateChildAtOffset => NULL",
|
||||
value_sp.get());
|
||||
}
|
||||
return sb_value;
|
||||
}
|
||||
|
@ -714,6 +718,14 @@ SBValue::Cast (SBType type)
|
|||
|
||||
lldb::SBValue
|
||||
SBValue::CreateValueFromExpression (const char *name, const char* expression)
|
||||
{
|
||||
SBExpressionOptions options;
|
||||
options.SetKeepInMemory(true);
|
||||
return CreateValueFromExpression (name, expression, options);
|
||||
}
|
||||
|
||||
lldb::SBValue
|
||||
SBValue::CreateValueFromExpression (const char *name, const char *expression, SBExpressionOptions &options)
|
||||
{
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
||||
lldb::SBValue sb_value;
|
||||
|
@ -734,12 +746,11 @@ SBValue::CreateValueFromExpression (const char *name, const char* expression)
|
|||
Target* target = exe_ctx.GetTargetPtr();
|
||||
if (target)
|
||||
{
|
||||
Target::EvaluateExpressionOptions options;
|
||||
options.SetKeepInMemory(true);
|
||||
target->EvaluateExpression (expression,
|
||||
exe_ctx.GetFramePtr(),
|
||||
new_value_sp,
|
||||
options);
|
||||
options.ref());
|
||||
if (new_value_sp)
|
||||
{
|
||||
new_value_sp->SetName(ConstString(name));
|
||||
|
@ -1617,7 +1628,9 @@ SBValue::GetAddress()
|
|||
}
|
||||
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
|
||||
if (log)
|
||||
log->Printf ("SBValue(%p)::GetAddress () => (%s,%llu)", value_sp.get(), (addr.GetSection() ? addr.GetSection()->GetName().GetCString() : "NULL"), addr.GetOffset());
|
||||
log->Printf ("SBValue(%p)::GetAddress () => (%s,%llu)", value_sp.get(),
|
||||
(addr.GetSection() ? addr.GetSection()->GetName().GetCString() : "NULL"),
|
||||
addr.GetOffset());
|
||||
return SBAddress(new Address(addr));
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,9 @@ CommandObjectExpression::CommandOptions::~CommandOptions ()
|
|||
OptionDefinition
|
||||
CommandObjectExpression::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', required_argument, NULL, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."},
|
||||
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "dynamic-value", 'd', required_argument, NULL, 0, eArgTypeBoolean, "Upcast the value resulting from the expression to its dynamic type if available."},
|
||||
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value for running the expression."},
|
||||
{ LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', required_argument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, breakpoint hit or signal."},
|
||||
{ LLDB_OPT_SET_2 , false, "object-description", 'o', no_argument, NULL, 0, eArgTypeNone, "Print the object description of the value resulting from the expression."},
|
||||
};
|
||||
|
@ -80,8 +82,16 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int
|
|||
//}
|
||||
//break;
|
||||
|
||||
case 'o':
|
||||
print_object = true;
|
||||
case 'a':
|
||||
{
|
||||
bool success;
|
||||
bool result;
|
||||
result = Args::StringToBoolean(option_arg, true, &success);
|
||||
if (!success)
|
||||
error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg);
|
||||
else
|
||||
try_all_threads = result;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
|
@ -101,6 +111,22 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int
|
|||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
print_object = true;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
{
|
||||
bool success;
|
||||
uint32_t result;
|
||||
result = Args::StringToUInt32(option_arg, 0, 0, &success);
|
||||
if (success)
|
||||
timeout = result;
|
||||
else
|
||||
error.SetErrorStringWithFormat ("invalid timeout setting \"%s\"", option_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
{
|
||||
bool success;
|
||||
|
@ -125,6 +151,8 @@ CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpret
|
|||
unwind_on_error = true;
|
||||
show_types = true;
|
||||
show_summary = true;
|
||||
try_all_threads = true;
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
const OptionDefinition*
|
||||
|
@ -146,7 +174,13 @@ CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interprete
|
|||
m_expr_lines ()
|
||||
{
|
||||
SetHelpLong(
|
||||
"Examples: \n\
|
||||
"Timeouts:\n\
|
||||
If the expression can be evaluated statically (without runnning code) then it will be.\n\
|
||||
Otherwise, by default the expression will run on the current thread with a short timeout:\n\
|
||||
currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted\n\
|
||||
and resumed with all threads running. You can use the -a option to disable retrying on all\n\
|
||||
threads. You can use the -t option to set a shorter timeout.\n\
|
||||
Examples: \n\
|
||||
\n\
|
||||
expr my_struct->a = my_array[3] \n\
|
||||
expr -f bin -- (index * 8) + 5 \n\
|
||||
|
@ -298,12 +332,13 @@ CommandObjectExpression::EvaluateExpression
|
|||
break;
|
||||
}
|
||||
|
||||
Target::EvaluateExpressionOptions options;
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(m_command_options.print_object)
|
||||
.SetUnwindOnError(m_command_options.unwind_on_error)
|
||||
.SetKeepInMemory(keep_in_memory)
|
||||
.SetUseDynamic(use_dynamic)
|
||||
.SetSingleThreadTimeoutUsec(0);
|
||||
.SetRunOthers(m_command_options.try_all_threads)
|
||||
.SetTimeoutUsec(m_command_options.timeout);
|
||||
|
||||
exe_results = target->EvaluateExpression (expr,
|
||||
m_interpreter.GetExecutionContext().GetFramePtr(),
|
||||
|
|
|
@ -55,6 +55,8 @@ public:
|
|||
bool unwind_on_error;
|
||||
bool show_types;
|
||||
bool show_summary;
|
||||
uint32_t timeout;
|
||||
bool try_all_threads;
|
||||
};
|
||||
|
||||
CommandObjectExpression (CommandInterpreter &interpreter);
|
||||
|
|
|
@ -1314,7 +1314,7 @@ protected:
|
|||
if (command && command[0] != '\0')
|
||||
{
|
||||
Target *target = exe_ctx.GetTargetPtr();
|
||||
Target::EvaluateExpressionOptions options;
|
||||
EvaluateExpressionOptions options;
|
||||
|
||||
options.SetUnwindOnError(true);
|
||||
options.SetUseDynamic(eNoDynamicValues);
|
||||
|
|
|
@ -1234,11 +1234,12 @@ protected:
|
|||
}
|
||||
|
||||
// Use expression evaluation to arrive at the address to watch.
|
||||
Target::EvaluateExpressionOptions options;
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(false)
|
||||
.SetSingleThreadTimeoutUsec(0);
|
||||
.SetRunOthers(true)
|
||||
.SetTimeoutUsec(0);
|
||||
|
||||
ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
|
||||
frame,
|
||||
|
|
|
@ -47,7 +47,7 @@ lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
|
|||
if (!target || !stack_frame)
|
||||
return false;
|
||||
|
||||
Target::EvaluateExpressionOptions options;
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
|
@ -85,7 +85,7 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
|
|||
if (!target || !stack_frame)
|
||||
return valobj_sp;
|
||||
|
||||
Target::EvaluateExpressionOptions options;
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
|
@ -122,7 +122,7 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
|
|||
if (!target || !stack_frame)
|
||||
return valobj_sp;
|
||||
|
||||
Target::EvaluateExpressionOptions options;
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
|
@ -459,7 +459,7 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream&
|
|||
if (!target || !stack_frame)
|
||||
return false;
|
||||
|
||||
Target::EvaluateExpressionOptions options;
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(true)
|
||||
|
@ -1055,7 +1055,7 @@ lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIn
|
|||
object_fetcher_expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = %s; _lldb_valgen_item.value = %s; _lldb_valgen_item;",key_fetcher_expr.GetData(),value_fetcher_expr.GetData());
|
||||
lldb::ValueObjectSP child_sp;
|
||||
m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp,
|
||||
Target::EvaluateExpressionOptions().SetKeepInMemory(true));
|
||||
EvaluateExpressionOptions().SetKeepInMemory(true));
|
||||
if (child_sp)
|
||||
child_sp->SetName(ConstString(idx_name.GetData()));
|
||||
return child_sp;
|
||||
|
|
|
@ -485,13 +485,13 @@ ExecutionResults
|
|||
ClangFunction::ExecuteFunction(
|
||||
ExecutionContext &exe_ctx,
|
||||
Stream &errors,
|
||||
uint32_t single_thread_timeout_usec,
|
||||
uint32_t timeout_usec,
|
||||
bool try_all_threads,
|
||||
Value &results)
|
||||
{
|
||||
const bool stop_others = true;
|
||||
const bool discard_on_error = true;
|
||||
return ExecuteFunction (exe_ctx, NULL, errors, stop_others, single_thread_timeout_usec,
|
||||
return ExecuteFunction (exe_ctx, NULL, errors, stop_others, timeout_usec,
|
||||
try_all_threads, discard_on_error, results);
|
||||
}
|
||||
|
||||
|
@ -504,7 +504,7 @@ ClangFunction::ExecuteFunction (
|
|||
bool stop_others,
|
||||
bool try_all_threads,
|
||||
bool discard_on_error,
|
||||
uint32_t single_thread_timeout_usec,
|
||||
uint32_t timeout_usec,
|
||||
Stream &errors,
|
||||
lldb::addr_t *this_arg)
|
||||
{
|
||||
|
@ -529,7 +529,7 @@ ClangFunction::ExecuteFunction (
|
|||
stop_others,
|
||||
try_all_threads,
|
||||
discard_on_error,
|
||||
single_thread_timeout_usec,
|
||||
timeout_usec,
|
||||
errors);
|
||||
|
||||
if (exe_ctx.GetProcessPtr())
|
||||
|
@ -544,7 +544,7 @@ ClangFunction::ExecuteFunction(
|
|||
lldb::addr_t *args_addr_ptr,
|
||||
Stream &errors,
|
||||
bool stop_others,
|
||||
uint32_t single_thread_timeout_usec,
|
||||
uint32_t timeout_usec,
|
||||
bool try_all_threads,
|
||||
bool discard_on_error,
|
||||
Value &results)
|
||||
|
@ -574,7 +574,7 @@ ClangFunction::ExecuteFunction(
|
|||
stop_others,
|
||||
try_all_threads,
|
||||
discard_on_error,
|
||||
single_thread_timeout_usec,
|
||||
timeout_usec,
|
||||
errors);
|
||||
|
||||
if (args_addr_ptr != NULL)
|
||||
|
|
|
@ -544,7 +544,8 @@ ClangUserExpression::Execute (Stream &error_stream,
|
|||
bool discard_on_error,
|
||||
ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
|
||||
lldb::ClangExpressionVariableSP &result,
|
||||
uint32_t single_thread_timeout_usec)
|
||||
bool run_others,
|
||||
uint32_t timeout_usec)
|
||||
{
|
||||
// The expression log is quite verbose, and if you're just tracking the execution of the
|
||||
// expression, it's quite convenient to have these logs come out with the STEP log as well.
|
||||
|
@ -594,7 +595,7 @@ ClangUserExpression::Execute (Stream &error_stream,
|
|||
stop_others,
|
||||
try_all_threads,
|
||||
discard_on_error,
|
||||
single_thread_timeout_usec,
|
||||
timeout_usec,
|
||||
error_stream);
|
||||
|
||||
if (exe_ctx.GetProcessPtr())
|
||||
|
@ -655,10 +656,21 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
|
|||
const char *expr_cstr,
|
||||
const char *expr_prefix,
|
||||
lldb::ValueObjectSP &result_valobj_sp,
|
||||
uint32_t single_thread_timeout_usec)
|
||||
bool run_others,
|
||||
uint32_t timeout_usec)
|
||||
{
|
||||
Error error;
|
||||
return EvaluateWithError (exe_ctx, execution_policy, language, desired_type, discard_on_error, expr_cstr, expr_prefix, result_valobj_sp, error, single_thread_timeout_usec);
|
||||
return EvaluateWithError (exe_ctx,
|
||||
execution_policy,
|
||||
language,
|
||||
desired_type,
|
||||
discard_on_error,
|
||||
expr_cstr,
|
||||
expr_prefix,
|
||||
result_valobj_sp,
|
||||
error,
|
||||
run_others,
|
||||
timeout_usec);
|
||||
}
|
||||
|
||||
ExecutionResults
|
||||
|
@ -671,7 +683,8 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
|
|||
const char *expr_prefix,
|
||||
lldb::ValueObjectSP &result_valobj_sp,
|
||||
Error &error,
|
||||
uint32_t single_thread_timeout_usec)
|
||||
bool run_others,
|
||||
uint32_t timeout_usec)
|
||||
{
|
||||
lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
|
||||
|
||||
|
@ -747,7 +760,8 @@ ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
|
|||
discard_on_error,
|
||||
user_expression_sp,
|
||||
expr_result,
|
||||
single_thread_timeout_usec);
|
||||
run_others,
|
||||
timeout_usec);
|
||||
|
||||
if (execution_results != eExecutionCompleted)
|
||||
{
|
||||
|
|
|
@ -1308,11 +1308,12 @@ CommandInterpreter::PreprocessCommand (std::string &command)
|
|||
{
|
||||
ValueObjectSP expr_result_valobj_sp;
|
||||
|
||||
Target::EvaluateExpressionOptions options;
|
||||
EvaluateExpressionOptions options;
|
||||
options.SetCoerceToId(false)
|
||||
.SetUnwindOnError(true)
|
||||
.SetKeepInMemory(false)
|
||||
.SetSingleThreadTimeoutUsec(0);
|
||||
.SetRunOthers(true)
|
||||
.SetTimeoutUsec(0);
|
||||
|
||||
ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
|
||||
exe_ctx.GetFramePtr(),
|
||||
|
|
|
@ -50,7 +50,7 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
|
|||
const bool stop_other_threads = true;
|
||||
const bool discard_on_error = true;
|
||||
const bool try_all_threads = true;
|
||||
const uint32_t single_thread_timeout_usec = 500000;
|
||||
const uint32_t timeout_usec = 500000;
|
||||
|
||||
addr_t prot_arg, flags_arg = 0;
|
||||
if (prot == eMmapProtNone)
|
||||
|
@ -105,7 +105,7 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
|
|||
stop_other_threads,
|
||||
try_all_threads,
|
||||
discard_on_error,
|
||||
single_thread_timeout_usec,
|
||||
timeout_usec,
|
||||
error_strm);
|
||||
if (result == eExecutionCompleted)
|
||||
{
|
||||
|
@ -154,7 +154,7 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
|
|||
const bool stop_other_threads = true;
|
||||
const bool discard_on_error = true;
|
||||
const bool try_all_threads = true;
|
||||
const uint32_t single_thread_timeout_usec = 500000;
|
||||
const uint32_t timeout_usec = 500000;
|
||||
|
||||
AddressRange munmap_range;
|
||||
if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
|
||||
|
@ -183,7 +183,7 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
|
|||
stop_other_threads,
|
||||
try_all_threads,
|
||||
discard_on_error,
|
||||
single_thread_timeout_usec,
|
||||
timeout_usec,
|
||||
error_strm);
|
||||
if (result == eExecutionCompleted)
|
||||
{
|
||||
|
|
|
@ -4133,9 +4133,9 @@ ExecutionResults
|
|||
Process::RunThreadPlan (ExecutionContext &exe_ctx,
|
||||
lldb::ThreadPlanSP &thread_plan_sp,
|
||||
bool stop_others,
|
||||
bool try_all_threads,
|
||||
bool run_others,
|
||||
bool discard_on_error,
|
||||
uint32_t single_thread_timeout_usec,
|
||||
uint32_t timeout_usec,
|
||||
Stream &errors)
|
||||
{
|
||||
ExecutionResults return_value = eExecutionSetupError;
|
||||
|
@ -4260,6 +4260,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
|
|||
|
||||
bool first_timeout = true;
|
||||
bool do_resume = true;
|
||||
const uint64_t default_one_thread_timeout_usec = 250000;
|
||||
uint64_t computed_timeout = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
@ -4298,9 +4300,12 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
|
|||
if (stop_state != eStateRunning)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("Process::RunThreadPlan(): didn't get running event after initial resume, got %s instead.", StateAsCString(stop_state));
|
||||
log->Printf("Process::RunThreadPlan(): didn't get running event after "
|
||||
"initial resume, got %s instead.",
|
||||
StateAsCString(stop_state));
|
||||
|
||||
errors.Printf("Didn't get running event after initial resume, got %s instead.", StateAsCString(stop_state));
|
||||
errors.Printf("Didn't get running event after initial resume, got %s instead.",
|
||||
StateAsCString(stop_state));
|
||||
return_value = eExecutionSetupError;
|
||||
break;
|
||||
}
|
||||
|
@ -4313,28 +4318,45 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
|
|||
// We set the timeout AFTER the resume, since the resume takes some time and we
|
||||
// don't want to charge that to the timeout.
|
||||
|
||||
if (single_thread_timeout_usec != 0)
|
||||
if (first_timeout)
|
||||
{
|
||||
if (run_others)
|
||||
{
|
||||
// If we are running all threads then we take half the time to run all threads, bounded by
|
||||
// .25 sec.
|
||||
if (timeout_usec == 0)
|
||||
computed_timeout = default_one_thread_timeout_usec;
|
||||
else
|
||||
{
|
||||
computed_timeout = timeout_usec / 2;
|
||||
if (computed_timeout > default_one_thread_timeout_usec)
|
||||
{
|
||||
computed_timeout = default_one_thread_timeout_usec;
|
||||
}
|
||||
timeout_usec -= computed_timeout;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
computed_timeout = timeout_usec;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
computed_timeout = timeout_usec;
|
||||
}
|
||||
|
||||
if (computed_timeout != 0)
|
||||
{
|
||||
// we have a > 0 timeout, let us set it so that we stop after the deadline
|
||||
real_timeout = TimeValue::Now();
|
||||
real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
|
||||
real_timeout.OffsetWithMicroSeconds(computed_timeout);
|
||||
|
||||
timeout_ptr = &real_timeout;
|
||||
}
|
||||
else if (first_timeout)
|
||||
{
|
||||
// if we are willing to wait "forever" we still need to have an initial timeout
|
||||
// this timeout is going to induce all threads to run when hit. we do this so that
|
||||
// we can avoid ending locked up because of multithreaded contention issues
|
||||
real_timeout = TimeValue::Now();
|
||||
real_timeout.OffsetWithNanoSeconds(500000000UL);
|
||||
timeout_ptr = &real_timeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeout_ptr = NULL; // if we are in a no-timeout scenario, then we only need a fake timeout the first time through
|
||||
// at this point in the code, all threads will be running so we are willing to wait forever, and do not
|
||||
// need a timeout
|
||||
timeout_ptr = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -4471,21 +4493,21 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
|
|||
// Not really sure what to do if Halt fails here...
|
||||
|
||||
if (log) {
|
||||
if (try_all_threads)
|
||||
if (run_others)
|
||||
{
|
||||
if (first_timeout)
|
||||
log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
|
||||
"trying with all threads enabled.",
|
||||
single_thread_timeout_usec);
|
||||
log->Printf ("Process::RunThreadPlan(): Running function with timeout: %lld timed out, "
|
||||
"trying for %d usec with all threads enabled.",
|
||||
computed_timeout, timeout_usec);
|
||||
else
|
||||
log->Printf ("Process::RunThreadPlan(): Restarting function with all threads enabled "
|
||||
"and timeout: %d timed out.",
|
||||
single_thread_timeout_usec);
|
||||
"and timeout: %d timed out, abandoning execution.",
|
||||
timeout_usec);
|
||||
}
|
||||
else
|
||||
log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
|
||||
"halt and abandoning execution.",
|
||||
single_thread_timeout_usec);
|
||||
"abandoning execution.",
|
||||
timeout_usec);
|
||||
}
|
||||
|
||||
Error halt_error = Halt();
|
||||
|
@ -4526,7 +4548,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!try_all_threads)
|
||||
if (!run_others)
|
||||
{
|
||||
if (log)
|
||||
log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting.");
|
||||
|
|
|
@ -1747,7 +1747,8 @@ Target::EvaluateExpression
|
|||
expr_cstr,
|
||||
prefix,
|
||||
result_valobj_sp,
|
||||
options.GetSingleThreadTimeoutUsec());
|
||||
options.GetRunOthers(),
|
||||
options.GetTimeoutUsec());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
LEVEL = ../../make
|
||||
|
||||
C_SOURCES := wait-a-while.c
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,94 @@
|
|||
"""
|
||||
Test calling a function that waits a while, and make sure the timeout option to expr works.
|
||||
"""
|
||||
|
||||
import unittest2
|
||||
import lldb
|
||||
import lldbutil
|
||||
from lldbtest import *
|
||||
|
||||
class ExprCommandWithTimeoutsTestCase(TestBase):
|
||||
|
||||
mydir = os.path.join("expression_command", "timeout")
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
|
||||
self.main_source = "wait-a-while.c"
|
||||
self.main_source_spec = lldb.SBFileSpec (self.main_source)
|
||||
|
||||
|
||||
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
|
||||
@dsym_test
|
||||
def test_with_dsym(self):
|
||||
"""Test calling std::String member function."""
|
||||
self.buildDsym()
|
||||
self.call_function()
|
||||
|
||||
@dwarf_test
|
||||
def test_with_dwarf(self):
|
||||
"""Test calling std::String member function."""
|
||||
self.buildDsym()
|
||||
self.call_function()
|
||||
|
||||
def call_function(self):
|
||||
"""Test calling function with timeout."""
|
||||
exe_name = "a.out"
|
||||
exe = os.path.join(os.getcwd(), exe_name)
|
||||
|
||||
target = self.dbg.CreateTarget(exe)
|
||||
self.assertTrue(target, VALID_TARGET)
|
||||
|
||||
breakpoint = target.BreakpointCreateBySourceRegex('stop here in main.',self.main_source_spec)
|
||||
self.assertTrue(breakpoint, VALID_BREAKPOINT)
|
||||
self.runCmd("breakpoint list")
|
||||
|
||||
# Launch the process, and do not stop at the entry point.
|
||||
process = target.LaunchSimple(None, None, os.getcwd())
|
||||
|
||||
self.assertTrue(process, PROCESS_IS_VALID)
|
||||
|
||||
# Frame #0 should be on self.step_out_of_malloc.
|
||||
threads = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint)
|
||||
|
||||
self.assertTrue(len(threads) == 1)
|
||||
thread = threads[0]
|
||||
|
||||
# First set the timeout too short, and make sure we fail.
|
||||
options = lldb.SBExpressionOptions()
|
||||
options.SetTimeoutUsec(100)
|
||||
options.SetUnwindOnError(True)
|
||||
|
||||
frame = thread.GetFrameAtIndex(0)
|
||||
|
||||
value = frame.EvaluateExpression ("wait_a_while (10000)", options)
|
||||
self.assertTrue (value.IsValid())
|
||||
self.assertTrue (value.GetError().Success() == False)
|
||||
|
||||
# Now do the same thing with the command line command, and make sure it works too.
|
||||
interp = self.dbg.GetCommandInterpreter()
|
||||
|
||||
result = lldb.SBCommandReturnObject()
|
||||
return_value = interp.HandleCommand ("expr -t 100 -u true -- wait_a_while(10000)", result)
|
||||
self.assertTrue (return_value == lldb.eReturnStatusFailed)
|
||||
|
||||
# Okay, now do it again with long enough time outs:
|
||||
|
||||
options.SetTimeoutUsec(1000000)
|
||||
value = frame.EvaluateExpression ("wait_a_while (1000)", options)
|
||||
self.assertTrue(value.IsValid())
|
||||
self.assertTrue (value.GetError().Success() == True)
|
||||
|
||||
# Now do the same thingwith the command line command, and make sure it works too.
|
||||
interp = self.dbg.GetCommandInterpreter()
|
||||
|
||||
result = lldb.SBCommandReturnObject()
|
||||
return_value = interp.HandleCommand ("expr -t 1000000 -u true -- wait_a_while(1000)", result)
|
||||
self.assertTrue(return_value == lldb.eReturnStatusSuccessFinishResult)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
|
@ -0,0 +1,41 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int
|
||||
wait_a_while (useconds_t interval)
|
||||
{
|
||||
int num_times = 0;
|
||||
int return_value = 1;
|
||||
|
||||
struct timeval start_time;
|
||||
gettimeofday(&start_time, NULL);
|
||||
uint64_t target = start_time.tv_sec * 1000000 + start_time.tv_usec + interval;
|
||||
|
||||
while (1)
|
||||
{
|
||||
num_times++;
|
||||
return_value = usleep (interval);
|
||||
if (return_value != 0)
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
interval = target - now.tv_sec * 1000000 + now.tv_usec;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return num_times;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
printf ("stop here in main.\n");
|
||||
int num_times = wait_a_while (argc * 1000);
|
||||
printf ("Done, took %d times.\n", num_times);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
Loading…
Reference in New Issue