[Lldb-commits] [lldb] r172503 - in /lldb/trunk: include/lldb/ include/lldb/API/ include/lldb/Expression/ include/lldb/Target/ scripts/Python/interface/ source/API/ source/Commands/ source/Expression/ source/Interpreter/ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/ source/Plugins/Process/Utility/ source/Target/ test/expression_command/test/

Jim Ingham jingham at apple.com
Mon Jan 14 18:47:49 PST 2013


Author: jingham
Date: Mon Jan 14 20:47:48 2013
New Revision: 172503

URL: http://llvm.org/viewvc/llvm-project?rev=172503&view=rev
Log:
Separated the "expr --unwind-on-error" behavior into two parts, actual errors (i.e. crashes) which continue to be
controlled by the --unwind-on-error flag, and --ignore-breakpoint which separately controls behavior when a called
function hits a breakpoint.  For breakpoints, we don't unwind, we either stop, or ignore the breakpoint, which makes
more sense.  
Also make both these behaviors globally settable through "settings set".
Also handle the case where a breakpoint command calls code that ends up re-hitting the breakpoint.  We were recursing
and crashing.  Now we just stop without calling the second command.

<rdar://problem/12986644>
<rdar://problem/9119325>

Modified:
    lldb/trunk/include/lldb/API/SBExpressionOptions.h
    lldb/trunk/include/lldb/Expression/ClangFunction.h
    lldb/trunk/include/lldb/Expression/ClangUserExpression.h
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/include/lldb/Target/Target.h
    lldb/trunk/include/lldb/Target/Thread.h
    lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h
    lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h
    lldb/trunk/include/lldb/lldb-private-enumerations.h
    lldb/trunk/scripts/Python/interface/SBExpressionOptions.i
    lldb/trunk/source/API/SBExpressionOptions.cpp
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Commands/CommandObjectExpression.h
    lldb/trunk/source/Expression/ClangFunction.cpp
    lldb/trunk/source/Expression/ClangUserExpression.cpp
    lldb/trunk/source/Interpreter/CommandInterpreter.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
    lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
    lldb/trunk/source/Target/Process.cpp
    lldb/trunk/source/Target/StopInfo.cpp
    lldb/trunk/source/Target/Target.cpp
    lldb/trunk/source/Target/Thread.cpp
    lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
    lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp
    lldb/trunk/test/expression_command/test/TestExprs.py
    lldb/trunk/test/expression_command/test/main.cpp

Modified: lldb/trunk/include/lldb/API/SBExpressionOptions.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBExpressionOptions.h?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBExpressionOptions.h (original)
+++ lldb/trunk/include/lldb/API/SBExpressionOptions.h Mon Jan 14 20:47:48 2013
@@ -42,6 +42,12 @@
     void
     SetUnwindOnError (bool unwind = false);
     
+    bool
+    GetIgnoreBreakpoints () const;
+    
+    void
+    SetIgnoreBreakpoints (bool ignore = false);
+    
     lldb::DynamicValueType
     GetFetchDynamicValue () const;
     

Modified: lldb/trunk/include/lldb/Expression/ClangFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangFunction.h?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangFunction.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangFunction.h Mon Jan 14 20:47:48 2013
@@ -246,7 +246,7 @@
     ///     If the timeout expires, true if other threads should run.  If
     ///     the function may try to take locks, this is useful.
     /// 
-    /// @param[in] discard_on_error
+    /// @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.
@@ -272,7 +272,8 @@
                      lldb::addr_t &void_arg, 
                      bool stop_others, 
                      bool try_all_threads,
-                     bool discard_on_error,
+                     bool unwind_on_error,
+                     bool ignore_breakpoints,
                      uint32_t timeout_usec,
                      Stream &errors,
                      lldb::addr_t* this_arg = 0);
@@ -404,7 +405,8 @@
                     bool stop_others, 
                     uint32_t timeout_usec,
                     bool try_all_threads,
-                    bool discard_on_error, 
+                    bool unwind_on_error,
+                    bool ignore_breakpoints,
                     Value &results);
     
     //------------------------------------------------------------------
@@ -426,9 +428,12 @@
     /// @param[in] stop_others
     ///     True if other threads should pause during execution.
     ///
-    /// @param[in] discard_on_error
+    /// @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' 
@@ -447,7 +452,8 @@
                                  lldb::addr_t &args_addr_ref, 
                                  Stream &errors, 
                                  bool stop_others, 
-                                 bool discard_on_error,
+                                 bool unwind_on_error,
+                                 bool ignore_breakpoints,
                                  lldb::addr_t *this_arg = 0,
                                  lldb::addr_t *cmd_arg = 0);
     
@@ -470,7 +476,7 @@
     /// @param[in] stop_others
     ///     True if other threads should pause during execution.
     ///
-    /// @param[in] discard_on_error
+    /// @param[in] unwind_on_error
     ///     True if the thread plan may simply be discarded if an error occurs.
     ///
     /// @return
@@ -481,14 +487,16 @@
                                  lldb::addr_t &args_addr_ref, 
                                  Stream &errors, 
                                  bool stop_others, 
-                                 bool discard_on_error = true)
+                                 bool unwind_on_error = true,
+                                 bool ignore_breakpoints = true)
     {
         return ClangFunction::GetThreadPlanToCallFunction (exe_ctx, 
                                                            m_jit_start_addr, 
                                                            args_addr_ref, 
                                                            errors, 
                                                            stop_others, 
-                                                           discard_on_error);
+                                                           unwind_on_error,
+                                                           ignore_breakpoints);
     }
     
     //------------------------------------------------------------------

Modified: lldb/trunk/include/lldb/Expression/ClangUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangUserExpression.h?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangUserExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangUserExpression.h Mon Jan 14 20:47:48 2013
@@ -117,11 +117,14 @@
     ///     The execution context to use when looking up entities that
     ///     are needed for parsing (locations of variables, etc.)
     ///
-    /// @param[in] discard_on_error
+    /// @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] ignore_breakpoints
+    ///     If true, ignore breakpoints while executing the expression.
+    ///
     /// @param[in] shared_ptr_to_me
     ///     This is a shared pointer to this ClangUserExpression.  This is
     ///     needed because Execute can push a thread plan that will hold onto
