[Lldb-commits] [lldb] r120386 - in /lldb/trunk: include/lldb/Expression/ include/lldb/Target/ lldb.xcodeproj/ source/API/ source/Commands/ source/Expression/ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/ source/Target/

Jim Ingham jingham at apple.com
Mon Nov 29 18:22:11 PST 2010


Author: jingham
Date: Mon Nov 29 20:22:11 2010
New Revision: 120386

URL: http://llvm.org/viewvc/llvm-project?rev=120386&view=rev
Log:
Moved the code in ClangUserExpression that set up & ran the thread plan with timeouts, and restarting with all threads into a utility function in Process.  This required a bunch of renaming. 

Added a ThreadPlanCallUserExpression that differs from ThreadPlanCallFunction in that it holds onto a shared pointer to its ClangUserExpression so that can't go away before the thread plan is done using it.

Fixed the stop message when you hit a breakpoint while running a user expression so it is more obvious what has happened.

Added:
    lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h
    lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp
Modified:
    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/ThreadPlan.h
    lldb/trunk/lldb.xcodeproj/project.pbxproj
    lldb/trunk/source/API/SBFrame.cpp
    lldb/trunk/source/Commands/CommandObjectCall.cpp
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Expression/ClangFunction.cpp
    lldb/trunk/source/Expression/ClangUserExpression.cpp
    lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
    lldb/trunk/source/Target/Process.cpp
    lldb/trunk/source/Target/ThreadPlan.cpp
    lldb/trunk/source/Target/ThreadPlanRunToAddress.cpp
    lldb/trunk/source/Target/ThreadPlanTestCondition.cpp

Modified: lldb/trunk/include/lldb/Expression/ClangFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangFunction.h?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangFunction.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangFunction.h Mon Nov 29 20:22:11 2010
@@ -21,9 +21,7 @@
 #include "lldb/Core/Value.h"
 #include "lldb/Core/ValueObjectList.h"
 #include "lldb/Expression/ClangExpression.h"
-
-// Right now, this is just a toy.  It calls a set function, with fixed
-// values.
+#include "lldb/Target/Process.h"
 
 namespace lldb_private
 {
@@ -68,15 +66,6 @@
 {
     friend class ASTStructExtractor;
 public:
-    enum ExecutionResults
-    {
-        eExecutionSetupError,
-        eExecutionCompleted,
-        eExecutionDiscarded,
-        eExecutionInterrupted,
-        eExecutionTimedOut
-    };
-        
 	//------------------------------------------------------------------
 	/// Constructor
     ///
@@ -275,15 +264,16 @@
     /// @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 discard_on_error,
-                                             uint32_t single_thread_timeout_usec, 
-                                             Stream &errors,
-                                             lldb::addr_t* this_arg = 0);
+    static Process::ExecutionResults 
+    ExecuteFunction (ExecutionContext &exe_ctx, 
+                     lldb::addr_t function_address, 
+                     lldb::addr_t &void_arg, 
+                     bool stop_others, 
+                     bool try_all_threads,
+                     bool discard_on_error,
+                     uint32_t single_thread_timeout_usec, 
+                     Stream &errors,
+                     lldb::addr_t* this_arg = 0);
     
     //------------------------------------------------------------------
     /// Run the function this ClangFunction was created with.
@@ -304,9 +294,10 @@
     /// @return
     ///     Returns one of the ExecutionResults enum indicating function call status.
     //------------------------------------------------------------------
-    ExecutionResults ExecuteFunction(ExecutionContext &exe_ctx, 
-                                     Stream &errors, 
-                                     Value &results);
+    Process::ExecutionResults 
+    ExecuteFunction(ExecutionContext &exe_ctx, 
+                     Stream &errors, 
+                     Value &results);
     
     //------------------------------------------------------------------
     /// Run the function this ClangFunction was created with.
@@ -329,9 +320,10 @@
     /// @return
     ///     Returns one of the ExecutionResults enum indicating function call status.
     //------------------------------------------------------------------
-    ExecutionResults ExecuteFunction(ExecutionContext &exe_ctx, 
-                                     Stream &errors, bool stop_others, 
-                                     Value &results);
+    Process::ExecutionResults 
+    ExecuteFunction(ExecutionContext &exe_ctx, 
+                     Stream &errors, bool stop_others, 
+                     Value &results);
     
     //------------------------------------------------------------------
     /// Run the function this ClangFunction was created with.
@@ -358,11 +350,12 @@
     /// @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);
+    Process::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.
@@ -397,14 +390,15 @@
     /// @return
     ///     Returns one of the ExecutionResults enum indicating function call status.
     //------------------------------------------------------------------
-    ExecutionResults ExecuteFunction(ExecutionContext &exe_ctx, 
-                                     lldb::addr_t *args_addr_ptr, 
-                                     Stream &errors, 
-                                     bool stop_others, 
-                                     uint32_t single_thread_timeout_usec,
-                                     bool try_all_threads,
-                                     bool discard_on_error, 
-                                     Value &results);
+    Process::ExecutionResults 
+    ExecuteFunction(ExecutionContext &exe_ctx, 
+                    lldb::addr_t *args_addr_ptr, 
+                    Stream &errors, 
+                    bool stop_others, 
+                    uint32_t single_thread_timeout_usec,
+                    bool try_all_threads,
+                    bool discard_on_error, 
+                    Value &results);
     
     //------------------------------------------------------------------
     /// [static] Get a thread plan to run a function.

Modified: lldb/trunk/include/lldb/Expression/ClangUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangUserExpression.h?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangUserExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangUserExpression.h Mon Nov 29 20:22:11 2010
@@ -26,6 +26,7 @@
 #include "lldb/Expression/ClangExpression.h"
 #include "lldb/Expression/ClangExpressionVariable.h"
 #include "lldb/Symbol/TaggedASTType.h"
+#include "lldb/Target/Process.h"
 
 #include "llvm/ExecutionEngine/JITMemoryManager.h"
 
@@ -44,6 +45,8 @@
 class ClangUserExpression : public ClangExpression
 {
 public:
+    typedef lldb::SharedPtr<ClangUserExpression>::Type ClangUserExpressionSP;
+
     //------------------------------------------------------------------
     /// Constructor
     ///
@@ -100,18 +103,25 @@
     ///     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] 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
+    ///     the ClangUserExpression for an unbounded period of time.  So you
+    ///     need to give the thread plan a reference to this object that can 
+    ///     keep it alive.
     /// 
     /// @param[in] result
     ///     A pointer to direct at the persistent variable in which the
     ///     expression's result is stored.
     ///
     /// @return
-    ///     True on success; false otherwise.
+    ///     A Process::Execution results value.
     //------------------------------------------------------------------
-    bool
+    Process::ExecutionResults
     Execute (Stream &error_stream,
              ExecutionContext &exe_ctx,
              bool discard_on_error,
+             ClangUserExpressionSP &shared_ptr_to_me,
              ClangExpressionVariable *&result);
              
     ThreadPlan *
@@ -222,12 +232,19 @@
     /// @param[in] expr_prefix
     ///     If non-NULL, a C string containing translation-unit level
     ///     definitions to be included when the expression is parsed.
+    ///
+    /// @param[in/out] result_valobj_sp
+    ///      If execution is successful, the result valobj is placed here.
+    ///
+    /// @result
+    ///      A Process::ExecutionResults value.  eExecutionCompleted for success.
     //------------------------------------------------------------------
-    static lldb::ValueObjectSP
+    static Process::ExecutionResults
     Evaluate (ExecutionContext &exe_ctx, 
               bool discard_on_error,
               const char *expr_cstr,
-              const char *expr_prefix);
+              const char *expr_prefix,
+              lldb::ValueObjectSP &result_valobj_sp);
 
 private:
     //------------------------------------------------------------------

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Mon Nov 29 20:22:11 2010
@@ -255,6 +255,17 @@
         eBroadcastInternalStateControlResume = (1<<2)
     };
 
