[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