This patch does a couple of things.

It completes the job of using EvaluateExpressionOptions consistently throughout
the inferior function calling mechanism in lldb begun in Greg's patch r194009. 

It removes a handful of alternate calls into the ClangUserExpression/ClangFunction/ThreadPlanCallFunction which
were there for convenience.  Using the EvaluateExpressionOptions removes the need for them.

Using that it gets the --debug option from Greg's patch to work cleanly.

It also adds another EvaluateExpressionOption to not trap exceptions when running expressions.  You shouldn't
use this option unless you KNOW your expression can't throw beyond itself.  This is:

<rdar://problem/15374885>

At present this is only available through the SB API's or python.

It fixes a bug where function calls would unset the ObjC & C++ exception breakpoints without checking whether
they were set by somebody else already.

llvm-svn: 194182
This commit is contained in:
Jim Ingham 2013-11-07 00:11:47 +00:00
parent bed356a9ea
commit 6fbc48bc42
36 changed files with 425 additions and 710 deletions

View File

@ -65,6 +65,12 @@ public:
void
SetTryAllThreads (bool run_others = true);
bool
GetTrapExceptions () const;
void
SetTrapExceptions (bool trap_exceptions = true);
protected:
SBExpressionOptions (lldb_private::EvaluateExpressionOptions &expression_options);

View File

@ -226,143 +226,6 @@ public:
ValueList &arg_values,
Stream &errors);
//------------------------------------------------------------------
/// [Static] Execute a function, passing it a single void* parameter.
/// ClangFunction uses this to call the wrapper function.
///
/// @param[in] exe_ctx
/// The execution context to insert the function and its arguments
/// into.
///
/// @param[in] function_address
/// The address of the function in the target process.
///
/// @param[in] void_arg
/// The value of the void* parameter.
///
/// @param[in] stop_others
/// True if other threads should pause during execution.
///
/// @param[in] try_all_threads
/// If the timeout expires, true if other threads should run. If
/// the function may try to take locks, this is useful.
///
/// @param[in] unwind_on_error
/// If true, and the execution stops before completion, we unwind the
/// 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] 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.
///
/// @param[in] this_arg
/// If non-NULL, the function is invoked like a C++ method, with the
/// value pointed to by the pointer as its 'this' argument.
///
/// @return
/// Returns one of the ExecutionResults enum indicating function call status.
//------------------------------------------------------------------
static ExecutionResults
ExecuteFunction (ExecutionContext &exe_ctx,
lldb::addr_t function_address,
lldb::addr_t &void_arg,
bool stop_others,
bool try_all_threads,
bool unwind_on_error,
bool ignore_breakpoints,
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 stopping other threads
/// for a fixed timeout period (1000 usec) and if it does not complete,
/// we halt the process and try with all threads running.
///
/// @param[in] exe_ctx
/// The thread & process in which this function will run.
///
/// @param[in] errors
/// Errors will be written here if there are any.
///
/// @param[out] results
/// The result value will be put here after running the function.
///
/// @return
/// Returns one of the ExecutionResults enum indicating function call status.
//------------------------------------------------------------------
ExecutionResults
ExecuteFunction(ExecutionContext &exe_ctx,
Stream &errors,
Value &results);
//------------------------------------------------------------------
/// Run the function this ClangFunction was created with.
///
/// This simple version will run the function obeying the stop_others
/// argument. There is no timeout.
///
/// @param[in] exe_ctx
/// The thread & process in which this function will run.
///
/// @param[in] errors
/// Errors will be written here if there are any.
///
/// @param[in] stop_others
/// If \b true, run only this thread, if \b false let all threads run.
///
/// @param[out] results
/// The result value will be put here after running the function.
///
/// @return
/// Returns one of the ExecutionResults enum indicating function call status.
//------------------------------------------------------------------
ExecutionResults
ExecuteFunction(ExecutionContext &exe_ctx,
Stream &errors, bool stop_others,
Value &results);
//------------------------------------------------------------------
/// Run the function this ClangFunction was created with.
///
/// 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] exe_ctx
/// The thread & process in which this function will run.
///
/// @param[in] errors
/// Errors will be written here if there are any.
///
/// @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[out] results
/// The result value will be put here after running the function.
///
/// @return
/// Returns one of the ExecutionResults enum indicating function call status.
//------------------------------------------------------------------
ExecutionResults
ExecuteFunction(ExecutionContext &exe_ctx,
Stream &errors,
uint32_t single_thread_timeout_usec,
bool try_all_threads,
Value &results);
//------------------------------------------------------------------
/// Run the function this ClangFunction was created with.
///
@ -381,17 +244,8 @@ public:
/// @param[in] errors
/// Errors will be written here if there are any.
///
/// @param[in] stop_others
/// 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] options
/// The options for this expression execution.
///
/// @param[out] results
/// The result value will be put here after running the function.
@ -402,62 +256,10 @@ public:
ExecutionResults
ExecuteFunction(ExecutionContext &exe_ctx,
lldb::addr_t *args_addr_ptr,
Stream &errors,
bool stop_others,
uint32_t timeout_usec,
bool try_all_threads,
bool unwind_on_error,
bool ignore_breakpoints,
const EvaluateExpressionOptions &options,
Stream &errors,
Value &results);
//------------------------------------------------------------------
/// [static] Get a thread plan to run a function.
///
/// @param[in] exe_ctx
/// The execution context to insert the function and its arguments
/// into.
///
/// @param[in] func_addr
/// The address of the function in the target process.
///
/// @param[in] args_addr_ref
/// The value of the void* parameter.
///
/// @param[in] errors
/// The stream to write errors to.
///
/// @param[in] stop_others
/// True if other threads should pause during execution.
///
/// @param[in] unwind_on_error
/// True if the thread plan may simply be discarded if an error occurs.
///
/// @param[in] ignore_breakpoints
/// True if the expression execution will ignore breakpoint hits and continue executing.
///
/// @param[in] this_arg
/// If non-NULL (and cmd_arg is NULL), the function is invoked like a C++
/// method, with the value pointed to by the pointer as its 'this'
/// argument.
///
/// @param[in] cmd_arg
/// If non-NULL, the function is invoked like an Objective-C method, with
/// this_arg in the 'self' slot and cmd_arg in the '_cmd' slot
///
/// @return
/// A ThreadPlan for executing the function.
//------------------------------------------------------------------
static ThreadPlan *
GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::addr_t func_addr,
lldb::addr_t &args_addr_ref,
Stream &errors,
bool stop_others,
bool unwind_on_error,
bool ignore_breakpoints,
lldb::addr_t *this_arg = 0,
lldb::addr_t *cmd_arg = 0);
//------------------------------------------------------------------
/// Get a thread plan to run the function this ClangFunction was created with.
///
@ -485,20 +287,9 @@ public:
//------------------------------------------------------------------
ThreadPlan *
GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::addr_t &args_addr_ref,
Stream &errors,
bool stop_others,
bool unwind_on_error = true,
bool ignore_breakpoints = true)
{
return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
m_jit_start_addr,
args_addr_ref,
errors,
stop_others,
unwind_on_error,
ignore_breakpoints);
}
lldb::addr_t &args_addr_ref,
const EvaluateExpressionOptions &options,
Stream &errors);
//------------------------------------------------------------------
/// Get the result of the function from its struct