+    // We can execute Thread Plans on one thread with various fall-back modes (try other threads after timeout, etc.)
+    // This enum gives the result of thread plan executions.
+    typedef enum ExecutionResults
+    {
+        eExecutionSetupError,
+        eExecutionCompleted,
+        eExecutionDiscarded,
+        eExecutionInterrupted,
+        eExecutionTimedOut
+    } ExecutionResults;
+        
     //------------------------------------------------------------------
     /// A notification structure that can be used by clients to listen
     /// for changes in a process's lifetime.
@@ -1019,8 +1030,12 @@
     //------------------------------------------------------------------
     /// Halts a running process.
     ///
-    /// DoHalt should consume any process events that were delivered in
-    /// the process of implementing the halt.
+    /// DoHalt must produce one and only one stop StateChanged event if it actually
+    /// stops the process.  If the stop happens through some natural event (for
+    /// instance a SIGSTOP), then forwarding that event will do.  Otherwise, you must 
+    /// generate the event manually.  Note also, the private event thread is stopped when 
+    /// DoHalt is run to prevent the events generated while halting to trigger
+    /// other state changes before the halt is complete.
     ///
     /// @param[out] caused_stop
     ///     If true, then this Halt caused the stop, otherwise, the 
@@ -1167,6 +1182,18 @@
     //------------------------------------------------------------------
     lldb::StateType
     GetState ();
+    
+    ExecutionResults
+    RunThreadPlan (ExecutionContext &exe_ctx,    
+                    lldb::ThreadPlanSP &thread_plan_sp,
+                    bool stop_others,
+                    bool try_all_threads,
+                    bool discard_on_error,
+                    uint32_t single_thread_timeout_usec,
+                    Stream &errors);
+
+    static const char *
+    ExecutionResultAsCString (ExecutionResults result);
 
 protected:
     friend class CommandObjectProcessLaunch;

Modified: lldb/trunk/include/lldb/Target/ThreadPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlan.h?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlan.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlan.h Mon Nov 29 20:22:11 2010
@@ -82,6 +82,11 @@
 //  Next the "StopOthers" method of all the threads are polled, and if one thread's Current plan
 //  returns "true" then only that thread gets to run.  If more than one returns "true" the threads that want to run solo
 //  get run one by one round robin fashion.  Otherwise all are let to run.
+//
+//  Note, the way StopOthers is implemented, the base class implementation just asks the previous plan.  So if your plan
+//  has no opinion about whether it should run stopping others or not, just don't implement StopOthers, and the parent
+//  will be asked.
+//
 //  Finally, for each thread that is running, it run state is set to the return of RunState from the
 //  thread's Current plan.
 //
@@ -240,6 +245,7 @@
     ///
     /// @param[in] error
     ///    A stream to which to print some reason why the plan could not be created.
+    ///    Can be NULL.
     ///
     /// @return
     ///   \b true if the plan should be queued, \b false otherwise.
@@ -281,6 +287,9 @@
     virtual lldb::Vote
     ShouldReportRun (Event *event_ptr);
 
+    virtual void
+    SetStopOthers (bool new_value);
+    
     virtual bool
     StopOthers ();
 

Added: lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h?rev=120386&view=auto
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h (added)
+++ lldb/trunk/include/lldb/Target/ThreadPlanCallUserExpression.h Mon Nov 29 20:22:11 2010
@@ -0,0 +1,59 @@
+//===-- ThreadPlanCallUserExpression.h --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ThreadPlanCallUserExpression_h_
+#define liblldb_ThreadPlanCallUserExpression_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallFunction.h"
+
+namespace lldb_private {
+
+class ThreadPlanCallUserExpression : public ThreadPlanCallFunction
+{
+public:
+    ThreadPlanCallUserExpression (Thread &thread,
+                            Address &function,
+                            lldb::addr_t arg,
+                            bool stop_other_threads,
+                            bool discard_on_error,
+                            lldb::addr_t *this_arg,
+                            ClangUserExpression::ClangUserExpressionSP &user_expression_sp);
+    
+    virtual
+    ~ThreadPlanCallUserExpression ();
+
+    virtual void
+    GetDescription (Stream *s, lldb::DescriptionLevel level);
+    
+    virtual void
+    WillPop ()
+    {
+        if (m_user_expression_sp)
+            m_user_expression_sp.reset();
+    }
+
+protected:
+private:
+    ClangUserExpression::ClangUserExpressionSP m_user_expression_sp;  // This is currently just used to ensure the
+                                                          // User expression the initiated this ThreadPlan
+                                                          // lives as long as the thread plan does.
+    DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallUserExpression);
+};
+
+} // namespace lldb_private
+
+#endif  // liblldb_ThreadPlanCallUserExpression_h_

Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Mon Nov 29 20:22:11 2010
@@ -341,6 +341,8 @@
 		4C61978E12823D4300FAFFCC /* AppleObjCRuntimeV1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C61978A12823D4300FAFFCC /* AppleObjCRuntimeV1.cpp */; };
 		4C61978F12823D4300FAFFCC /* AppleObjCRuntimeV1.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C61978B12823D4300FAFFCC /* AppleObjCRuntimeV1.h */; };
 		4C74CB6312288704006A8171 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C74CB6212288704006A8171 /* Carbon.framework */; };