@@ -150,7 +153,8 @@
     ExecutionResults
     Execute (Stream &error_stream,
              ExecutionContext &exe_ctx,
-             bool discard_on_error,
+             bool unwind_on_error,
+             bool ignore_breakpoints,
              ClangUserExpressionSP &shared_ptr_to_me,
              lldb::ClangExpressionVariableSP &result,
              bool try_all_threads,
@@ -305,10 +309,13 @@
     ///     the expression.  Currently restricted to those languages 
     ///     supported by Clang.
     ///
-    /// @param[in] discard_on_error
+    /// @param[in] unwind_on_error
     ///     True if the thread's state should be restored in the case 
     ///     of an error.
     ///
+    /// @param[in] ignore_breakpoints
+    ///     If true, ignore breakpoints while executing the expression.
+    ///
     /// @param[in] result_type
     ///     If not eResultTypeAny, the type of the desired result.  Will
     ///     result in parse errors if impossible.
@@ -341,7 +348,8 @@
               lldb_private::ExecutionPolicy execution_policy,
               lldb::LanguageType language,
               ResultType desired_type,
-              bool discard_on_error,
+              bool unwind_on_error,
+              bool ignore_breakpoints,
               const char *expr_cstr,
               const char *expr_prefix,
               lldb::ValueObjectSP &result_valobj_sp,
@@ -353,7 +361,8 @@
                        lldb_private::ExecutionPolicy execution_policy,
                        lldb::LanguageType language,
                        ResultType desired_type,
-                       bool discard_on_error,
+                       bool unwind_on_error,
+                       bool ignore_breakpoints,
                        const char *expr_cstr,
                        const char *expr_prefix,
                        lldb::ValueObjectSP &result_valobj_sp,

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Mon Jan 14 20:47:48 2013
@@ -73,6 +73,18 @@
 
     void
     SetPythonOSPluginPath (const FileSpec &file);
+    
+    bool
+    GetIgnoreBreakpointsInExpressions () const;
+    
+    void
+    SetIgnoreBreakpointsInExpressions (bool ignore);
+
+    bool
+    GetUnwindOnErrorInExpressions () const;
+    
+    void
+    SetUnwindOnErrorInExpressions (bool ignore);
 };
 
 typedef STD_SHARED_PTR(ProcessProperties) ProcessPropertiesSP;
@@ -2414,7 +2426,8 @@
                     lldb::ThreadPlanSP &thread_plan_sp,
                     bool stop_others,
                     bool run_others,
-                    bool discard_on_error,
+                    bool unwind_on_error,
+                    bool ignore_breakpoints,
                     uint32_t timeout_usec,
                     Stream &errors);
 

Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Mon Jan 14 20:47:48 2013
@@ -151,6 +151,7 @@
         m_execution_policy(eExecutionPolicyOnlyWhenNeeded),
         m_coerce_to_id(false),
         m_unwind_on_error(true),
+        m_ignore_breakpoints (false),
         m_keep_in_memory(false),
         m_run_others(true),
         m_use_dynamic(lldb::eNoDynamicValues),
@@ -197,6 +198,19 @@
     }
     
     bool
+    DoesIgnoreBreakpoints () const
+    {
+        return m_ignore_breakpoints;
+    }
+    
+    EvaluateExpressionOptions&
+    SetIgnoreBreakpoints (bool ignore = false)
+    {
+        m_ignore_breakpoints = ignore;
+        return *this;
+    }
+    
+    bool
     DoesKeepInMemory () const
     {
         return m_keep_in_memory;
@@ -252,6 +266,7 @@
     ExecutionPolicy m_execution_policy;
     bool m_coerce_to_id;
     bool m_unwind_on_error;
+    bool m_ignore_breakpoints;
     bool m_keep_in_memory;
     bool m_run_others;
     lldb::DynamicValueType m_use_dynamic;

Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Mon Jan 14 20:47:48 2013
@@ -648,7 +648,8 @@
                                     Address& function,
                                     lldb::addr_t arg,
                                     bool stop_other_threads,
-                                    bool discard_on_error = false);
+                                    bool unwind_on_error = false,
+                                    bool ignore_breakpoints = true);
                                             
     //------------------------------------------------------------------
     // Thread Plan accessors:

Modified: lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h Mon Jan 14 20:47:48 2013
@@ -31,7 +31,8 @@
                             const ClangASTType &return_type,
                             lldb::addr_t arg,
                             bool stop_other_threads,
-                            bool discard_on_error = true,
+                            bool unwind_on_error = true,
+                            bool ignore_breakpoints = false,
                             lldb::addr_t *this_arg = 0,
                             lldb::addr_t *cmd_arg = 0);
 
@@ -39,7 +40,8 @@
                             Address &function,
                             const ClangASTType &return_type,
                             bool stop_other_threads,
-                            bool discard_on_error,
+                            bool unwind_on_error,
+                            bool ignore_breakpoints,
                             lldb::addr_t *arg1_ptr = NULL,
                             lldb::addr_t *arg2_ptr = NULL,
                             lldb::addr_t *arg3_ptr = NULL,
@@ -170,7 +172,8 @@
     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.
     lldb::addr_t                                    m_stop_address;     // This is the address we stopped at.  Also set in DoTakedown;
-    bool                                            m_discard_on_error;
+    bool                                            m_unwind_on_error;
+    bool                                            m_ignore_breakpoints;
 
     DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction);
 };

Modified: lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h Mon Jan 14 20:47:48 2013
@@ -29,7 +29,8 @@
                                   Address &function,
                                   lldb::addr_t arg,
                                   bool stop_other_threads,
-                                  bool discard_on_error,
+                                  bool unwind_on_error,
+                                  bool ignore_breakpoints,
                                   lldb::addr_t *this_arg,
                                   lldb::addr_t *cmd_arg,
                                   ClangUserExpression::ClangUserExpressionSP &user_expression_sp);

Modified: lldb/trunk/include/lldb/lldb-private-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-enumerations.h?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-private-enumerations.h Mon Jan 14 20:47:48 2013
@@ -131,6 +131,7 @@
     eExecutionCompleted,
     eExecutionDiscarded,
     eExecutionInterrupted,