View File

@ -150,10 +150,6 @@ public:
ClangUserExpressionSP &shared_ptr_to_me,
lldb::ClangExpressionVariableSP &result);
ThreadPlan *
GetThreadPlanToExecuteJITExpression (Stream &error_stream,
ExecutionContext &exe_ctx);
//------------------------------------------------------------------
/// Apply the side effects of the function to program state.
///

View File

@ -66,6 +66,12 @@ public:
{
}
virtual bool
ExceptionBreakpointsAreSet ()
{
return false;
}
virtual bool
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
{

View File

@ -2502,11 +2502,7 @@ public:
ExecutionResults
RunThreadPlan (ExecutionContext &exe_ctx,
lldb::ThreadPlanSP &thread_plan_sp,
bool stop_others,
bool run_others,
bool unwind_on_error,
bool ignore_breakpoints,
uint32_t timeout_usec,
const EvaluateExpressionOptions &options,
Stream &errors);
static const char *

View File

@ -189,8 +189,10 @@ public:
m_unwind_on_error(true),
m_ignore_breakpoints (false),
m_keep_in_memory(false),
m_run_others(true),
m_try_others(true),
m_stop_others(true),
m_debug(false),
m_trap_exceptions(true),
m_use_dynamic(lldb::eNoDynamicValues),
m_timeout_usec(default_timeout)
{}
@ -201,11 +203,10 @@ public:
return m_execution_policy;
}
EvaluateExpressionOptions&
void
SetExecutionPolicy (ExecutionPolicy policy = eExecutionPolicyAlways)
{
m_execution_policy = policy;
return *this;
}
lldb::LanguageType
@ -214,11 +215,10 @@ public:
return m_language;
}
EvaluateExpressionOptions&
void
SetLanguage(lldb::LanguageType language)
{
m_language = language;
return *this;
}
bool
@ -227,11 +227,10 @@ public:
return m_coerce_to_id;
}
EvaluateExpressionOptions&
void
SetCoerceToId (bool coerce = true)
{
m_coerce_to_id = coerce;
return *this;
}
bool
@ -240,11 +239,10 @@ public:
return m_unwind_on_error;
}
EvaluateExpressionOptions&
void
SetUnwindOnError (bool unwind = false)
{
m_unwind_on_error = unwind;
return *this;
}
bool
@ -253,11 +251,10 @@ public:
return m_ignore_breakpoints;
}
EvaluateExpressionOptions&
void
SetIgnoreBreakpoints (bool ignore = false)
{
m_ignore_breakpoints = ignore;
return *this;
}
bool
@ -266,11 +263,10 @@ public:
return m_keep_in_memory;
}
EvaluateExpressionOptions&
void
SetKeepInMemory (bool keep = true)
{
m_keep_in_memory = keep;
return *this;
}
lldb::DynamicValueType
@ -279,11 +275,10 @@ public:
return m_use_dynamic;
}
EvaluateExpressionOptions&
void
SetUseDynamic (lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget)
{
m_use_dynamic = dynamic;
return *this;
}
uint32_t
@ -292,24 +287,34 @@ public:
return m_timeout_usec;
}
EvaluateExpressionOptions&
void
SetTimeoutUsec (uint32_t timeout = 0)
{
m_timeout_usec = timeout;
return *this;
}
bool
GetRunOthers () const
GetTryAllThreads () const
{
return m_run_others;
return m_try_others;
}
EvaluateExpressionOptions&
SetRunOthers (bool run_others = true)
void
SetTryAllThreads (bool try_others = true)
{
m_run_others = run_others;
return *this;
m_try_others = try_others;
}
bool
GetStopOthers () const
{
return m_stop_others;
}
void
SetStopOthers (bool stop_others = true)
{
m_stop_others = stop_others;
}
bool
@ -318,11 +323,22 @@ public:
return m_debug;
}
EvaluateExpressionOptions&
void
SetDebug(bool b)
{
m_debug = b;
return *this;
}
bool
GetTrapExceptions() const
{
return m_trap_exceptions;
}
void
SetTrapExceptions (bool b)
{
m_trap_exceptions = b;
}
private:
@ -332,8 +348,10 @@ private:
bool m_unwind_on_error;
bool m_ignore_breakpoints;
bool m_keep_in_memory;
bool m_run_others;
bool m_try_others;
bool m_stop_others;
bool m_debug;
bool m_trap_exceptions;
lldb::DynamicValueType m_use_dynamic;
uint32_t m_timeout_usec;
};

View File

@ -528,21 +528,6 @@ public:
virtual lldb::ThreadPlanSP
QueueFundamentalPlan (bool abort_other_plans);
//------------------------------------------------------------------
/// Queues the plan used to step over a breakpoint at the current PC of \a thread.
/// The default version returned by Process handles trap based breakpoints, and
/// will disable the breakpoint, single step over it, then re-enable it.
///
/// @param[in] abort_other_plans
/// \b true if we discard the currently queued plans and replace them with this one.
/// Otherwise this plan will go on the end of the plan stack.
///
/// @return
/// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans);
//------------------------------------------------------------------
/// Queues the plan used to step one instruction from the current PC of \a thread.
///
@ -728,14 +713,6 @@ public:
bool stop_others,
uint32_t frame_idx);
virtual lldb::ThreadPlanSP
QueueThreadPlanForCallFunction (bool abort_other_plans,
Address& function,
lldb::addr_t arg,
bool stop_other_threads,
bool unwind_on_error = false,
bool ignore_breakpoints = true);
//------------------------------------------------------------------
// Thread Plan accessors:
//------------------------------------------------------------------

View File