+		4C7CF7E41295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C7CF7E31295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h */; };
+		4C7CF7E61295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7CF7E51295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp */; };
 		4CA9637B11B6E99A00780E28 /* CommandObjectApropos.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CA9637911B6E99A00780E28 /* CommandObjectApropos.cpp */; };
 		4CB4430C12491DDA00C13DC2 /* LanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CB4430A12491DDA00C13DC2 /* LanguageRuntime.cpp */; };
 		4CB4436C124944B000C13DC2 /* ItaniumABILanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CB4436A124944B000C13DC2 /* ItaniumABILanguageRuntime.cpp */; };
@@ -981,6 +983,8 @@
 		4C61978A12823D4300FAFFCC /* AppleObjCRuntimeV1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AppleObjCRuntimeV1.cpp; path = LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp; sourceTree = "<group>"; };
 		4C61978B12823D4300FAFFCC /* AppleObjCRuntimeV1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppleObjCRuntimeV1.h; path = LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h; sourceTree = "<group>"; };
 		4C74CB6212288704006A8171 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
+		4C7CF7E31295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanCallUserExpression.h; path = include/lldb/Target/ThreadPlanCallUserExpression.h; sourceTree = "<group>"; };
+		4C7CF7E51295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallUserExpression.cpp; path = source/Target/ThreadPlanCallUserExpression.cpp; sourceTree = "<group>"; };
 		4C98D3DA118FB96F00E575D0 /* ClangFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangFunction.cpp; path = source/Expression/ClangFunction.cpp; sourceTree = "<group>"; };
 		4C98D3DB118FB96F00E575D0 /* RecordingMemoryManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RecordingMemoryManager.cpp; path = source/Expression/RecordingMemoryManager.cpp; sourceTree = "<group>"; };
 		4C98D3E0118FB98F00E575D0 /* ClangFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangFunction.h; path = include/lldb/Expression/ClangFunction.h; sourceTree = "<group>"; };
@@ -2061,6 +2065,8 @@
 				260C847110F50EFC00BB2B04 /* ThreadPlanBase.cpp */,
 				49EC3E9C118F90D400B1265E /* ThreadPlanCallFunction.h */,
 				49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */,
+				4C7CF7E31295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h */,
+				4C7CF7E51295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp */,
 				4C43DEF9110641F300E55CBF /* ThreadPlanShouldStopHere.h */,
 				4C43DEFA110641F300E55CBF /* ThreadPlanShouldStopHere.cpp */,
 				260C848010F50F0A00BB2B04 /* ThreadPlanStepInstruction.h */,
@@ -2381,6 +2387,7 @@
 				4C61978F12823D4300FAFFCC /* AppleObjCRuntimeV1.h in Headers */,
 				4CC2A14D128C7409001531C4 /* ThreadPlanTracer.h in Headers */,
 				266A42D8128E40040090CF7C /* ClangNamespaceDecl.h in Headers */,
+				4C7CF7E41295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2452,7 +2459,6 @@
 			isa = PBXProject;
 			buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */;
 			compatibilityVersion = "Xcode 3.1";
-			developmentRegion = English;
 			hasScannedForEncodings = 1;
 			knownRegions = (
 				en,
@@ -2885,6 +2891,7 @@
 				4C61978E12823D4300FAFFCC /* AppleObjCRuntimeV1.cpp in Sources */,
 				4CC2A149128C73ED001531C4 /* ThreadPlanTracer.cpp in Sources */,
 				266A42D6128E3FFB0090CF7C /* ClangNamespaceDecl.cpp in Sources */,
+				4C7CF7E61295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: lldb/trunk/source/API/SBFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBFrame.cpp?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/source/API/SBFrame.cpp (original)
+++ lldb/trunk/source/API/SBFrame.cpp Mon Nov 29 20:22:11 2010
@@ -577,7 +577,7 @@
         if (exe_ctx.target)
             prefix = exe_ctx.target->GetExpressionPrefixContentsAsCString();
         
-        *expr_result = ClangUserExpression::Evaluate (exe_ctx, discard_on_error, expr, prefix);
+        ClangUserExpression::Evaluate (exe_ctx, discard_on_error, expr, prefix, *expr_result);
     }
     
     if (log)

Modified: lldb/trunk/source/Commands/CommandObjectCall.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectCall.cpp?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectCall.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectCall.cpp Mon Nov 29 20:22:11 2010
@@ -292,20 +292,20 @@
             }
         }
         
-        ClangFunction::ExecutionResults return_status;
+        Process::ExecutionResults return_status;
         Value return_value;
         
         bool stop_others = true;
         return_status = clang_fun.ExecuteFunction(exe_ctx, errors, stop_others, NULL, return_value);
 
         // Now figure out what to do with the return value.
-        if (return_status == ClangFunction::eExecutionSetupError)
+        if (return_status == Process::eExecutionSetupError)
         {
             result.AppendErrorWithFormat("Error setting up function execution: '%s'.\n", errors.GetData());
             result.SetStatus (eReturnStatusFailed);
             return false;
         }
