class SBError;
class SBEvent;
class SBEventList;
+class SBExpressionOptions;
class SBFileSpec;
class SBFileSpecList;
class SBFrame;
--- /dev/null
+//===-- 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_
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
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);
/// 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.
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);
//------------------------------------------------------------------
/// 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.
///
/// @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.
/// @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.
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);
/// 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.
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,
/// @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.
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,
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:
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 *
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
//----------------------------------------------------------------------
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,
class DynamicLoader;
class EmulateInstruction;
class Error;
+class EvaluateExpressionOptions;
class Event;
class EventData;
class ExecutionContext;
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 */; };
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>"; };
2611FEFC142D83060017FEA3 /* SBFileSpec.i */,
2611FEFD142D83060017FEA3 /* SBFileSpecList.i */,
2611FEFE142D83060017FEA3 /* SBFrame.i */,
+ 4CE4F676162CE1E100F75CB3 /* SBExpressionOptions.i */,
2611FEFF142D83060017FEA3 /* SBFunction.i */,
2611FF00142D83060017FEA3 /* SBHostOS.i */,
2611FF01142D83060017FEA3 /* SBInputReader.i */,
2682F284115EF3A700CCFF99 /* SBError.cpp */,
9A9830FE1125FC5800A56CB0 /* SBEvent.h */,
9A9830FD1125FC5800A56CB0 /* SBEvent.cpp */,
+ 4CE4F672162C971A00F75CB3 /* SBExpressionOptions.h */,
+ 4CE4F674162C973F00F75CB3 /* SBExpressionOptions.cpp */,
26022531115F27FA00A601A2 /* SBFileSpec.h */,
26022532115F281400A601A2 /* SBFileSpec.cpp */,
4CF52AF41428291E0051E832 /* SBFileSpecList.h */,
B2A58722143119810092BFBA /* SBWatchpoint.h in Headers */,
26D265A2136B40EE002EEE45 /* SharingPtr.h in Headers */,
26D265BC136B4269002EEE45 /* lldb-public.h in Headers */,
+ 4CE4F673162C971A00F75CB3 /* SBExpressionOptions.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9475C18814E5E9FA001BFC6D /* SBTypeCategory.cpp in Sources */,
9475C18E14E5F834001BFC6D /* SBTypeNameSpecifier.cpp in Sources */,
9452573A16262D0200325455 /* SBDeclaration.cpp in Sources */,
+ 4CE4F675162C973F00F75CB3 /* SBExpressionOptions.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
" ${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"\
" ${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"\
--- /dev/null
+//===-- 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
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
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);
#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"
%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"
--- /dev/null
+//===-- 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());
+}
#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"
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;
}
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));
LogSP expr_log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
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);
#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;
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;
}
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;
lldb::ValueObjectSP value_sp(GetSP());
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));
}
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));
}
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."},
};
//}
//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':
}
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;
unwind_on_error = true;
show_types = true;
show_summary = true;
+ try_all_threads = true;
+ timeout = 0;
}
const OptionDefinition*
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\
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(),
bool unwind_on_error;
bool show_types;
bool show_summary;
+ uint32_t timeout;
+ bool try_all_threads;
};
CommandObjectExpression (CommandInterpreter &interpreter);
if (command && command[0] != '\0')
{
Target *target = exe_ctx.GetTargetPtr();
- Target::EvaluateExpressionOptions options;
+ EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetUseDynamic(eNoDynamicValues);
}
// 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,
if (!target || !stack_frame)
return false;
- Target::EvaluateExpressionOptions options;
+ EvaluateExpressionOptions options;
options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(true)
if (!target || !stack_frame)
return valobj_sp;
- Target::EvaluateExpressionOptions options;
+ EvaluateExpressionOptions options;
options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(true)
if (!target || !stack_frame)
return valobj_sp;
- Target::EvaluateExpressionOptions options;
+ EvaluateExpressionOptions options;
options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(true)
if (!target || !stack_frame)
return false;
- Target::EvaluateExpressionOptions options;
+ EvaluateExpressionOptions options;
options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(true)
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;
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);
}
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)
{
stop_others,
try_all_threads,
discard_on_error,
- single_thread_timeout_usec,
+ timeout_usec,
errors);
if (exe_ctx.GetProcessPtr())
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)
stop_others,
try_all_threads,
discard_on_error,
- single_thread_timeout_usec,
+ timeout_usec,
errors);
if (args_addr_ptr != NULL)
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.
stop_others,
try_all_threads,
discard_on_error,
- single_thread_timeout_usec,
+ timeout_usec,
error_stream);
if (exe_ctx.GetProcessPtr())
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
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));
discard_on_error,
user_expression_sp,
expr_result,
- single_thread_timeout_usec);
+ run_others,
+ timeout_usec);
if (execution_results != eExecutionCompleted)
{
{
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(),
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)
stop_other_threads,
try_all_threads,
discard_on_error,
- single_thread_timeout_usec,
+ timeout_usec,
error_strm);
if (result == eExecutionCompleted)
{
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))
stop_other_threads,
try_all_threads,
discard_on_error,
- single_thread_timeout_usec,
+ timeout_usec,
error_strm);
if (result == eExecutionCompleted)
{
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;
bool first_timeout = true;
bool do_resume = true;
+ const uint64_t default_one_thread_timeout_usec = 250000;
+ uint64_t computed_timeout = 0;
while (1)
{
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;
}
// 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)
{
- // 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);
-
- timeout_ptr = &real_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;
}
- else if (first_timeout)
+
+ if (computed_timeout != 0)
{
- // 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
+ // we have a > 0 timeout, let us set it so that we stop after the deadline
real_timeout = TimeValue::Now();
- real_timeout.OffsetWithNanoSeconds(500000000UL);
+ real_timeout.OffsetWithMicroSeconds(computed_timeout);
+
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
// 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();
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.");
expr_cstr,
prefix,
result_valobj_sp,
- options.GetSingleThreadTimeoutUsec());
+ options.GetRunOthers(),
+ options.GetTimeoutUsec());
}
}
--- /dev/null
+LEVEL = ../../make
+
+C_SOURCES := wait-a-while.c
+
+include $(LEVEL)/Makefile.rules
--- /dev/null
+"""
+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()
--- /dev/null
+#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;
+
+}