@ -30,18 +30,14 @@ public:
const Address &function,
const ClangASTType &return_type,
lldb::addr_t arg,
bool stop_other_threads,
bool unwind_on_error = true,
bool ignore_breakpoints = false,
const EvaluateExpressionOptions &options,
lldb::addr_t *this_arg = 0,
lldb::addr_t *cmd_arg = 0);
ThreadPlanCallFunction (Thread &thread,
const Address &function,
const ClangASTType &return_type,
bool stop_other_threads,
bool unwind_on_error,
bool ignore_breakpoints,
const EvaluateExpressionOptions &options,
lldb::addr_t *arg1_ptr = NULL,
lldb::addr_t *arg2_ptr = NULL,
lldb::addr_t *arg3_ptr = NULL,
@ -171,6 +167,10 @@ private:
bool m_valid;
bool m_stop_other_threads;
bool m_unwind_on_error;
bool m_ignore_breakpoints;
bool m_debug_execution;
bool m_trap_exceptions;
Address m_function_addr;
Address m_start_addr;
lldb::addr_t m_function_sp;
@ -187,9 +187,9 @@ private:
ClangASTType m_return_type;
lldb::ValueObjectSP m_return_valobj_sp; // If this contains a valid pointer, use the ABI to extract values when complete
bool m_takedown_done; // We want to ensure we only do the takedown once. This ensures that.
bool m_should_clear_objc_exception_bp;
bool m_should_clear_cxx_exception_bp;
lldb::addr_t m_stop_address; // This is the address we stopped at. Also set in DoTakedown;
bool m_unwind_on_error;
bool m_ignore_breakpoints;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction);
};

View File

@ -28,9 +28,7 @@ public:
ThreadPlanCallUserExpression (Thread &thread,
Address &function,
lldb::addr_t arg,
bool stop_other_threads,
bool unwind_on_error,
bool ignore_breakpoints,
const EvaluateExpressionOptions &options,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg,
ClangUserExpression::ClangUserExpressionSP &user_expression_sp);

View File

@ -133,7 +133,8 @@ typedef enum ExecutionResults
eExecutionDiscarded,
eExecutionInterrupted,
eExecutionHitBreakpoint,
eExecutionTimedOut
eExecutionTimedOut,
eExecutionStoppedForDebug
} ExecutionResults;
typedef enum ObjCRuntimeVersions {

View File

@ -71,6 +71,13 @@ public:
void
SetTryAllThreads (bool run_others = true);
bool
GetTrapExceptions () const;
%feature("docstring", "Sets whether to abort expression evaluation if an exception is thrown while executing. Don't set this to false unless you know the function you are calling traps all exceptions itself.") SetTryAllThreads;
void
SetTrapExceptions (bool trap_exceptions = true);
protected:
SBExpressionOptions (lldb_private::EvaluateExpressionOptions &expression_options);

View File

@ -104,13 +104,25 @@ SBExpressionOptions::SetTimeoutInMicroSeconds (uint32_t timeout)
bool
SBExpressionOptions::GetTryAllThreads () const
{
return m_opaque_ap->GetRunOthers ();
return m_opaque_ap->GetTryAllThreads ();
}
void
SBExpressionOptions::SetTryAllThreads (bool run_others)
{
m_opaque_ap->SetRunOthers (run_others);
m_opaque_ap->SetTryAllThreads (run_others);
}
bool
SBExpressionOptions::GetTrapExceptions () const
{
return m_opaque_ap->GetTrapExceptions ();
}
void
SBExpressionOptions::SetTrapExceptions (bool trap_exceptions)
{
m_opaque_ap->SetTrapExceptions (trap_exceptions);
}
EvaluateExpressionOptions *

View File

@ -295,7 +295,7 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
options.SetRunOthers(true);
options.SetTryAllThreads(true);
Error expr_error;

View File

@ -363,13 +363,13 @@ CommandObjectExpression::EvaluateExpression
bool keep_in_memory = true;
EvaluateExpressionOptions options;
options.SetCoerceToId(m_varobj_options.use_objc)
.SetUnwindOnError(m_command_options.unwind_on_error)
.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints)
.SetKeepInMemory(keep_in_memory)
.SetUseDynamic(m_varobj_options.use_dynamic)
.SetRunOthers(m_command_options.try_all_threads)
.SetDebug(m_command_options.debug);
options.SetCoerceToId(m_varobj_options.use_objc);
options.SetUnwindOnError(m_command_options.unwind_on_error);
options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);
options.SetKeepInMemory(keep_in_memory);
options.SetUseDynamic(m_varobj_options.use_dynamic);
options.SetTryAllThreads(m_command_options.try_all_threads);
options.SetDebug(m_command_options.debug);
if (m_command_options.timeout > 0)
options.SetTimeoutUsec(m_command_options.timeout);

View File