-        else if (return_status != ClangFunction::eExecutionCompleted)
+        else if (return_status != Process::eExecutionCompleted)
         {
             result.AppendWarningWithFormat("Interrupted while calling function: '%s'.\n", errors.GetData());
             result.SetStatus(eReturnStatusSuccessFinishNoResult);

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Mon Nov 29 20:22:11 2010
@@ -13,6 +13,7 @@
 // C++ Includes
 // Other libraries and framework includes
 // Project includes
+#include "CommandObjectThread.h" // For DisplayThreadInfo.
 #include "lldb/Interpreter/Args.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Core/InputReader.h"
@@ -242,7 +243,8 @@
     if (m_exe_ctx.target)
         prefix = m_exe_ctx.target->GetExpressionPrefixContentsAsCString();
     
-    lldb::ValueObjectSP result_valobj_sp (ClangUserExpression::Evaluate (m_exe_ctx, m_options.unwind_on_error, expr, prefix));
+    lldb::ValueObjectSP result_valobj_sp;
+    Process::ExecutionResults execution_results = ClangUserExpression::Evaluate (m_exe_ctx, m_options.unwind_on_error, expr, prefix, result_valobj_sp);
     assert (result_valobj_sp.get());
     if (result_valobj_sp->GetError().Success())
     {
@@ -267,6 +269,16 @@
     else
     {
         error_stream.PutCString(result_valobj_sp->GetError().AsCString());
+        // If we've been interrupted, display state information.
+        if (execution_results == Process::eExecutionInterrupted && !m_options.unwind_on_error)
+        {
+            if (m_exe_ctx.thread)
+                lldb_private::DisplayThreadInfo (m_interpreter, result->GetOutputStream(), m_exe_ctx.thread, false, true);
+            else
+            {
+                lldb_private::DisplayThreadsInfo (m_interpreter, &m_exe_ctx, *result, true, true); 
+            }
+        }
         if (result)
             result->SetStatus (eReturnStatusFailed);
     }

Modified: lldb/trunk/source/Expression/ClangFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangFunction.cpp?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangFunction.cpp Mon Nov 29 20:22:11 2010
@@ -275,7 +275,7 @@
         
     Error error;
     using namespace clang;
-    ExecutionResults return_value = eExecutionSetupError;
+    Process::ExecutionResults return_value = Process::eExecutionSetupError;
 
     Process *process = exe_ctx.process;
 
@@ -439,13 +439,13 @@
     exe_ctx.process->DeallocateMemory(args_addr);
 }
 
-ClangFunction::ExecutionResults
+Process::ExecutionResults
 ClangFunction::ExecuteFunction(ExecutionContext &exe_ctx, Stream &errors, Value &results)
 {
     return ExecuteFunction (exe_ctx, errors, 1000, true, results);
 }
 
-ClangFunction::ExecutionResults
+Process::ExecutionResults
 ClangFunction::ExecuteFunction(ExecutionContext &exe_ctx, Stream &errors, bool stop_others, Value &results)
 {
     const bool try_all_threads = false;
@@ -453,7 +453,7 @@
     return ExecuteFunction (exe_ctx, NULL, errors, stop_others, NULL, try_all_threads, discard_on_error, results);
 }
 
-ClangFunction::ExecutionResults
+Process::ExecutionResults
 ClangFunction::ExecuteFunction(
         ExecutionContext &exe_ctx, 
         Stream &errors, 
@@ -468,7 +468,7 @@
 }
 
 // This is the static function
-ClangFunction::ExecutionResults 
+Process::ExecutionResults 
 ClangFunction::ExecuteFunction (
         ExecutionContext &exe_ctx, 
         lldb::addr_t function_address, 
@@ -480,259 +480,19 @@
         Stream &errors,
         lldb::addr_t *this_arg)
 {
-    // Save this value for restoration of the execution context after we run
-    uint32_t tid = exe_ctx.thread->GetIndexID();
-    
-    // N.B. Running the target may unset the currently selected thread and frame.  We don't want to do that either, 
-    // so we should arrange to reset them as well.
-    
-    lldb::ThreadSP selected_thread_sp = exe_ctx.process->GetThreadList().GetSelectedThread();
-    lldb::StackFrameSP selected_frame_sp;
-    
-    uint32_t selected_tid; 
-    if (selected_thread_sp != NULL)
-    {
-        selected_tid = selected_thread_sp->GetIndexID();
-        selected_frame_sp = selected_thread_sp->GetSelectedFrame();
-    }
-    else
-    {
-        selected_tid = LLDB_INVALID_THREAD_ID;
-    }
-
-    ClangFunction::ExecutionResults return_value = eExecutionSetupError;
     lldb::ThreadPlanSP call_plan_sp(ClangFunction::GetThreadPlanToCallFunction(exe_ctx, function_address, void_arg, 
                                                                                errors, stop_others, discard_on_error, 
                                                                                this_arg));
-    
-    ThreadPlanCallFunction *call_plan_ptr = static_cast<ThreadPlanCallFunction *> (call_plan_sp.get());
-    
     if (call_plan_sp == NULL)
-        return eExecutionSetupError;
+        return Process::eExecutionSetupError;
     
     call_plan_sp->SetPrivate(true);
-    exe_ctx.thread->QueueThreadPlan(call_plan_sp, true);
-    
-    Listener listener("ClangFunction temporary listener");
-    exe_ctx.process->HijackProcessEvents(&listener);
-    
-    Error resume_error = exe_ctx.process->Resume ();
-    if (!resume_error.Success())
-    {
-        errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
-        exe_ctx.process->RestoreProcessEvents();
-        return eExecutionSetupError;
-    }
-    
-    // We need to call the function synchronously, so spin waiting for it to return.
-    // If we get interrupted while executing, we're going to lose our context, and
-    // won't be able to gather the result at this point.
-    // We set the timeout AFTER the resume, since the resume takes some time and we
-    // don't want to charge that to the timeout.
-    
-    TimeValue* timeout_ptr = NULL;
-    TimeValue real_timeout;
-    
-    if (single_thread_timeout_usec != 0)
-    {
-        real_timeout = TimeValue::Now();
-        real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
-        timeout_ptr = &real_timeout;
-    }
-    
-    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
-    while (1)
-    {
-        lldb::EventSP event_sp;
-        lldb::StateType stop_state = lldb::eStateInvalid;
-        // Now wait for the process to stop again:
-        bool got_event = listener.WaitForEvent (timeout_ptr, event_sp);
-        
-        if (!got_event)
-        {
-            // Right now this is the only way to tell we've timed out...
-            // We should interrupt the process here...
-            // Not really sure what to do if Halt fails here...
-            if (log)
-                if (try_all_threads)
-                    log->Printf ("Running function with timeout: %d timed out, trying with all threads enabled.",
-                                 single_thread_timeout_usec);
-                else
-                    log->Printf ("Running function with timeout: %d timed out, abandoning execution.", 
-                                 single_thread_timeout_usec);
-            
-            if (exe_ctx.process->Halt().Success())
-            {
-                timeout_ptr = NULL;
-                if (log)
-                    log->Printf ("Halt succeeded.");
-                    
-                // Between the time that we got the timeout and the time we halted, but target
-                // might have actually completed the plan.  If so, we're done.  Note, I call WFE here with a short 
-                // timeout to 
-                got_event = listener.WaitForEvent(NULL, event_sp);
-                
-                if (got_event)
-                {
-                    stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
-                    if (log)
-                    {
-                        log->Printf ("Stopped with event: %s", StateAsCString(stop_state));
-                        if (stop_state == lldb::eStateStopped && Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get()))
-                            log->Printf ("    Event was the Halt interruption event.");
-                    }
-                    
-                    if (exe_ctx.thread->IsThreadPlanDone (call_plan_sp.get()))
-                    {
-                        if (log)
-                            log->Printf ("Even though we timed out, the call plan was done.  Exiting wait loop.");
-                        return_value = eExecutionCompleted;
-                        break;
-                    }
-
-                    if (try_all_threads 
-                        && (stop_state == lldb::eStateStopped && Process::ProcessEventData::GetInterruptedFromEvent (event_sp.get())))
-                    {
-                        
-                        call_plan_ptr->SetStopOthers (false);
-                        if (log)
-                            log->Printf ("About to resume.");
-
-                        exe_ctx.process->Resume();
-                        continue;
-                    }
-                    else
-                    {
-                        exe_ctx.process->RestoreProcessEvents ();
-                        return eExecutionInterrupted;
-                    }
-                }
-            }
-        }
-        
-        stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
-        if (log)
-            log->Printf("Got event: %s.", StateAsCString(stop_state));
-        
-        if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping)
-            continue;
-        
-        if (exe_ctx.thread->IsThreadPlanDone (call_plan_sp.get()))
-        {
-            return_value = eExecutionCompleted;
-            break;
-        }
-        else if (exe_ctx.thread->WasThreadPlanDiscarded (call_plan_sp.get()))
-        {
-            return_value = eExecutionDiscarded;
-            break;
-        }
-        else
-        {
-            if (log)
-            {
-                StreamString s;
-                event_sp->Dump (&s);
-                StreamString ts;
-
-                const char *event_explanation;                
-                
-                do 
-                {
-                    const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get());
-
-                    if (!event_data)
-                    {
-                        event_explanation = "<no event data>";
-                        break;
-                    }
-                    
-                    Process *process = event_data->GetProcessSP().get();
-
-                    if (!process)
-                    {
-                        event_explanation = "<no process>";
-                        break;
-                    }
-                    
-                    ThreadList &thread_list = process->GetThreadList();
-                    
-                    uint32_t num_threads = thread_list.GetSize();
-                    uint32_t thread_index;
-                    
-                    ts.Printf("<%u threads> ", num_threads);
-                    
-                    for (thread_index = 0;
-                         thread_index < num_threads;
-                         ++thread_index)
-                    {
-                        Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();
-                        
-                        if (!thread)
-                        {
-                            ts.Printf("<?> ");
-                            continue;
-                        }
-                        
-                        ts.Printf("<");
-                        RegisterContext *register_context = thread->GetRegisterContext();
-                        
-                        if (register_context)
-                            ts.Printf("[ip 0x%llx] ", register_context->GetPC());
-                        else
-                            ts.Printf("[ip unknown] ");
-                        
-                        lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
-                        if (stop_info_sp)
-                        {
-                            const char *stop_desc = stop_info_sp->GetDescription();
-                            if (stop_desc)
-                                ts.PutCString (stop_desc);
-                        }
-                        ts.Printf(">");
-                    }
-                    
-                    event_explanation = ts.GetData();
-                } while (0);
-                
-                if (log)
-                    log->Printf("Execution interrupted: %s %s", s.GetData(), event_explanation);
-            }
-            
-            if (discard_on_error && call_plan_sp)
-            {
-                exe_ctx.thread->DiscardThreadPlansUpToPlan (call_plan_sp);
-            }
-            return_value = eExecutionInterrupted;
-            break;
-        }
-    }
-    
-    if (exe_ctx.process)
-        exe_ctx.process->RestoreProcessEvents ();
-            
-    // Thread we ran the function in may have gone away because we ran the target
-    // Check that it's still there.
-    exe_ctx.thread = exe_ctx.process->GetThreadList().FindThreadByIndexID(tid, true).get();
-    if (exe_ctx.thread)
-        exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex(0).get();
-    
-    // Also restore the current process'es selected frame & thread, since this function calling may
-    // be done behind the user's back.
-    
-    if (selected_tid != LLDB_INVALID_THREAD_ID)
-    {
-        if (exe_ctx.process->GetThreadList().SetSelectedThreadByIndexID (selected_tid))
-        {
-            // We were able to restore the selected thread, now restore the frame:
-            exe_ctx.process->GetThreadList().GetSelectedThread()->SetSelectedFrame(selected_frame_sp.get());
-        }
-    }
     