+    eExecutionHitBreakpoint,
     eExecutionTimedOut
 } ExecutionResults;
 

Modified: lldb/trunk/scripts/Python/interface/SBExpressionOptions.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBExpressionOptions.i?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/interface/SBExpressionOptions.i (original)
+++ lldb/trunk/scripts/Python/interface/SBExpressionOptions.i Mon Jan 14 20:47:48 2013
@@ -41,6 +41,14 @@
     void
     SetUnwindOnError (bool unwind = false);
     
+    bool
+    GetIgnoreBreakpoints () const;
+    
+    %feature("docstring", "Sets whether to ignore breakpoint hits while running expressions.") SetUnwindOnError;
+    
+    void
+    SetIgnoreBreakpoints (bool ignore = false);
+    
     lldb::DynamicValueType
     GetFetchDynamicValue () const;
     

Modified: lldb/trunk/source/API/SBExpressionOptions.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBExpressionOptions.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/API/SBExpressionOptions.cpp (original)
+++ lldb/trunk/source/API/SBExpressionOptions.cpp Mon Jan 14 20:47:48 2013
@@ -65,6 +65,18 @@
     m_opaque_ap->SetUnwindOnError (unwind);
 }
 
+bool
+SBExpressionOptions::GetIgnoreBreakpoints () const
+{
+    return m_opaque_ap->DoesIgnoreBreakpoints ();
+}
+
+void
+SBExpressionOptions::SetIgnoreBreakpoints (bool ignore)
+{
+    m_opaque_ap->SetIgnoreBreakpoints (ignore);
+}
+
 lldb::DynamicValueType
 SBExpressionOptions::GetFetchDynamicValue () const
 {

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Mon Jan 14 20:47:48 2013
@@ -53,6 +53,7 @@
 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, "ignore-breakpoints", 'i', required_argument, NULL, 0, eArgTypeBoolean,    "Ignore breakpoint hits while running expressions"},
     { 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."},
 };
@@ -94,6 +95,16 @@
         }
         break;
         
+    case 'i':
+        {
+            bool success;
+            bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
+            if (success)
+                ignore_breakpoints = tmp_value;
+            else
+                error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
+            break;
+        }
     case 't':
         {
             bool success;
@@ -109,8 +120,10 @@
     case 'u':
         {
             bool success;
-            unwind_on_error = Args::StringToBoolean(option_arg, true, &success);
-            if (!success)
+            bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
+            if (success)
+                unwind_on_error = tmp_value;
+            else
                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
             break;
         }
@@ -125,7 +138,18 @@
 void
 CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter)
 {
-    unwind_on_error = true;
+    Process *process = interpreter.GetExecutionContext().GetProcessPtr();
+    if (process != NULL)
+    {
+        ignore_breakpoints = process->GetIgnoreBreakpointsInExpressions();
+        unwind_on_error    = process->GetUnwindOnErrorInExpressions();
+    }
+    else
+    {
+        ignore_breakpoints = false;
+        unwind_on_error = true;
+    }
+    
     show_summary = true;
     try_all_threads = true;
     timeout = 0;
@@ -306,6 +330,7 @@
         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)
@@ -316,7 +341,8 @@
                                                   result_valobj_sp,
                                                   options);
         
-        if (exe_results == eExecutionInterrupted && !m_command_options.unwind_on_error)
+        if ((exe_results == eExecutionInterrupted && !m_command_options.unwind_on_error)
+            ||(exe_results == eExecutionHitBreakpoint && !m_command_options.ignore_breakpoints))
         {
             uint32_t start_frame = 0;
             uint32_t num_frames = 1;

Modified: lldb/trunk/source/Commands/CommandObjectExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.h?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.h (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.h Mon Jan 14 20:47:48 2013
@@ -52,6 +52,7 @@
 
         static OptionDefinition g_option_table[];
         bool        unwind_on_error;
+        bool        ignore_breakpoints;
         bool        show_types;
         bool        show_summary;
         uint32_t    timeout;

Modified: lldb/trunk/source/Expression/ClangFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangFunction.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangFunction.cpp Mon Jan 14 20:47:48 2013
@@ -402,7 +402,8 @@
                                             lldb::addr_t &args_addr, 
                                             Stream &errors, 
                                             bool stop_others, 
-                                            bool discard_on_error, 
+                                            bool unwind_on_error,
+                                            bool ignore_breakpoints,
                                             lldb::addr_t *this_arg,
                                             lldb::addr_t *cmd_arg)
 {
@@ -422,7 +423,8 @@
                                                        ClangASTType(),
                                                        args_addr,
                                                        stop_others, 
-                                                       discard_on_error,
+                                                       unwind_on_error,
+                                                       ignore_breakpoints,
                                                        this_arg,
                                                        cmd_arg);
     new_plan->SetIsMasterPlan(true);
@@ -479,8 +481,10 @@
 ClangFunction::ExecuteFunction(ExecutionContext &exe_ctx, Stream &errors, bool stop_others, Value &results)
 {
     const bool try_all_threads = false;
-    const bool discard_on_error = true;
-    return ExecuteFunction (exe_ctx, NULL, errors, stop_others, 0UL, try_all_threads, discard_on_error, results);
+    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
@@ -492,9 +496,10 @@
         Value &results)
 {
     const bool stop_others = true;
-    const bool discard_on_error = 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, discard_on_error, results);
+                            try_all_threads, unwind_on_error, ignore_breakpoints, results);
 }
 
 // This is the static function
@@ -505,7 +510,8 @@
         lldb::addr_t &void_arg,
         bool stop_others,
         bool try_all_threads,
-        bool discard_on_error,
+        bool unwind_on_error,
+        bool ignore_breakpoints,
         uint32_t timeout_usec,
         Stream &errors,
         lldb::addr_t *this_arg)
@@ -515,7 +521,8 @@
                                                                                  void_arg, 
                                                                                  errors, 
                                                                                  stop_others, 
-                                                                                 discard_on_error, 
+                                                                                 unwind_on_error,
+                                                                                 ignore_breakpoints,
                                                                                  this_arg));
     if (!call_plan_sp)
         return eExecutionSetupError;