@ -1256,11 +1256,11 @@ protected:
// Use expression evaluation to arrive at the address to watch.
EvaluateExpressionOptions options;
options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(false)
.SetRunOthers(true)
.SetTimeoutUsec(0);
options.SetCoerceToId(false);
options.SetUnwindOnError(true);
options.SetKeepInMemory(false);
options.SetTryAllThreads(true);
options.SetTimeoutUsec(0);
ExecutionResults expr_result = target->EvaluateExpression (expr,
frame,

View File

@ -49,9 +49,9 @@ lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
return false;
EvaluateExpressionOptions options;
options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(true);
options.SetCoerceToId(false);
options.SetUnwindOnError(true);
options.SetKeepInMemory(true);
target->EvaluateExpression(expr.GetData(),
stack_frame,
@ -83,10 +83,10 @@ lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
return false;
EvaluateExpressionOptions options;
options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(true)
.SetUseDynamic(lldb::eDynamicCanRunTarget);
options.SetCoerceToId(false);
options.SetUnwindOnError(true);
options.SetKeepInMemory(true);
options.SetUseDynamic(lldb::eDynamicCanRunTarget);
target->EvaluateExpression(expr.GetData(),
stack_frame,
@ -121,10 +121,10 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
return valobj_sp;
EvaluateExpressionOptions options;
options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(true)
.SetUseDynamic(lldb::eDynamicCanRunTarget);
options.SetCoerceToId(false);
options.SetUnwindOnError(true);
options.SetKeepInMemory(true);
options.SetUseDynamic(lldb::eDynamicCanRunTarget);
target->EvaluateExpression(expr.GetData(),
stack_frame,
@ -158,10 +158,10 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
return valobj_sp;
EvaluateExpressionOptions options;
options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(true)
.SetUseDynamic(lldb::eDynamicCanRunTarget);
options.SetCoerceToId(false);
options.SetUnwindOnError(true);
options.SetKeepInMemory(true);
options.SetUseDynamic(lldb::eDynamicCanRunTarget);
target->EvaluateExpression(expr.GetData(),
stack_frame,

View File

@ -35,10 +35,10 @@ m_options()
{
if (valobj_sp)
Update();
m_options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(true)
.SetUseDynamic(lldb::eDynamicCanRunTarget);
m_options.SetCoerceToId(false);
m_options.SetUnwindOnError(true);
m_options.SetKeepInMemory(true);
m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
}
size_t

View File

@ -34,10 +34,10 @@ m_options()
{
if (valobj_sp)
Update();
m_options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(true)
.SetUseDynamic(lldb::eDynamicCanRunTarget);
m_options.SetCoerceToId(false);
m_options.SetUnwindOnError(true);
m_options.SetKeepInMemory(true);
m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
}
size_t
@ -215,10 +215,10 @@ lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIte
{
if (valobj_sp)
Update();
m_options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetKeepInMemory(true)
.SetUseDynamic(lldb::eDynamicCanRunTarget);
m_options.SetCoerceToId(false);
m_options.SetUnwindOnError(true);
m_options.SetKeepInMemory(true);
m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
}
bool

View File

@ -218,8 +218,10 @@ lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIn
StreamString object_fetcher_expr;
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;
EvaluateExpressionOptions options;
options.SetKeepInMemory(true);
m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp,
EvaluateExpressionOptions().SetKeepInMemory(true));
options);
if (child_sp)
child_sp->SetName(ConstString(idx_name.GetData()));
return child_sp;

View File

@ -394,14 +394,9 @@ ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_add
ThreadPlan *
ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::addr_t func_addr,
lldb::addr_t &args_addr,
Stream &errors,
bool stop_others,
bool unwind_on_error,
bool ignore_breakpoints,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg)
lldb::addr_t &args_addr,
const EvaluateExpressionOptions &options,
Stream &errors)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
@ -418,16 +413,14 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
// Okay, now run the function:
Address wrapper_address (func_addr);
Address wrapper_address (m_jit_start_addr);
ThreadPlan *new_plan = new ThreadPlanCallFunction (*thread,
wrapper_address,
ClangASTType(),
args_addr,
stop_others,
unwind_on_error,
ignore_breakpoints,
this_arg,
cmd_arg);
options,
0,
0);
new_plan->SetIsMasterPlan(true);
new_plan->SetOkayToDiscard (false);
return new_plan;
@ -478,113 +471,24 @@ ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_
exe_ctx.GetProcessRef().DeallocateMemory(args_addr);
}
ExecutionResults
ClangFunction::ExecuteFunction(ExecutionContext &exe_ctx, Stream &errors, Value &results)
{
return ExecuteFunction (exe_ctx, errors, 1000, true, results);
}
ExecutionResults
ClangFunction::ExecuteFunction(ExecutionContext &exe_ctx, Stream &errors, bool stop_others, Value &results)
{
const bool try_all_threads = false;
const bool unwind_on_error = true;
const bool ignore_breakpoints = true;
return ExecuteFunction (exe_ctx, NULL, errors, stop_others, 0UL, try_all_threads,
unwind_on_error, ignore_breakpoints, results);
}
ExecutionResults
ClangFunction::ExecuteFunction(
ExecutionContext &exe_ctx,
lldb::addr_t *args_addr_ptr,
const EvaluateExpressionOptions &options,
Stream &errors,
uint32_t timeout_usec,
bool try_all_threads,
Value &results)
{
const bool stop_others = true;
const bool unwind_on_error = true;
const bool ignore_breakpoints = true;
return ExecuteFunction (exe_ctx, NULL, errors, stop_others, timeout_usec,
try_all_threads, unwind_on_error, ignore_breakpoints, results);
}
// This is the static function
ExecutionResults
ClangFunction::ExecuteFunction (
ExecutionContext &exe_ctx,
lldb::addr_t function_address,
lldb::addr_t &void_arg,
bool stop_others,
bool try_all_threads,
bool unwind_on_error,
bool ignore_breakpoints,
uint32_t timeout_usec,
Stream &errors,
lldb::addr_t *this_arg)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
log->Printf("== [ClangFunction::ExecuteFunction] Executing function ==");
lldb::ThreadPlanSP call_plan_sp (ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
function_address,
void_arg,
errors,
stop_others,
unwind_on_error,
ignore_breakpoints,
this_arg));
if (!call_plan_sp)
return eExecutionSetupError;
// <rdar://problem/12027563> we need to make sure we record the fact that we are running an expression here
// otherwise this fact will fail to be recorded when fetching an Objective-C object description
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
ExecutionResults results = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, call_plan_sp,
stop_others,
try_all_threads,
unwind_on_error,
ignore_breakpoints,
timeout_usec,
errors);
if (log)
{
if (results != eExecutionCompleted)
{
log->Printf("== [ClangFunction::ExecuteFunction] Execution completed abnormally ==");
}
else
{
log->Printf("== [ClangFunction::ExecuteFunction] Execution completed normally ==");
}
}
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
return results;
}
ExecutionResults
ClangFunction::ExecuteFunction(
ExecutionContext &exe_ctx,
lldb::addr_t *args_addr_ptr,
Stream &errors,
bool stop_others,
uint32_t timeout_usec,
bool try_all_threads,
bool unwind_on_error,
bool ignore_breakpoints,
Value &results)
{
using namespace clang;
ExecutionResults return_value = eExecutionSetupError;
// ClangFunction::ExecuteFunction execution is always just to get the result. Do make sure we ignore
// breakpoints, unwind on error, and don't try to debug it.
EvaluateExpressionOptions real_options = options;
real_options.SetDebug(false);
real_options.SetUnwindOnError(true);
real_options.SetIgnoreBreakpoints(true);
lldb::addr_t args_addr;
if (args_addr_ptr != NULL)
@ -600,17 +504,44 @@ ClangFunction::ExecuteFunction(
if (!InsertFunction(exe_ctx, args_addr, errors))
return eExecutionSetupError;
}
return_value = ClangFunction::ExecuteFunction (exe_ctx,
m_jit_start_addr,
args_addr,
stop_others,
try_all_threads,
unwind_on_error,
ignore_breakpoints,
timeout_usec,
errors);
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
log->Printf("== [ClangFunction::ExecuteFunction] Executing function ==");
lldb::ThreadPlanSP call_plan_sp (GetThreadPlanToCallFunction (exe_ctx,
args_addr,
real_options,
errors));
if (!call_plan_sp)
return eExecutionSetupError;
// <rdar://problem/12027563> we need to make sure we record the fact that we are running an expression here
// otherwise this fact will fail to be recorded when fetching an Objective-C object description
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
return_value = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
call_plan_sp,
real_options,
errors);
if (log)
{
if (return_value != eExecutionCompleted)
{
log->Printf("== [ClangFunction::ExecuteFunction] Execution completed abnormally ==");
}
else
{
log->Printf("== [ClangFunction::ExecuteFunction] Execution completed normally ==");
}
}
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
if (args_addr_ptr != NULL)
*args_addr_ptr = args_addr;