-    return return_value;
+    return exe_ctx.process->RunThreadPlan (exe_ctx, call_plan_sp, stop_others, try_all_threads, discard_on_error,
+                                            single_thread_timeout_usec, errors);
 }  
 
-ClangFunction::ExecutionResults
+Process::ExecutionResults
 ClangFunction::ExecuteFunction(
         ExecutionContext &exe_ctx, 
         lldb::addr_t *args_addr_ptr, 
@@ -744,7 +504,7 @@
         Value &results)
 {
     using namespace clang;
-    ExecutionResults return_value = eExecutionSetupError;
+    Process::ExecutionResults return_value = Process::eExecutionSetupError;
     
     lldb::addr_t args_addr;
     
@@ -754,12 +514,12 @@
         args_addr = LLDB_INVALID_ADDRESS;
         
     if (CompileFunction(errors) != 0)
-        return eExecutionSetupError;
+        return Process::eExecutionSetupError;
     
     if (args_addr == LLDB_INVALID_ADDRESS)
     {
         if (!InsertFunction(exe_ctx, args_addr, errors))
-            return eExecutionSetupError;
+            return Process::eExecutionSetupError;
     }
     
     return_value = ClangFunction::ExecuteFunction(exe_ctx, m_wrapper_function_addr, args_addr, stop_others, 
@@ -768,7 +528,7 @@
     if (args_addr_ptr != NULL)
         *args_addr_ptr = args_addr;
     
-    if (return_value != eExecutionCompleted)
+    if (return_value != Process::eExecutionCompleted)
         return return_value;
 
     FetchFunctionResults(exe_ctx, args_addr, results);
@@ -776,7 +536,7 @@
     if (args_addr_ptr == NULL)
         DeallocateFunctionResults(exe_ctx, args_addr);
         
-    return eExecutionCompleted;
+    return Process::eExecutionCompleted;
 }
 
 clang::ASTConsumer *

Modified: lldb/trunk/source/Expression/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangUserExpression.cpp Mon Nov 29 20:22:11 2010
@@ -33,6 +33,8 @@
 #include "lldb/Target/Process.h"
 #include "lldb/Target/StackFrame.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
 
 using namespace lldb_private;
 
@@ -318,6 +320,9 @@
     
     PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_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.  
     return ClangFunction::GetThreadPlanToCallFunction (exe_ctx, 
                                         m_jit_addr, 
                                         struct_address, 
@@ -342,10 +347,11 @@
     return true;
 }        
 
-bool
+Process::ExecutionResults
 ClangUserExpression::Execute (Stream &error_stream,
                               ExecutionContext &exe_ctx,
                               bool discard_on_error,
+                              ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
                               ClangExpressionVariable *&result)
 {
     if (m_dwarf_opcodes.get())
@@ -354,7 +360,7 @@
         
         error_stream.Printf("We don't currently support executing DWARF expressions");
         
-        return false;
+        return Process::eExecutionSetupError;
     }
     else if (m_jit_addr != LLDB_INVALID_ADDRESS)
     {
@@ -366,50 +372,46 @@
         
         const bool stop_others = true;
         const bool try_all_threads = true;
-        ClangFunction::ExecutionResults execution_result = 
-        ClangFunction::ExecuteFunction (exe_ctx, 
-                                        m_jit_addr, 
-                                        struct_address, 
-                                        stop_others,
-                                        try_all_threads,
-                                        discard_on_error, 
-                                        10000000, 
-                                        error_stream,
-                                        (m_needs_object_ptr ? &object_ptr : NULL));
         
-        if (execution_result != ClangFunction::eExecutionCompleted)
+        Address wrapper_address (NULL, m_jit_addr);
+        lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (*(exe_ctx.thread), wrapper_address, struct_address, 
+                                                                               stop_others, discard_on_error, 
+                                                                               (m_needs_object_ptr ? &object_ptr : NULL),
+                                                                               shared_ptr_to_me));
+        if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL))
+            return Process::eExecutionSetupError;
+    
+        call_plan_sp->SetPrivate(true);
+    
+        uint32_t single_thread_timeout_usec = 10000000;
+        Process::ExecutionResults execution_result = 
+           exe_ctx.process->RunThreadPlan (exe_ctx, call_plan_sp, stop_others, try_all_threads, discard_on_error,
+                                           single_thread_timeout_usec, error_stream);
+
+        if (execution_result == Process::eExecutionInterrupted)
         {
-            const char *result_name;
-            
-            switch (execution_result)
-            {
-                case ClangFunction::eExecutionCompleted:
-                    result_name = "eExecutionCompleted";
-                    break;
-                case ClangFunction::eExecutionDiscarded:
-                    result_name = "eExecutionDiscarded";
-                    break;
-                case ClangFunction::eExecutionInterrupted:
-                    result_name = "eExecutionInterrupted";
-                    break;
-                case ClangFunction::eExecutionSetupError:
-                    result_name = "eExecutionSetupError";
-                    break;
-                case ClangFunction::eExecutionTimedOut:
-                    result_name = "eExecutionTimedOut";
-                    break;
-            }
-            
-            error_stream.Printf ("Couldn't execute function; result was %s\n", result_name);
-            return false;
+            if (discard_on_error)
+                error_stream.Printf ("Expression execution was interrupted.  The process has been returned to the state before execution.");
+            else
+                error_stream.Printf ("Expression execution was interrupted.  The process has been left at the point where it was interrupted.");
+
+            return execution_result;
+        }
+        else if (execution_result != Process::eExecutionCompleted)
+        {
+            error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
+            return execution_result;
         }
         