@@ -528,7 +535,8 @@
     ExecutionResults results = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, call_plan_sp,
                                                                       stop_others, 
                                                                       try_all_threads, 
-                                                                      discard_on_error,
+                                                                      unwind_on_error,
+                                                                      ignore_breakpoints,
                                                                       timeout_usec,
                                                                       errors);
     
@@ -546,7 +554,8 @@
         bool stop_others, 
         uint32_t timeout_usec, 
         bool try_all_threads,
-        bool discard_on_error, 
+        bool unwind_on_error,
+        bool ignore_breakpoints,
         Value &results)
 {
     using namespace clang;
@@ -573,7 +582,8 @@
                                                    args_addr, 
                                                    stop_others, 
                                                    try_all_threads, 
-                                                   discard_on_error, 
+                                                   unwind_on_error,
+                                                   ignore_breakpoints,
                                                    timeout_usec, 
                                                    errors);
 

Modified: lldb/trunk/source/Expression/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangUserExpression.cpp Mon Jan 14 20:47:48 2013
@@ -537,12 +537,16 @@
     // 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,
-                                                       true,
-                                                       true, 
+                                                       stop_others,
+                                                       unwind_on_error,
+                                                       ignore_breakpoints,
                                                        (m_needs_object_ptr ? &object_ptr : NULL),
                                                        (m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
 }
@@ -593,7 +597,8 @@
 ExecutionResults
 ClangUserExpression::Execute (Stream &error_stream,
                               ExecutionContext &exe_ctx,
-                              bool discard_on_error,
+                              bool unwind_on_error,
+                              bool ignore_breakpoints,
                               ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
                               lldb::ClangExpressionVariableSP &result,
                               bool run_others,
@@ -624,7 +629,8 @@
                                                                           wrapper_address, 
                                                                           struct_address, 
                                                                           stop_others, 
-                                                                          discard_on_error, 
+                                                                          unwind_on_error,
+                                                                          ignore_breakpoints,
                                                                           (m_needs_object_ptr ? &object_ptr : NULL),
                                                                           ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
                                                                           shared_ptr_to_me));
@@ -644,7 +650,8 @@
                                                                                    call_plan_sp, 
                                                                                    stop_others, 
                                                                                    try_all_threads, 
-                                                                                   discard_on_error,
+                                                                                   unwind_on_error,
+                                                                                   ignore_breakpoints,
                                                                                    timeout_usec, 
                                                                                    error_stream);
         
@@ -654,7 +661,7 @@
         if (log)
             log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
 
-        if (execution_result == eExecutionInterrupted)
+        if (execution_result == eExecutionInterrupted || execution_result == eExecutionHitBreakpoint)
         {
             const char *error_desc = NULL;
             
@@ -669,7 +676,8 @@
             else
                 error_stream.Printf ("Execution was interrupted.");
                 
-            if (discard_on_error)
+            if ((execution_result == eExecutionInterrupted && unwind_on_error)
+                || (execution_result == eExecutionHitBreakpoint && ignore_breakpoints))
                 error_stream.Printf ("\nThe process has been returned to the state before execution.");
             else
                 error_stream.Printf ("\nThe process has been left at the point where it was interrupted.");
@@ -702,7 +710,8 @@
                                lldb_private::ExecutionPolicy execution_policy,
                                lldb::LanguageType language,
                                ResultType desired_type,
-                               bool discard_on_error,
+                               bool unwind_on_error,
+                               bool ignore_breakpoints,
                                const char *expr_cstr,
                                const char *expr_prefix,
                                lldb::ValueObjectSP &result_valobj_sp,
@@ -714,7 +723,8 @@
                               execution_policy,
                               language,
                               desired_type,
-                              discard_on_error,
+                              unwind_on_error,
+                              ignore_breakpoints,
                               expr_cstr,
                               expr_prefix,
                               result_valobj_sp,
@@ -728,7 +738,8 @@
                                         lldb_private::ExecutionPolicy execution_policy,
                                         lldb::LanguageType language,
                                         ResultType desired_type,
-                                        bool discard_on_error,
+                                        bool unwind_on_error,
+                                        bool ignore_breakpoints,
                                         const char *expr_cstr,
                                         const char *expr_prefix,
                                         lldb::ValueObjectSP &result_valobj_sp,
@@ -807,7 +818,8 @@
 
             execution_results = user_expression_sp->Execute (error_stream, 
                                                              exe_ctx, 
-                                                             discard_on_error,
+                                                             unwind_on_error,
+                                                             ignore_breakpoints,
                                                              user_expression_sp, 
                                                              expr_result,
                                                              run_others,

Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Mon Jan 14 20:47:48 2013
@@ -1320,6 +1320,7 @@
                     EvaluateExpressionOptions options;
                     options.SetCoerceToId(false)
                     .SetUnwindOnError(true)
+                    .SetIgnoreBreakpoints(true)
                     .SetKeepInMemory(false)
                     .SetRunOthers(true)
                     .SetTimeoutUsec(0);
@@ -1375,6 +1376,9 @@
                                 case eExecutionInterrupted:
                                     error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
                                     break;
+                                case eExecutionHitBreakpoint:
+                                    error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
+                                    break;
                                 case eExecutionTimedOut:
                                     error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
                                     break;

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp Mon Jan 14 20:47:48 2013
@@ -134,9 +134,10 @@
     lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS;
     func.InsertFunction(exe_ctx, wrapper_struct_addr, error_stream);
 
-    bool unwind_on_error = true;
-    bool try_all_threads = true;
-    bool stop_others = true;
+    const bool unwind_on_error = true;
+    const bool try_all_threads = true;
+    const bool stop_others = true;
+    const bool ignore_breakpoints = true;
     
     ExecutionResults results = func.ExecuteFunction (exe_ctx, 
                                                      &wrapper_struct_addr, 
@@ -144,7 +145,8 @@
                                                      stop_others, 
                                                      0 /* no timeout */,
                                                      try_all_threads, 
-                                                     unwind_on_error, 
+                                                     unwind_on_error,
+                                                     ignore_breakpoints,
                                                      ret);
     if (results != eExecutionCompleted)
     {

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Mon Jan 14 20:47:48 2013
@@ -220,9 +220,10 @@
     if (!m_get_class_name_function->WriteFunctionArguments (exe_ctx, m_get_class_name_args, find_class_name_address, dispatch_values, errors))
         return false;
     
-    bool stop_others = true;
-    bool try_all_threads = true;
-    bool unwind_on_error = true;
+    const bool stop_others = true;
+    const bool try_all_threads = true;
+    const bool unwind_on_error = true;
+    const bool ignore_breakpoints = true;
     
     ExecutionResults results = m_get_class_name_function->ExecuteFunction (exe_ctx, 
                                                      &m_get_class_name_args, 
@@ -230,7 +231,8 @@
                                                      stop_others, 
                                                      100000, 
                                                      try_all_threads, 
-                                                     unwind_on_error, 
+                                                     unwind_on_error,
+                                                     ignore_breakpoints,
                                                      void_ptr_value);
                                                      
     if (results != eExecutionCompleted)

Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp Mon Jan 14 20:47:48 2013
@@ -84,8 +84,15 @@
         }
         m_impl_function = m_trampoline_handler->GetLookupImplementationWrapperFunction();
         ExecutionContext exc_ctx;
+        const bool unwind_on_error = true;
+        const bool ignore_breakpoints = true;
         m_thread.CalculateExecutionContext(exc_ctx);
-        m_func_sp.reset(m_impl_function->GetThreadPlanToCallFunction (exc_ctx, m_args_addr, errors, m_stop_others));
+        m_func_sp.reset(m_impl_function->GetThreadPlanToCallFunction (exc_ctx,
+                                                                      m_args_addr,
+                                                                      errors,
+                                                                      m_stop_others,
+                                                                      unwind_on_error,
+                                                                      ignore_breakpoints));
         m_func_sp->SetOkayToDiscard(true);
         m_thread.QueueThreadPlan (m_func_sp, false);
     }

Modified: lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp Mon Jan 14 20:47:48 2013
@@ -48,7 +48,8 @@
             const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
             const bool use_inline_block_range = false;
             const bool stop_other_threads = true;
-            const bool discard_on_error = true;
+            const bool unwind_on_error = true;
+            const bool ignore_breakpoints = true;
             const bool try_all_threads = true;
             const uint32_t timeout_usec = 500000;
 
@@ -80,7 +81,8 @@
                                                 mmap_range.GetBaseAddress(),
                                                 ClangASTType (clang_ast_context->getASTContext(), clang_void_ptr_type),
                                                 stop_other_threads,
-                                                discard_on_error,
+                                                unwind_on_error,
+                                                ignore_breakpoints,
                                                 &addr,
                                                 &length,
                                                 &prot_arg,
@@ -104,7 +106,8 @@
                                                                           call_plan_sp,        
                                                                           stop_other_threads,
                                                                           try_all_threads,
-                                                                          discard_on_error,
+                                                                          unwind_on_error,
+                                                                          ignore_breakpoints,
                                                                           timeout_usec,
                                                                           error_strm);
                         if (result == eExecutionCompleted)