View File

@ -716,35 +716,6 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
return true;
}
ThreadPlan *
ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
ExecutionContext &exe_ctx)
{
lldb::addr_t struct_address;
lldb::addr_t object_ptr = 0;
lldb::addr_t cmd_ptr = 0;
PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr);
// FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
// ClangUserExpression resources before the thread plan finishes execution in the target. But because we are
// forcing unwind_on_error to be true here, in practical terms that can't happen.
const bool stop_others = true;
const bool unwind_on_error = true;
const bool ignore_breakpoints = false;
return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
m_jit_start_addr,
struct_address,
error_stream,
stop_others,
unwind_on_error,
ignore_breakpoints,
(m_needs_object_ptr ? &object_ptr : NULL),
(m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
}
bool
ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
ExecutionContext &exe_ctx,
@ -852,25 +823,11 @@ ClangUserExpression::Execute (Stream &error_stream,
}
else
{
const uint32_t timeout_usec = options.GetTimeoutUsec();
const bool debug = options.GetDebug();
const bool unwind_on_error = debug ? false : options.DoesUnwindOnError();
const bool ignore_breakpoints = debug ? false : options.DoesIgnoreBreakpoints();
const bool stop_others = true;
const bool try_all_threads = options.GetRunOthers();
lldb::BreakpointSP debug_bkpt_sp;
if (debug)
{
// TODO: push this down into the thread plan and let the plan manage it
debug_bkpt_sp = exe_ctx.GetTargetRef().CreateBreakpoint(m_jit_start_addr, false, false);
}
Address wrapper_address (m_jit_start_addr);
lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
wrapper_address,
struct_address,
stop_others,
unwind_on_error,
ignore_breakpoints,
struct_address,
options,
(m_needs_object_ptr ? &object_ptr : NULL),
((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
shared_ptr_to_me));
@ -890,19 +847,10 @@ ClangUserExpression::Execute (Stream &error_stream,
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
call_plan_sp,
stop_others,
try_all_threads,
unwind_on_error,
ignore_breakpoints,
timeout_usec,
call_plan_sp,
options,
error_stream);
if (debug_bkpt_sp)
{
exe_ctx.GetTargetRef().RemoveBreakpointByID(debug_bkpt_sp->GetID());
}
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
@ -922,16 +870,22 @@ ClangUserExpression::Execute (Stream &error_stream,
if (error_desc)
error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
else
error_stream.Printf ("Execution was interrupted.");
error_stream.PutCString ("Execution was interrupted.");
if ((execution_result == eExecutionInterrupted && unwind_on_error)
|| (execution_result == eExecutionHitBreakpoint && ignore_breakpoints))
error_stream.Printf ("\nThe process has been returned to the state before expression evaluation.");
if ((execution_result == eExecutionInterrupted && options.DoesUnwindOnError())
|| (execution_result == eExecutionHitBreakpoint && options.DoesIgnoreBreakpoints()))
error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
else
error_stream.Printf ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");
error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");
return execution_result;
}
else if (execution_result == eExecutionStoppedForDebug)
{
error_stream.PutCString ("Execution was halted at the first instruction of the expression function because \"debug\" was requested.\n"
"Use \"thread return -x\" to return to the state before expression evaluation.");
return execution_result;
}
else if (execution_result != eExecutionCompleted)
{
error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));

View File

@ -815,7 +815,7 @@ Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::add
options.SetCoerceToId(false);
options.SetUnwindOnError(true);
options.SetKeepInMemory(false);
options.SetRunOthers(true);
options.SetTryAllThreads(true);
ExecutionResults expr_result = target->EvaluateExpression(s,
exe_ctx->GetFramePtr(),

View File

@ -1434,12 +1434,12 @@ CommandInterpreter::PreprocessCommand (std::string &command)
ValueObjectSP expr_result_valobj_sp;
EvaluateExpressionOptions options;
options.SetCoerceToId(false)
.SetUnwindOnError(true)
.SetIgnoreBreakpoints(true)
.SetKeepInMemory(false)
.SetRunOthers(true)
.SetTimeoutUsec(0);
options.SetCoerceToId(false);
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
options.SetKeepInMemory(false);
options.SetTryAllThreads(true);
options.SetTimeoutUsec(0);
ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
exe_ctx.GetFramePtr(),

View File

@ -444,6 +444,12 @@ ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
}
}
bool
ItaniumABILanguageRuntime::ExceptionBreakpointsAreSet ()
{
return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled();
}
bool
ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
{

View File

@ -70,6 +70,9 @@ namespace lldb_private {
virtual void
ClearExceptionBreakpoints ();
virtual bool
ExceptionBreakpointsAreSet ();
virtual bool
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason);

View File

@ -137,19 +137,17 @@ AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionCon
lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS;
func.InsertFunction(exe_ctx, wrapper_struct_addr, error_stream);
const bool unwind_on_error = true;
const bool try_all_threads = true;
const bool stop_others = true;
const bool ignore_breakpoints = true;
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetTryAllThreads(true);
options.SetStopOthers(true);
options.SetIgnoreBreakpoints(true);
options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC);
ExecutionResults results = func.ExecuteFunction (exe_ctx,
&wrapper_struct_addr,
&wrapper_struct_addr,
options,
error_stream,
stop_others,
PO_FUNCTION_TIMEOUT_USEC /* 15 secs timeout */,
try_all_threads,
unwind_on_error,
ignore_breakpoints,
ret);
if (results != eExecutionCompleted)
{
@ -361,6 +359,12 @@ AppleObjCRuntime::ClearExceptionBreakpoints ()
}
}
bool
AppleObjCRuntime::ExceptionBreakpointsAreSet ()
{
return m_objc_exception_bp_sp && m_objc_exception_bp_sp->IsEnabled();
}
bool
AppleObjCRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
{

View File

@ -94,6 +94,9 @@ public:
virtual void
ClearExceptionBreakpoints ();
virtual bool
ExceptionBreakpointsAreSet ();
virtual bool
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason);

View File