-        return FinalizeJITExecution (error_stream, exe_ctx, result);
+        if  (FinalizeJITExecution (error_stream, exe_ctx, result))
+            return Process::eExecutionCompleted;
+        else
+            return Process::eExecutionSetupError;
     }
     else
     {
         error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function is present");
-        return false;
+        return Process::eExecutionSetupError;
     }
 }
 
@@ -422,18 +424,24 @@
     return *m_dwarf_opcodes.get();
 }
 
-lldb::ValueObjectSP
+Process::ExecutionResults
 ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, 
                                bool discard_on_error,
                                const char *expr_cstr,
-                               const char *expr_prefix)
+                               const char *expr_prefix,
+                               lldb::ValueObjectSP &result_valobj_sp)
 {
     Error error;
-    lldb::ValueObjectSP result_valobj_sp;
+    Process::ExecutionResults execution_results = Process::eExecutionSetupError;
     
     if (exe_ctx.process == NULL)
-        return result_valobj_sp;
-
+    {
+        error.SetErrorString ("Must have a process to evaluate expressions.");
+            
+        result_valobj_sp.reset (new ValueObjectConstResult (error));
+        return Process::eExecutionSetupError;
+    }
+    
     if (!exe_ctx.process->GetDynamicCheckers())
     {
         DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
@@ -448,17 +456,17 @@
                 error.SetErrorString (install_errors.GetString().c_str());
             
             result_valobj_sp.reset (new ValueObjectConstResult (error));
-            return result_valobj_sp;
+            return Process::eExecutionSetupError;
         }
             
         exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
     }
     
-    ClangUserExpression user_expression (expr_cstr, expr_prefix);
-    
+    ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix));
+
     StreamString error_stream;
     
-    if (!user_expression.Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL)))
+    if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL)))
     {
         if (error_stream.GetString().empty())
             error.SetErrorString ("expression failed to parse, unknown error");
@@ -471,7 +479,12 @@
 
         error_stream.GetString().clear();
 
-        if (!user_expression.Execute (error_stream, exe_ctx, discard_on_error, expr_result))
+        execution_results = user_expression_sp->Execute (error_stream, 
+                                                         exe_ctx, 
+                                                         discard_on_error, 
+                                                         user_expression_sp, 
+                                                         expr_result);
+        if (execution_results != Process::eExecutionCompleted)
         {
             if (error_stream.GetString().empty())
                 error.SetErrorString ("expression failed to execute, unknown error");
@@ -499,5 +512,5 @@
     if (result_valobj_sp.get() == NULL)
         result_valobj_sp.reset (new ValueObjectConstResult (error));
 
-    return result_valobj_sp;
+    return execution_results;
 }

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=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp Mon Nov 29 20:22:11 2010
@@ -122,9 +122,9 @@
     bool try_all_threads = true;
     bool stop_others = true;
     
-    ClangFunction::ExecutionResults results 
+    Process::ExecutionResults results 
         = func.ExecuteFunction(exe_ctx, &wrapper_struct_addr, error_stream, stop_others, 1000000, try_all_threads, unwind_on_error, ret);
-    if (results != ClangFunction::eExecutionCompleted)
+    if (results != Process::eExecutionCompleted)
     {
         str.Printf("Error evaluating Print Object function: %d.\n", results);
         return false;

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Mon Nov 29 20:22:11 2010
@@ -524,7 +524,8 @@
                 image_spec.GetPath(path, sizeof(path));
                 expr.Printf("dlopen (\"%s\", 2)", path);
                 const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
-                lldb::ValueObjectSP result_valobj_sp (ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix));
+                lldb::ValueObjectSP result_valobj_sp;
+                ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
                 if (result_valobj_sp->GetError().Success())
                 {
                     Scalar scalar;
@@ -588,7 +589,8 @@
                         StreamString expr;
                         expr.Printf("dlclose ((void *)0x%llx)", image_addr);
                         const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
-                        lldb::ValueObjectSP result_valobj_sp (ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix));
+                        lldb::ValueObjectSP result_valobj_sp;
+                        ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
                         if (result_valobj_sp->GetError().Success())
                         {
                             Scalar scalar;
@@ -1502,7 +1504,8 @@
 
         // Post any event we might have consumed. If all goes well, we will have
         // stopped the process, intercepted the event and set the interrupted
-        // bool in the event.
+        // bool in the event.  Post it to the private event queue and that will end up
+        // correctly setting the state.
         if (event_sp)
             m_private_state_broadcaster.BroadcastEvent(event_sp);
 
@@ -2281,6 +2284,284 @@
     }
 }
 