@@ -152,7 +155,8 @@
            const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
            const bool use_inline_block_range = false;
            const bool stop_other_threads = true;
-           const bool discard_on_error = true;
+           const bool unwind_on_error = true;
+           const bool ignore_breakpoints = true;
            const bool try_all_threads = true;
            const uint32_t timeout_usec = 500000;
            
@@ -163,7 +167,8 @@
                                                                             munmap_range.GetBaseAddress(),
                                                                             ClangASTType(),
                                                                             stop_other_threads,
-                                                                            discard_on_error,
+                                                                            unwind_on_error,
+                                                                            ignore_breakpoints,
                                                                             &addr,
                                                                             &length));
                if (call_plan_sp)
@@ -182,7 +187,8 @@
                                                                          call_plan_sp,        
                                                                          stop_other_threads,
                                                                          try_all_threads,
-                                                                         discard_on_error,
+                                                                         unwind_on_error,
+                                                                         ignore_breakpoints,
                                                                          timeout_usec,
                                                                          error_strm);
                        if (result == eExecutionCompleted)

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Mon Jan 14 20:47:48 2013
@@ -97,6 +97,8 @@
     { "disable-memory-cache" , OptionValue::eTypeBoolean, false, DISABLE_MEM_CACHE_DEFAULT, NULL, NULL, "Disable reading and caching of memory in fixed-size units." },
     { "extra-startup-command", OptionValue::eTypeArray  , false, OptionValue::eTypeString, NULL, NULL, "A list containing extra commands understood by the particular process plugin used.  "
                                                                                                        "For instance, to turn on debugserver logging set this to \"QSetLogging:bitmask=LOG_DEFAULT;\"" },
+    { "ignore-breakpoints-in-expressions", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, breakpoints will be ignored during expression evaluation." },
+    { "unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, errors in expression evaluation will unwind the stack back to the state before the call." },
     { "python-os-plugin-path", OptionValue::eTypeFileSpec, false, true, NULL, NULL, "A path to a python OS plug-in module file that contains a OperatingSystemPlugIn class." },
     {  NULL                  , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL  }
 };
@@ -104,6 +106,8 @@
 enum {
     ePropertyDisableMemCache,
     ePropertyExtraStartCommand,
+    ePropertyIgnoreBreakpointsInExpressions,
+    ePropertyUnwindOnErrorInExpressions,
     ePropertyPythonOSPluginPath
 };
 
@@ -164,6 +168,35 @@
     m_collection_sp->SetPropertyAtIndexAsFileSpec(NULL, idx, file);
 }
 