@ -1829,10 +1829,12 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
arguments,
errors))
{
bool stop_others = true;
bool try_all_threads = false;
bool unwind_on_error = true;
bool ignore_breakpoints = true;
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetTryAllThreads(false);
options.SetStopOthers(true);
options.SetIgnoreBreakpoints(true);
options.SetTimeoutUsec(UTILITY_FUNCTION_TIMEOUT_USEC);
Value return_value;
return_value.SetValueType (Value::eValueTypeScalar);
@ -1845,12 +1847,8 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
// Run the function
ExecutionResults results = m_get_class_info_function->ExecuteFunction (exe_ctx,
&m_get_class_info_args,
options,
errors,
stop_others,
UTILITY_FUNCTION_TIMEOUT_USEC,
try_all_threads,
unwind_on_error,
ignore_breakpoints,
return_value);
if (results == eExecutionCompleted)
@ -2080,10 +2078,12 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
arguments,
errors))
{
bool stop_others = true;
bool try_all_threads = false;
bool unwind_on_error = true;
bool ignore_breakpoints = true;
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetTryAllThreads(false);
options.SetStopOthers(true);
options.SetIgnoreBreakpoints(true);
options.SetTimeoutUsec(UTILITY_FUNCTION_TIMEOUT_USEC);
Value return_value;
return_value.SetValueType (Value::eValueTypeScalar);
@ -2096,12 +2096,8 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
// Run the function
ExecutionResults results = m_get_shared_cache_class_info_function->ExecuteFunction (exe_ctx,
&m_get_shared_cache_class_info_args,
options,
errors,
stop_others,
UTILITY_FUNCTION_TIMEOUT_USEC,
try_all_threads,
unwind_on_error,
ignore_breakpoints,
return_value);
if (results == eExecutionCompleted)

View File

@ -84,15 +84,15 @@ AppleThreadPlanStepThroughObjCTrampoline::InitializeClangFunction ()
}
m_impl_function = m_trampoline_handler->GetLookupImplementationWrapperFunction();
ExecutionContext exc_ctx;
const bool unwind_on_error = true;
const bool ignore_breakpoints = true;
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
options.SetStopOthers(m_stop_others);
m_thread.CalculateExecutionContext(exc_ctx);
m_func_sp.reset(m_impl_function->GetThreadPlanToCallFunction (exc_ctx,
m_args_addr,
errors,
m_stop_others,
unwind_on_error,
ignore_breakpoints));
options,
errors));
m_func_sp->SetOkayToDiscard(true);
m_thread.QueueThreadPlan (m_func_sp, false);
}

View File