+Process::ExecutionResults
+Process::RunThreadPlan (ExecutionContext &exe_ctx,
+                        lldb::ThreadPlanSP &thread_plan_sp,        
+                        bool stop_others,
+                        bool try_all_threads,
+                        bool discard_on_error,
+                        uint32_t single_thread_timeout_usec,
+                        Stream &errors)
+{
+    ExecutionResults return_value = eExecutionSetupError;
+    
+    // Save this value for restoration of the execution context after we run
+    uint32_t tid = exe_ctx.thread->GetIndexID();
+
+    // N.B. Running the target may unset the currently selected thread and frame.  We don't want to do that either, 
+    // so we should arrange to reset them as well.
+    
+    lldb::ThreadSP selected_thread_sp = exe_ctx.process->GetThreadList().GetSelectedThread();
+    lldb::StackFrameSP selected_frame_sp;
+    
+    uint32_t selected_tid; 
+    if (selected_thread_sp != NULL)
+    {
+        selected_tid = selected_thread_sp->GetIndexID();
+        selected_frame_sp = selected_thread_sp->GetSelectedFrame();
+    }
+    else
+    {
+        selected_tid = LLDB_INVALID_THREAD_ID;
+    }
+
+    exe_ctx.thread->QueueThreadPlan(thread_plan_sp, true);
+    
+    Listener listener("ClangFunction temporary listener");
+    exe_ctx.process->HijackProcessEvents(&listener);
+    
+    Error resume_error = exe_ctx.process->Resume ();
+    if (!resume_error.Success())
+    {
+        errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
+        exe_ctx.process->RestoreProcessEvents();
+        return Process::eExecutionSetupError;
+    }
+    
+    // We need to call the function synchronously, so spin waiting for it to return.
+    // If we get interrupted while executing, we're going to lose our context, and
+    // won't be able to gather the result at this point.
+    // We set the timeout AFTER the resume, since the resume takes some time and we
+    // don't want to charge that to the timeout.
+    
+    TimeValue* timeout_ptr = NULL;
+    TimeValue real_timeout;
+    
+    if (single_thread_timeout_usec != 0)
+    {
+        real_timeout = TimeValue::Now();
+        real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
+        timeout_ptr = &real_timeout;
+    }
+    
+    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+    while (1)
+    {
+        lldb::EventSP event_sp;
+        lldb::StateType stop_state = lldb::eStateInvalid;
+        // Now wait for the process to stop again:
+        bool got_event = listener.WaitForEvent (timeout_ptr, event_sp);
+        
+        if (!got_event)
+        {
+            // Right now this is the only way to tell we've timed out...
+            // We should interrupt the process here...
+            // Not really sure what to do if Halt fails here...
+            if (log)
+                if (try_all_threads)
+                    log->Printf ("Running function with timeout: %d timed out, trying with all threads enabled.",
+                                 single_thread_timeout_usec);
+                else
+                    log->Printf ("Running function with timeout: %d timed out, abandoning execution.", 
+                                 single_thread_timeout_usec);
+            
+            if (exe_ctx.process->Halt().Success())
+            {
+                timeout_ptr = NULL;
+                if (log)
+                    log->Printf ("Halt succeeded.");
+                    
+                // Between the time that we got the timeout and the time we halted, but target
+                // might have actually completed the plan.  If so, we're done.  Note, I call WFE here with a short 
+                // timeout to 
+                got_event = listener.WaitForEvent(NULL, event_sp);
+                
+                if (got_event)
+                {
+                    stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                    if (log)
+                    {
+                        log->Printf ("Stopped with event: %s", StateAsCString(stop_state));
+                        if (stop_state == lldb::eStateStopped && Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get()))
+                            log->Printf ("    Event was the Halt interruption event.");
+                    }
+                    
+                    if (exe_ctx.thread->IsThreadPlanDone (thread_plan_sp.get()))
+                    {
+                        if (log)
+                            log->Printf ("Even though we timed out, the call plan was done.  Exiting wait loop.");
+                        return_value = Process::eExecutionCompleted;
+                        break;
+                    }
+
+                    if (try_all_threads 
+                        && (stop_state == lldb::eStateStopped && Process::ProcessEventData::GetInterruptedFromEvent (event_sp.get())))
+                    {
+                        
+                        thread_plan_sp->SetStopOthers (false);
+                        if (log)
+                            log->Printf ("About to resume.");
+
+                        exe_ctx.process->Resume();
+                        continue;
+                    }
+                    else
+                    {
+                        exe_ctx.process->RestoreProcessEvents ();
+                        return Process::eExecutionInterrupted;
+                    }
+                }
+            }
+        }
+        
+        stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+        if (log)
+            log->Printf("Got event: %s.", StateAsCString(stop_state));
+        
+        if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping)
+            continue;
+        
+        if (exe_ctx.thread->IsThreadPlanDone (thread_plan_sp.get()))
+        {
+            return_value = Process::eExecutionCompleted;
+            break;
+        }
+        else if (exe_ctx.thread->WasThreadPlanDiscarded (thread_plan_sp.get()))
+        {
+            return_value = Process::eExecutionDiscarded;
+            break;
+        }
+        else
+        {
+            if (log)
+            {
+                StreamString s;
+                event_sp->Dump (&s);
+                StreamString ts;
+
+                const char *event_explanation;                
+                
+                do 
+                {
+                    const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get());
+
+                    if (!event_data)
+                    {
+                        event_explanation = "<no event data>";
+                        break;
+                    }
+                    
+                    Process *process = event_data->GetProcessSP().get();
+
+                    if (!process)
+                    {
+                        event_explanation = "<no process>";
+                        break;
+                    }
+                    
+                    ThreadList &thread_list = process->GetThreadList();
+                    
+                    uint32_t num_threads = thread_list.GetSize();
+                    uint32_t thread_index;
+                    
+                    ts.Printf("<%u threads> ", num_threads);
+                    
+                    for (thread_index = 0;
+                         thread_index < num_threads;
+                         ++thread_index)
+                    {
+                        Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();
+                        
+                        if (!thread)
+                        {
+                            ts.Printf("<?> ");
+                            continue;
+                        }
+                        
+                        ts.Printf("<");
+                        RegisterContext *register_context = thread->GetRegisterContext();
+                        
+                        if (register_context)
+                            ts.Printf("[ip 0x%llx] ", register_context->GetPC());
+                        else
+                            ts.Printf("[ip unknown] ");
+                        
+                        lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
+                        if (stop_info_sp)
+                        {
+                            const char *stop_desc = stop_info_sp->GetDescription();
+                            if (stop_desc)
+                                ts.PutCString (stop_desc);
+                        }
+                        ts.Printf(">");
+                    }
+                    
+                    event_explanation = ts.GetData();
+                } while (0);
+                
+                if (log)
+                    log->Printf("Execution interrupted: %s %s", s.GetData(), event_explanation);
+            }
+            
+            if (discard_on_error && thread_plan_sp)
+            {
+                exe_ctx.thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
+            }
+            return_value = Process::eExecutionInterrupted;
+            break;
+        }
+    }
+    
+    if (exe_ctx.process)
+        exe_ctx.process->RestoreProcessEvents ();
+            
+    // Thread we ran the function in may have gone away because we ran the target
+    // Check that it's still there.
+    exe_ctx.thread = exe_ctx.process->GetThreadList().FindThreadByIndexID(tid, true).get();
+    if (exe_ctx.thread)
+        exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex(0).get();
+    
+    // Also restore the current process'es selected frame & thread, since this function calling may
+    // be done behind the user's back.
+    
+    if (selected_tid != LLDB_INVALID_THREAD_ID)
+    {
+        if (exe_ctx.process->GetThreadList().SetSelectedThreadByIndexID (selected_tid))
+        {
+            // We were able to restore the selected thread, now restore the frame:
+            exe_ctx.process->GetThreadList().GetSelectedThread()->SetSelectedFrame(selected_frame_sp.get());
+        }
+    }
+    
+    return return_value;
+}
+
+const char *
+Process::ExecutionResultAsCString (ExecutionResults result)
+{
+    const char *result_name;
+    
+    switch (result)
+    {
+        case Process::eExecutionCompleted:
+            result_name = "eExecutionCompleted";
+            break;
+        case Process::eExecutionDiscarded:
+            result_name = "eExecutionDiscarded";
+            break;
+        case Process::eExecutionInterrupted:
+            result_name = "eExecutionInterrupted";
+            break;
+        case Process::eExecutionSetupError:
+            result_name = "eExecutionSetupError";
+            break;
+        case Process::eExecutionTimedOut:
+            result_name = "eExecutionTimedOut";
+            break;
+    }
+    return result_name;
+}
+
 //--------------------------------------------------------------
 // class Process::SettingsController
 //--------------------------------------------------------------