+
+bool
+ProcessProperties::GetIgnoreBreakpointsInExpressions () const
+{
+    const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions;
+    return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+    
+void
+ProcessProperties::SetIgnoreBreakpointsInExpressions (bool ignore)
+{
+    const uint32_t idx = ePropertyIgnoreBreakpointsInExpressions;
+    m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, ignore);
+}
+
+bool
+ProcessProperties::GetUnwindOnErrorInExpressions () const
+{
+    const uint32_t idx = ePropertyUnwindOnErrorInExpressions;
+    return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+    
+void
+ProcessProperties::SetUnwindOnErrorInExpressions (bool ignore)
+{
+    const uint32_t idx = ePropertyUnwindOnErrorInExpressions;
+    m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, ignore);
+}
+
 void
 ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const
 {
@@ -1668,7 +1701,8 @@
             {
                 ExecutionContext exe_ctx;
                 frame_sp->CalculateExecutionContext (exe_ctx);
-                bool unwind_on_error = true;
+                const bool unwind_on_error = true;
+                const bool ignore_breakpoints = true;
                 StreamString expr;
                 expr.Printf("dlopen (\"%s\", 2)", path);
                 const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
@@ -1678,6 +1712,7 @@
                                                lldb::eLanguageTypeUnknown,
                                                ClangUserExpression::eResultTypeAny,
                                                unwind_on_error,
+                                               ignore_breakpoints,
                                                expr.GetData(),
                                                prefix,
                                                result_valobj_sp,
@@ -1743,7 +1778,8 @@
                     {
                         ExecutionContext exe_ctx;
                         frame_sp->CalculateExecutionContext (exe_ctx);
-                        bool unwind_on_error = true;
+                        const bool unwind_on_error = true;
+                        const bool ignore_breakpoints = true;
                         StreamString expr;
                         expr.Printf("dlclose ((void *)0x%" PRIx64 ")", image_addr);
                         const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
@@ -1753,6 +1789,7 @@
                                                        lldb::eLanguageTypeUnknown,
                                                        ClangUserExpression::eResultTypeAny,
                                                        unwind_on_error,
+                                                       ignore_breakpoints,
                                                        expr.GetData(),
                                                        prefix,
                                                        result_valobj_sp,
@@ -4293,7 +4330,8 @@
                         lldb::ThreadPlanSP &thread_plan_sp,
                         bool stop_others,
                         bool run_others,
-                        bool discard_on_error,
+                        bool unwind_on_error,
+                        bool ignore_breakpoints,
                         uint32_t timeout_usec,
                         Stream &errors)
 {
@@ -4419,8 +4457,10 @@
         
         bool first_timeout = true;
         bool do_resume = true;
+        bool handle_running_event = true;
         const uint64_t default_one_thread_timeout_usec = 250000;
         uint64_t computed_timeout = 0;
+        bool stopped_by_breakpoint = false;
         
         // This while loop must exit out the bottom, there's cleanup that we need to do when we are done.
         // So don't call return anywhere within it.
@@ -4431,16 +4471,19 @@
             // The only exception is if we get two running events with no intervening
             // stop, which can happen, we will just wait for then next stop event.
             
-            if (do_resume)
+            if (do_resume || handle_running_event)
             {
                 // Do the initial resume and wait for the running event before going further.
         
-                Error resume_error = PrivateResume ();
-                if (!resume_error.Success())
+                if (do_resume)
                 {
-                    errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
-                    return_value = eExecutionSetupError;
-                    break;
+                    Error resume_error = PrivateResume ();
+                    if (!resume_error.Success())
+                    {
+                        errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
+                        return_value = eExecutionSetupError;
+                        break;
+                    }
                 }
         
                 real_timeout = TimeValue::Now();
@@ -4526,6 +4569,7 @@
                 if (log)
                     log->PutCString ("Process::RunThreadPlan(): handled an extra running event.");
                 do_resume = true;
+                handle_running_event = true;
             }
             
             // Now wait for the process to stop again:
@@ -4601,10 +4645,24 @@
                                     }
                                     else
                                     {
-                                        if (log)
-                                            log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
-
-                                        return_value = eExecutionInterrupted;
+                                        // Something restarted the target, so just wait for it to stop for real.
+                                        if (Process::ProcessEventData::GetRestartedFromEvent(event_sp.get()))
+                                        {
+                                            if (log)
+                                                log->PutCString ("Process::RunThreadPlan(): Somebody stopped and then restarted, we'll continue waiting.");
+                                           keep_going = true;
+                                           do_resume = false;
+                                           handle_running_event = true;
+                                        }
+                                        else
+                                        {
+                                            if (log)
+                                                log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
+                                            if (stop_reason == eStopReasonBreakpoint)
+                                                return_value = eExecutionHitBreakpoint;
+                                            else
+                                                return_value = eExecutionInterrupted;
+                                        }
                                     }
                                 }
                             }        
@@ -4619,6 +4677,7 @@
                         case lldb::eStateRunning:
                             do_resume = false;
                             keep_going = true;
+                            handle_running_event = false;
                             break;
 
                         default:
@@ -4815,7 +4874,6 @@
                 }
 
             }
-            
         }  // END WAIT LOOP
         
         // If we had to start up a temporary private state thread to run this thread plan, shut it down now.
@@ -4832,15 +4890,22 @@
 
         }
         
-        // Restore the thread state if we are going to discard the plan execution.
+        // Restore the thread state if we are going to discard the plan execution.  There are three cases where this
+        // could happen:
+        // 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);
         
-        if (return_value == eExecutionCompleted || discard_on_error)
+        if (return_value == eExecutionCompleted
+            || should_unwind)
         {
             thread_plan_sp->RestoreThreadState();
         }
         
         // Now do some processing on the results of the run:
-        if (return_value == eExecutionInterrupted)
+        if (return_value == eExecutionInterrupted || return_value == eExecutionHitBreakpoint)
         {
             if (log)
             {
@@ -4933,7 +4998,7 @@
                     log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData());
             }
             