@ -59,11 +59,13 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
{
const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
const bool use_inline_block_range = false;
const bool stop_other_threads = true;
const bool unwind_on_error = true;
const bool ignore_breakpoints = true;
const bool try_all_threads = true;
const uint32_t timeout_usec = 500000;
EvaluateExpressionOptions options;
options.SetStopOthers(true);
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
addr_t prot_arg, flags_arg = 0;
if (prot == eMmapProtNone)
@ -92,9 +94,7 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
= new ThreadPlanCallFunction (*thread,
mmap_range.GetBaseAddress(),
clang_void_ptr_type,
stop_other_threads,
unwind_on_error,
ignore_breakpoints,
options,
&addr,
&length,
&prot_arg,
@ -115,12 +115,8 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
ExecutionContext exe_ctx;
frame->CalculateExecutionContext (exe_ctx);
ExecutionResults result = process->RunThreadPlan (exe_ctx,
call_plan_sp,
stop_other_threads,
try_all_threads,
unwind_on_error,
ignore_breakpoints,
timeout_usec,
call_plan_sp,
options,
error_strm);
if (result == eExecutionCompleted)
{
@ -169,56 +165,52 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
SymbolContext sc;
if (sc_list.GetContextAtIndex(0, sc))
{
const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
const bool use_inline_block_range = false;
const bool stop_other_threads = true;
const bool unwind_on_error = true;
const bool ignore_breakpoints = true;
const bool try_all_threads = true;
const uint32_t timeout_usec = 500000;
const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
const bool use_inline_block_range = false;
EvaluateExpressionOptions options;
options.SetStopOthers(true);
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
AddressRange munmap_range;
if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
{
lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
AddressRange munmap_range;
if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
{
lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
munmap_range.GetBaseAddress(),
ClangASTType(),
stop_other_threads,
unwind_on_error,
ignore_breakpoints,
options,
&addr,
&length));
if (call_plan_sp)
{
StreamFile error_strm;
// This plan is a utility plan, so set it to discard itself when done.
call_plan_sp->SetIsMasterPlan (true);
call_plan_sp->SetOkayToDiscard(true);
if (call_plan_sp)
{
StreamFile error_strm;
// This plan is a utility plan, so set it to discard itself when done.
call_plan_sp->SetIsMasterPlan (true);
call_plan_sp->SetOkayToDiscard(true);
StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
if (frame)
{
ExecutionContext exe_ctx;
frame->CalculateExecutionContext (exe_ctx);
ExecutionResults result = process->RunThreadPlan (exe_ctx,
call_plan_sp,
stop_other_threads,
try_all_threads,
unwind_on_error,
ignore_breakpoints,
timeout_usec,
error_strm);
if (result == eExecutionCompleted)
{
return true;
}
}
}
}
}
}
StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
if (frame)
{
ExecutionContext exe_ctx;
frame->CalculateExecutionContext (exe_ctx);
ExecutionResults result = process->RunThreadPlan (exe_ctx,
call_plan_sp,
options,
error_strm);
if (result == eExecutionCompleted)
{
return true;
}
}
}
}
}
}
return false;
return false;
}
bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) {
@ -226,11 +218,13 @@ bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t
if (thread == NULL || address == NULL)
return false;
const bool stop_other_threads = true;
const bool unwind_on_error = true;
const bool ignore_breakpoints = true;
const bool try_all_threads = true;
const uint32_t timeout_usec = 500000;
EvaluateExpressionOptions options;
options.SetStopOthers(true);
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
@ -238,9 +232,7 @@ bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t
= new ThreadPlanCallFunction (*thread,
*address,
clang_void_ptr_type,
stop_other_threads,
unwind_on_error,
ignore_breakpoints);
options);
lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
if (call_plan_sp)
{
@ -256,11 +248,7 @@ bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t
frame->CalculateExecutionContext (exe_ctx);
ExecutionResults result = process->RunThreadPlan (exe_ctx,
call_plan_sp,
stop_other_threads,
try_all_threads,
unwind_on_error,
ignore_breakpoints,
timeout_usec,
options,
error_strm);
if (result == eExecutionCompleted)
{

View File

@ -4697,11 +4697,7 @@ Process::SettingsTerminate ()
ExecutionResults
Process::RunThreadPlan (ExecutionContext &exe_ctx,
lldb::ThreadPlanSP &thread_plan_sp,
bool stop_others,
bool run_others,
bool unwind_on_error,
bool ignore_breakpoints,
uint32_t timeout_usec,
const EvaluateExpressionOptions &options,
Stream &errors)
{
ExecutionResults return_value = eExecutionSetupError;
@ -4812,6 +4808,17 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
thread->QueueThreadPlan(thread_plan_sp, false); // This used to pass "true" does that make sense?
if (options.GetDebug())
{
// In this case, we aren't actually going to run, we just want to stop right away.
// Flush this thread so we will refetch the stacks and show the correct backtrace.
// FIXME: To make this prettier we should invent some stop reason for this, but that
// is only cosmetic, and this functionality is only of use to lldb developers who can
// live with not pretty...
thread->Flush();
return eExecutionStoppedForDebug;
}
Listener listener("lldb.process.listener.run-thread-plan");
lldb::EventSP event_to_broadcast_sp;
@ -4853,11 +4860,12 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
TimeValue one_thread_timeout = TimeValue::Now();
TimeValue final_timeout = one_thread_timeout;
if (run_others)
uint32_t timeout_usec = options.GetTimeoutUsec();
if (options.GetTryAllThreads())
{
// If we are running all threads then we take half the time to run all threads, bounded by
// .25 sec.
if (timeout_usec == 0)
if (options.GetTimeoutUsec() == 0)
one_thread_timeout.OffsetWithMicroSeconds(default_one_thread_timeout_usec);
else
{
@ -4969,7 +4977,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (before_first_timeout)
{
if (run_others)
if (options.GetTryAllThreads())
timeout_ptr = &one_thread_timeout;
else
{
@ -5085,7 +5093,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (log)
log->Printf ("Process::RunThreadPlan() stopped for breakpoint: %s.", stop_info_sp->GetDescription());
return_value = eExecutionHitBreakpoint;
if (!ignore_breakpoints)
if (!options.DoesIgnoreBreakpoints())
{
event_to_broadcast_sp = event_sp;
}
@ -5094,7 +5102,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
if (!unwind_on_error)
if (!options.DoesUnwindOnError())
event_to_broadcast_sp = event_sp;
return_value = eExecutionInterrupted;
}
@ -5145,7 +5153,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// either exit, or try with all threads running for the same timeout.
if (log) {
if (run_others)
if (options.GetTryAllThreads())
{
uint64_t remaining_time = final_timeout - TimeValue::Now();
if (before_first_timeout)
@ -5228,7 +5236,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
continue;
}
if (!run_others)
if (!options.GetTryAllThreads())
{
if (log)
log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting.");
@ -5301,8 +5309,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// 1) The execution successfully completed
// 2) We hit a breakpoint, and ignore_breakpoints was true
// 3) We got some other error, and discard_on_error was true
bool should_unwind = (return_value == eExecutionInterrupted && unwind_on_error)
|| (return_value == eExecutionHitBreakpoint && ignore_breakpoints);
bool should_unwind = (return_value == eExecutionInterrupted && options.DoesUnwindOnError())
|| (return_value == eExecutionHitBreakpoint && options.DoesIgnoreBreakpoints());
if (return_value == eExecutionCompleted
|| should_unwind)
@ -5422,7 +5430,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (log)
log->PutCString("Process::RunThreadPlan(): execution set up error.");
if (unwind_on_error)
if (options.DoesUnwindOnError())
{
thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
thread_plan_sp->SetPrivate (orig_plan_private);
@ -5446,7 +5454,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->PutCString("Process::RunThreadPlan(): thread plan stopped in mid course");
if (unwind_on_error && thread_plan_sp)
if (options.DoesUnwindOnError() && thread_plan_sp)
{
if (log)
log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause unwind_on_error is set.");
@ -5518,6 +5526,9 @@ Process::ExecutionResultAsCString (ExecutionResults result)
case eExecutionTimedOut:
result_name = "eExecutionTimedOut";
break;
case eExecutionStoppedForDebug:
result_name = "eExecutionStoppedForDebug";
break;
}
return result_name;
}

View File

@ -1419,14 +1419,6 @@ Thread::QueueThreadPlanForStepInRange
}
ThreadPlanSP
Thread::QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans)
{
ThreadPlanSP thread_plan_sp (new ThreadPlanStepOverBreakpoint (*this));
QueueThreadPlan (thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
ThreadPlanSP
Thread::QueueThreadPlanForStepOut
(
@ -1469,25 +1461,6 @@ Thread::QueueThreadPlanForStepThrough (StackID &return_stack_id, bool abort_othe
return thread_plan_sp;
}
ThreadPlanSP
Thread::QueueThreadPlanForCallFunction (bool abort_other_plans,
Address& function,
lldb::addr_t arg,
bool stop_other_threads,
bool unwind_on_error,
bool ignore_breakpoints)
{
ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this,
function,
ClangASTType(),
arg,
stop_other_threads,
unwind_on_error,
ignore_breakpoints));
QueueThreadPlan (thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
ThreadPlanSP
Thread::QueueThreadPlanForRunToAddress (bool abort_other_plans,
Address &target_addr,

View File

@ -55,8 +55,6 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
if (!abi)
return false;
TargetSP target_sp (thread.CalculateTarget());
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
SetBreakpoints();
@ -74,7 +72,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
return false;
}
Module *exe_module = target_sp->GetExecutableModulePointer();
Module *exe_module = GetTarget().GetExecutableModulePointer();
if (exe_module == NULL)
{
@ -107,7 +105,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
}
}
start_load_addr = m_start_addr.GetLoadAddress (target_sp.get());
start_load_addr = m_start_addr.GetLoadAddress (&GetTarget());
// Checkpoint the thread state so we can restore it later.
if (log && log->GetVerbose())
@ -120,7 +118,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
return false;
}
function_load_addr = m_function_addr.GetLoadAddress (target_sp.get());
function_load_addr = m_function_addr.GetLoadAddress (&GetTarget());
return true;
}
@ -129,28 +127,30 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
const Address &function,
const ClangASTType &return_type,
addr_t arg,
bool stop_other_threads,
bool unwind_on_error,
bool ignore_breakpoints,
const EvaluateExpressionOptions &options,
addr_t *this_arg,
addr_t *cmd_arg) :
ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
m_valid (false),
m_stop_other_threads (stop_other_threads),
m_stop_other_threads (options.GetStopOthers()),
m_unwind_on_error (options.DoesUnwindOnError()),
m_ignore_breakpoints (options.DoesIgnoreBreakpoints()),
m_debug_execution (options.GetDebug()),
m_trap_exceptions (options.GetTrapExceptions()),
m_function_addr (function),
m_function_sp (0),
m_return_type (return_type),
m_takedown_done (false),
m_stop_address (LLDB_INVALID_ADDRESS),
m_unwind_on_error (unwind_on_error),
m_ignore_breakpoints (ignore_breakpoints)
m_should_clear_objc_exception_bp(false),
m_should_clear_cxx_exception_bp (false),
m_stop_address (LLDB_INVALID_ADDRESS)
{
lldb::addr_t start_load_addr;
ABI *abi;
lldb::addr_t function_load_addr;
if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr))
return;
if (this_arg && cmd_arg)
{
if (!abi->PrepareTrivialCall (thread,
@ -191,9 +191,7 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
const Address &function,
const ClangASTType &return_type,
bool stop_other_threads,
bool unwind_on_error,
bool ignore_breakpoints,
const EvaluateExpressionOptions &options,
addr_t *arg1_ptr,
addr_t *arg2_ptr,
addr_t *arg3_ptr,
@ -202,14 +200,16 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
addr_t *arg6_ptr) :
ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
m_valid (false),
m_stop_other_threads (stop_other_threads),
m_stop_other_threads (options.GetStopOthers()),
m_unwind_on_error (options.DoesUnwindOnError()),
m_ignore_breakpoints (options.DoesIgnoreBreakpoints()),
m_debug_execution (options.GetDebug()),
m_trap_exceptions (options.GetTrapExceptions()),
m_function_addr (function),
m_function_sp (0),
m_return_type (return_type),
m_takedown_done (false),
m_stop_address (LLDB_INVALID_ADDRESS),
m_unwind_on_error (unwind_on_error),
m_ignore_breakpoints (ignore_breakpoints)
m_stop_address (LLDB_INVALID_ADDRESS)
{
lldb::addr_t start_load_addr;
ABI *abi;
@ -560,25 +560,34 @@ void
ThreadPlanCallFunction::SetBreakpoints ()
{
ProcessSP process_sp (m_thread.CalculateProcess());
if (process_sp)
if (m_trap_exceptions && process_sp)
{
m_cxx_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeC_plus_plus);
m_objc_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeObjC);
if (m_cxx_language_runtime)
{
m_should_clear_cxx_exception_bp = !m_cxx_language_runtime->ExceptionBreakpointsAreSet();
m_cxx_language_runtime->SetExceptionBreakpoints();
}
if (m_objc_language_runtime)
{
m_should_clear_objc_exception_bp = !m_objc_language_runtime->ExceptionBreakpointsAreSet();
m_objc_language_runtime->SetExceptionBreakpoints();
}
}
}
void
ThreadPlanCallFunction::ClearBreakpoints ()
{
if (m_cxx_language_runtime)
m_cxx_language_runtime->ClearExceptionBreakpoints();
if (m_objc_language_runtime)
m_objc_language_runtime->ClearExceptionBreakpoints();
if (m_trap_exceptions)
{
if (m_cxx_language_runtime && m_should_clear_cxx_exception_bp)
m_cxx_language_runtime->ClearExceptionBreakpoints();
if (m_objc_language_runtime && m_should_clear_objc_exception_bp)
m_objc_language_runtime->ClearExceptionBreakpoints();
}
}
bool
@ -586,21 +595,24 @@ ThreadPlanCallFunction::BreakpointsExplainStop()
{
StopInfoSP stop_info_sp = GetPrivateStopInfo ();
if ((m_cxx_language_runtime &&
m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
||(m_objc_language_runtime &&
m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)))
if (m_trap_exceptions)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
log->Printf ("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an exception breakpoint, setting plan complete.");
SetPlanComplete(false);
// If the user has set the ObjC language breakpoint, it would normally get priority over our internal
// catcher breakpoint, but in this case we can't let that happen, so force the ShouldStop here.
stop_info_sp->OverrideShouldStop (true);
return true;
if ((m_cxx_language_runtime &&
m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
||(m_objc_language_runtime &&
m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)))
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
log->Printf ("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an exception breakpoint, setting plan complete.");
SetPlanComplete(false);
// If the user has set the ObjC language breakpoint, it would normally get priority over our internal
// catcher breakpoint, but in this case we can't let that happen, so force the ShouldStop here.
stop_info_sp->OverrideShouldStop (true);
return true;
}
}
return false;

View File

@ -39,13 +39,11 @@ using namespace lldb_private;
ThreadPlanCallUserExpression::ThreadPlanCallUserExpression (Thread &thread,
Address &function,
lldb::addr_t arg,
bool stop_other_threads,
bool unwind_on_error,
bool ignore_breakpoints,
const EvaluateExpressionOptions &options,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg,
ClangUserExpression::ClangUserExpressionSP &user_expression_sp) :
ThreadPlanCallFunction (thread, function, ClangASTType(), arg, stop_other_threads, unwind_on_error, ignore_breakpoints, this_arg, cmd_arg),
ThreadPlanCallFunction (thread, function, ClangASTType(), arg, options, this_arg, cmd_arg),
m_user_expression_sp (user_expression_sp)
{
// User expressions are generally "User generated" so we should set them up to stop when done.

View File

@ -98,6 +98,17 @@ class ExprCommandWithThrowTestCase(TestBase):
self.assertTrue (value.IsValid() and value.GetError().Success() == False)
self.check_after_call()
# Now turn off exception trapping, and call a function that catches the exceptions,
# and make sure the function actually completes, and we get the right value:
options.SetTrapExceptions(False)
value = frame.EvaluateExpression ("[my_class iCatchMyself]", options)
self.assertTrue (value.IsValid())
self.assertTrue (value.GetError().Success() == True)
self.assertTrue (value.GetValueAsUnsigned() == 57)
self.check_after_call()
options.SetTrapExceptions(True)
# Now set this unwind on error to false, and make sure that we stop where the exception was thrown
options.SetUnwindOnError(False)
value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)

View File

@ -4,6 +4,7 @@
{
}
- (int) callMeIThrow;
- (int) iCatchMyself;
@end
@implementation MyClass
@ -16,6 +17,20 @@
@throw e;
return 56;
}
- (int) iCatchMyself
{
int return_value = 55;
@try
{
return_value = [self callMeIThrow];
}
@catch (NSException *e)
{
return_value = 57;
}
return return_value;
}
@end
int
@ -26,7 +41,7 @@ main ()
NSLog (@"I am about to throw.");
return_value = [my_class callMeIThrow];
return_value = [my_class iCatchMyself];
return return_value;
}