Modified: lldb/trunk/source/Target/ThreadPlan.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlan.cpp?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlan.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlan.cpp Mon Nov 29 20:22:11 2010
@@ -133,6 +133,13 @@
         return prev_plan->StopOthers();
 }
 
+void
+ThreadPlan::SetStopOthers (bool new_value)
+{
+	// SetStopOthers doesn't work up the hierarchy.  You have to set the 
+    // explicit ThreadPlan you want to affect.
+}
+
 bool
 ThreadPlan::WillResume (StateType resume_state, bool current_plan)
 {

Added: lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp?rev=120386&view=auto
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp (added)
+++ lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp Mon Nov 29 20:22:11 2010
@@ -0,0 +1,59 @@
+//===-- ThreadPlanCallUserExpression.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/MachO.h"
+// Project includes
+#include "lldb/lldb-private-log.h"
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ThreadPlanCallUserExpression: Plan to call a single function
+//----------------------------------------------------------------------
+
+ThreadPlanCallUserExpression::ThreadPlanCallUserExpression (Thread &thread,
+                                                Address &function,
+                                                lldb::addr_t arg,
+                                                bool stop_other_threads,
+                                                bool discard_on_error,
+                                                lldb::addr_t *this_arg,
+                                                ClangUserExpression::ClangUserExpressionSP &user_expression_sp) :
+    ThreadPlanCallFunction (thread, function, arg, stop_other_threads, discard_on_error, this_arg),
+    m_user_expression_sp (user_expression_sp)
+{
+}
+
+ThreadPlanCallUserExpression::~ThreadPlanCallUserExpression ()
+{
+}
+
+void
+ThreadPlanCallUserExpression::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+    ThreadPlanCallFunction::GetDescription (s, level);
+}

Modified: lldb/trunk/source/Target/ThreadPlanRunToAddress.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanRunToAddress.cpp?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanRunToAddress.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanRunToAddress.cpp Mon Nov 29 20:22:11 2010
@@ -168,9 +168,12 @@
         if (m_break_ids[i] == LLDB_INVALID_BREAK_ID)
         {
             all_bps_good = false;
-            error->Printf ("Could not set breakpoint for address: ");
-            error->Address (m_addresses[i], sizeof (addr_t));
-            error->Printf ("\n");
+            if (error)
+            {
+                error->Printf ("Could not set breakpoint for address: ");
+                error->Address (m_addresses[i], sizeof (addr_t));
+                error->Printf ("\n");
+            }
         }
     }
     return all_bps_good;

Modified: lldb/trunk/source/Target/ThreadPlanTestCondition.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanTestCondition.cpp?rev=120386&r1=120385&r2=120386&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanTestCondition.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanTestCondition.cpp Mon Nov 29 20:22:11 2010
@@ -64,7 +64,10 @@
 void 
 ThreadPlanTestCondition::GetDescription (Stream *s, lldb::DescriptionLevel level)
 {
-
+    if (m_expression)
+        s->Printf("Thread plan to test condition: \"%s\".", m_expression->GetUserText());
+    else
+        s->Printf("Thread plan to test unspecified condition.");
 }
 
 bool 





More information about the lldb-commits mailing list