-            if (discard_on_error && thread_plan_sp)
+            if (should_unwind && thread_plan_sp)
             {
                 if (log)
                     log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.", thread_plan_sp.get());
@@ -4951,7 +5016,7 @@
             if (log)
                 log->PutCString("Process::RunThreadPlan(): execution set up error.");
                 
-            if (discard_on_error && thread_plan_sp)
+            if (unwind_on_error && thread_plan_sp)
             {
                 thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
                 thread_plan_sp->SetPrivate (orig_plan_private);
@@ -4975,10 +5040,10 @@
             {
                 if (log)
                     log->PutCString("Process::RunThreadPlan(): thread plan stopped in mid course");
-                if (discard_on_error && thread_plan_sp)
+                if (unwind_on_error && thread_plan_sp)
                 {
                     if (log)
-                        log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause discard_on_error is set.");
+                        log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause unwind_on_error is set.");
                     thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
                     thread_plan_sp->SetPrivate (orig_plan_private);
                 }
@@ -5037,6 +5102,9 @@
         case eExecutionInterrupted:
             result_name = "eExecutionInterrupted";
             break;
+        case eExecutionHitBreakpoint:
+            result_name = "eExecutionHitBreakpoint";
+            break;
         case eExecutionSetupError:
             result_name = "eExecutionSetupError";
             break;

Modified: lldb/trunk/source/Target/StopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Target/StopInfo.cpp (original)
+++ lldb/trunk/source/Target/StopInfo.cpp Mon Jan 14 20:47:48 2013
@@ -275,6 +275,47 @@
                 m_should_stop = false;
 
                 ExecutionContext exe_ctx (m_thread.GetStackFrameAtIndex(0));
+                Process *process  = exe_ctx.GetProcessPtr();
+                if (process->GetModIDRef().IsLastResumeForUserExpression())
+                {
+                    // If we are in the middle of evaluating an expression, don't run asynchronous breakpoint commands or
+                    // expressions.  That could lead to infinite recursion if the command or condition re-calls the function
+                    // with this breakpoint.
+                    // TODO: We can keep a list of the breakpoints we've seen while running expressions in the nested
+                    // PerformAction calls that can arise when the action runs a function that hits another breakpoint,
+                    // and only stop running commands when we see the same breakpoint hit a second time.
+                    
+                    m_should_stop_is_valid = true;
+                    if (log)
+                        log->Printf ("StopInfoBreakpoint::PerformAction - Hit a breakpoint while running an expression,"
+                                     " not running commands to avoid recursion.");
+                    bool ignoring_breakpoints = process->GetIgnoreBreakpointsInExpressions();
+                    if (ignoring_breakpoints)
+                    {
+                        m_should_stop = false;
+                        // Internal breakpoints will always stop.  
+                        for (size_t j = 0; j < num_owners; j++)
+                        {
+                            lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j);
+                            if (bp_loc_sp->GetBreakpoint().IsInternal())
+                            {
+                                m_should_stop = true;
+                                break;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        m_should_stop = true;
+                    }
+                    if (log)
+                        log->Printf ("StopInfoBreakpoint::PerformAction - in expression, continuing: %s.",
+                                     m_should_stop ? "true" : "false");
+                    process->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf("Warning: hit breakpoint while "
+                                           "running function, skipping commands and conditions to prevent recursion.");
+                    return;
+                }
+                
                 StoppointCallbackContext context (event_ptr, exe_ctx, false);
 
                 for (size_t j = 0; j < num_owners; j++)
@@ -294,13 +335,15 @@
                         
                         ExecutionResults result_code;
                         ValueObjectSP result_value_sp;
-                        const bool discard_on_error = true;
+                        const bool unwind_on_error = true;
+                        const bool ignore_breakpoints = true;
                         Error error;
                         result_code = ClangUserExpression::EvaluateWithError (exe_ctx,
                                                                               eExecutionPolicyOnlyWhenNeeded,
                                                                               lldb::eLanguageTypeUnknown,
                                                                               ClangUserExpression::eResultTypeAny,
-                                                                              discard_on_error,
+                                                                              unwind_on_error,
+                                                                              ignore_breakpoints,
                                                                               bp_loc_sp->GetConditionText(),
                                                                               NULL,
                                                                               result_value_sp,
@@ -575,13 +618,15 @@
                 // constructor errors up to the debugger's Async I/O.
                 ExecutionResults result_code;
                 ValueObjectSP result_value_sp;
-                const bool discard_on_error = true;
+                const bool unwind_on_error = true;
+                const bool ignore_breakpoints = true;
                 Error error;
                 result_code = ClangUserExpression::EvaluateWithError (exe_ctx,
                                                                       eExecutionPolicyOnlyWhenNeeded,
                                                                       lldb::eLanguageTypeUnknown,
                                                                       ClangUserExpression::eResultTypeAny,
-                                                                      discard_on_error,
+                                                                      unwind_on_error,
+                                                                      ignore_breakpoints,
                                                                       wp_sp->GetConditionText(),
                                                                       NULL,
                                                                       result_value_sp,

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Mon Jan 14 20:47:48 2013
@@ -1757,6 +1757,7 @@
                                                            lldb::eLanguageTypeUnknown,
                                                            options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny,
                                                            options.DoesUnwindOnError(),
+                                                           options.DoesIgnoreBreakpoints(),
                                                            expr_cstr, 
                                                            prefix, 
                                                            result_valobj_sp,

Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Mon Jan 14 20:47:48 2013
@@ -1283,9 +1283,16 @@
                                         Address& function,
                                         lldb::addr_t arg,
                                         bool stop_other_threads,
-                                        bool discard_on_error)
+                                        bool unwind_on_error,
+                                        bool ignore_breakpoints)
 {
-    ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this, function, ClangASTType(), arg, stop_other_threads, discard_on_error));
+    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.get();
 }

Modified: lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanCallFunction.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanCallFunction.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanCallFunction.cpp Mon Jan 14 20:47:48 2013
@@ -123,7 +123,8 @@
                                                 const ClangASTType &return_type,
                                                 addr_t arg,
                                                 bool stop_other_threads,
-                                                bool discard_on_error,
+                                                bool unwind_on_error,
+                                                bool ignore_breakpoints,
                                                 addr_t *this_arg,
                                                 addr_t *cmd_arg) :
     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
@@ -134,7 +135,8 @@
     m_return_type (return_type),
     m_takedown_done (false),
     m_stop_address (LLDB_INVALID_ADDRESS),
-    m_discard_on_error (discard_on_error)
+    m_unwind_on_error (unwind_on_error),
+    m_ignore_breakpoints (ignore_breakpoints)
 {
     lldb::addr_t start_load_addr;
     ABI *abi;
@@ -183,7 +185,8 @@
                                                 Address &function,
                                                 const ClangASTType &return_type,
                                                 bool stop_other_threads,
-                                                bool discard_on_error,
+                                                bool unwind_on_error,
+                                                bool ignore_breakpoints,
                                                 addr_t *arg1_ptr,
                                                 addr_t *arg2_ptr,
                                                 addr_t *arg3_ptr,
@@ -198,7 +201,8 @@
     m_return_type (return_type),
     m_takedown_done (false),
     m_stop_address (LLDB_INVALID_ADDRESS),
-    m_discard_on_error (discard_on_error)
+    m_unwind_on_error (unwind_on_error),
+    m_ignore_breakpoints (ignore_breakpoints)
 {
     lldb::addr_t start_load_addr;
     ABI *abi;
@@ -339,7 +343,10 @@
     // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
     // we answer yes.
     if (m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop())
+    {
+        SetPlanComplete();
         return true;
+    }
     
     // Check if the breakpoint is one of ours.
     
@@ -353,7 +360,7 @@
         return true;
     
     // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
-    if (!m_discard_on_error)
+    if (!m_unwind_on_error)
         return false;
             
     // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on.
@@ -385,7 +392,7 @@
                 return false;
         }
         
-        if (m_discard_on_error)
+        if (m_ignore_breakpoints)
         {
             DoTakedown(false);
             return true;
@@ -399,9 +406,10 @@
         // If we want to discard the plan, then we say we explain the stop
         // but if we are going to be discarded, let whoever is above us
         // explain the stop.
+        SetPlanComplete(false);
         if (m_subplan_sp)
         {
-            if (m_discard_on_error)
+            if (m_unwind_on_error)
             {
                 DoTakedown(false);
                 return true;
@@ -417,7 +425,11 @@
 bool
 ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
 {
-    if (IsPlanComplete() || PlanExplainsStop())
+    // We do some computation in PlanExplainsStop that may or may not set the plan as complete.
+    // We need to do that here to make sure our state is correct.
+    PlanExplainsStop();
+    
+    if (IsPlanComplete())
     {
         ReportRegisterState ("Function completed.  Register state was:");
         
@@ -481,10 +493,16 @@
 bool
 ThreadPlanCallFunction::MischiefManaged ()
 {
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+    
+    if (PlanExplainsStop() && !IsPlanComplete())
+    {
+        if (log)
+            log->Printf ("ThreadPlanCallFunction: Got into MischiefManaged, explained stop but was not complete.");
+    }
+    
     if (IsPlanComplete())
     {
-        LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
-
         if (log)
             log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.", this);
 
@@ -527,12 +545,19 @@
 {
     StopInfoSP stop_info_sp = GetPrivateStopReason();
     
-    if (m_cxx_language_runtime &&
-        m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
+    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)))
+    {
+        SetPlanComplete(false);
         return true;
+    }
+    
+    // Finally, if the process is set to ignore breakpoints in function calls,
+    // then we explain all breakpoint stops.
     
-    if (m_objc_language_runtime &&
-        m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
+    if (m_ignore_breakpoints)
         return true;
     
     return false;

Modified: lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp Mon Jan 14 20:47:48 2013
@@ -40,11 +40,12 @@
                                                 Address &function,
                                                 lldb::addr_t arg,
                                                 bool stop_other_threads,
-                                                bool discard_on_error,
+                                                bool unwind_on_error,
+                                                bool ignore_breakpoints,
                                                 lldb::addr_t *this_arg,
                                                 lldb::addr_t *cmd_arg,
                                                 ClangUserExpression::ClangUserExpressionSP &user_expression_sp) :
-    ThreadPlanCallFunction (thread, function, ClangASTType(), arg, stop_other_threads, discard_on_error, this_arg, cmd_arg),
+    ThreadPlanCallFunction (thread, function, ClangASTType(), arg, stop_other_threads, unwind_on_error, ignore_breakpoints, 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.

Modified: lldb/trunk/test/expression_command/test/TestExprs.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/expression_command/test/TestExprs.py?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/test/expression_command/test/TestExprs.py (original)
+++ lldb/trunk/test/expression_command/test/TestExprs.py Mon Jan 14 20:47:48 2013
@@ -157,6 +157,22 @@
             startstr = "'Z'")
         self.DebugSBValue(val)
 
+        callee_break = target.BreakpointCreateByName ("a_function_to_call", None)
+        self.assertTrue(callee_break.GetNumLocations() > 0)
+
+        # Make sure ignoring breakpoints works from the command line:
+        self.expect("expression -i true -- a_function_to_call()",
+                    substrs = ['(int) $', ' 1'])
+        self.assertTrue (callee_break.GetHitCount() == 1)
+
+        # Now try ignoring breakpoints using the SB API's:
+        options = lldb.SBExpressionOptions()
+        options.SetIgnoreBreakpoints(True)
+        value = frame.EvaluateExpression('a_function_to_call()', options)
+        self.assertTrue (value.IsValid())
+        self.assertTrue (value.GetValueAsSigned(0) == 2)
+        self.assertTrue (callee_break.GetHitCount() == 2)
+
     # rdar://problem/8686536
     # CommandInterpreter::HandleCommand is stripping \'s from input for WantsRawCommand commands
     def test_expr_commands_can_handle_quotes(self):
@@ -207,7 +223,6 @@
             substrs = ['(int) $',
                        '6'])
 
-
 if __name__ == '__main__':
     import atexit
     lldb.SBDebugger.Initialize()

Modified: lldb/trunk/test/expression_command/test/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/expression_command/test/main.cpp?rev=172503&r1=172502&r2=172503&view=diff
==============================================================================
--- lldb/trunk/test/expression_command/test/main.cpp (original)
+++ lldb/trunk/test/expression_command/test/main.cpp Mon Jan 14 20:47:48 2013
@@ -1,5 +1,14 @@
 #include <stdio.h>
 
+static int static_value = 0;
+
+int
+a_function_to_call()
+{
+    static_value++;
+    return static_value;
+}
+
 int main (int argc, char const *argv[])
 {
     printf ("Hello world!\n");
@@ -29,5 +38,7 @@
     expression printf ("two: %llu, one: %i\n", 2ull, 1)
     expression random() % 255l
 #endif
+
+    a_function_to_call();
     return 0;
 }





More information about the lldb-commits mailing list