summaryrefslogtreecommitdiffstats
path: root/lldb
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2010-10-14 23:45:03 +0000
committerJim Ingham <jingham@apple.com>2010-10-14 23:45:03 +0000
commit36f3b369d2632e6898166c0e697f85e2ab458ece (patch)
tree62bfedb1bc23100bdf34b43673fa90dbc0f38d5e /lldb
parent3f1cf0f373ab9915d4f7dff04c57017c62869386 (diff)
downloadbcm5719-llvm-36f3b369d2632e6898166c0e697f85e2ab458ece.tar.gz
bcm5719-llvm-36f3b369d2632e6898166c0e697f85e2ab458ece.zip
Added support for breakpoint conditions. I also had to separate the "run the expression" part of ClangFunction::Execute from the "Gather the expression result" so that in the case of the Breakpoint condition I can move the condition evaluation into the normal thread plan processing.
Also added support for remembering the "last set breakpoint" so that "break modify" will act on the last set breakpoint. llvm-svn: 116542
Diffstat (limited to 'lldb')
-rw-r--r--lldb/include/lldb/Breakpoint/Breakpoint.h39
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointLocation.h35
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointOptions.h55
-rw-r--r--lldb/include/lldb/Core/Event.h50
-rw-r--r--lldb/include/lldb/Expression/ClangExpressionVariable.h3
-rw-r--r--lldb/include/lldb/Expression/ClangUserExpression.h26
-rw-r--r--lldb/include/lldb/Target/Process.h8
-rw-r--r--lldb/include/lldb/Target/StopInfo.h4
-rw-r--r--lldb/include/lldb/Target/Target.h7
-rw-r--r--lldb/include/lldb/Target/Thread.h6
-rw-r--r--lldb/include/lldb/Target/ThreadPlan.h5
-rw-r--r--lldb/include/lldb/Target/ThreadPlanTestCondition.h65
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj11
-rw-r--r--lldb/source/Breakpoint/Breakpoint.cpp18
-rw-r--r--lldb/source/Breakpoint/BreakpointLocation.cpp55
-rw-r--r--lldb/source/Breakpoint/BreakpointOptions.cpp89
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.cpp61
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.h2
-rw-r--r--lldb/source/Core/Event.cpp43
-rw-r--r--lldb/source/Expression/ClangExpressionParser.cpp2
-rw-r--r--lldb/source/Expression/ClangFunction.cpp6
-rw-r--r--lldb/source/Expression/ClangUserExpression.cpp87
-rw-r--r--lldb/source/Target/Process.cpp4
-rw-r--r--lldb/source/Target/StopInfo.cpp14
-rw-r--r--lldb/source/Target/Target.cpp12
-rw-r--r--lldb/source/Target/ThreadPlanTestCondition.cpp182
26 files changed, 760 insertions, 129 deletions
diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h
index 299707f0741..91b059a5be7 100644
--- a/lldb/include/lldb/Breakpoint/Breakpoint.h
+++ b/lldb/include/lldb/Breakpoint/Breakpoint.h
@@ -370,12 +370,41 @@ public:
ClearCallback ();
//------------------------------------------------------------------
- /// Set the condition expression to be checked when the breakpoint is hit.
- /// @param[in] expression
- /// The method that will get called when the breakpoint is hit.
+ /// Set the breakpoint's condition.
+ ///
+ /// @param[in] condition
+ /// The condition expression to evaluate when the breakpoint is hit.
+ /// Pass in NULL to clear the condition.
//------------------------------------------------------------------
- void
- SetCondition (void *expression);
+ void SetCondition (const char *condition);
+
+ //------------------------------------------------------------------
+ /// Test the breakpoint condition in the Execution context passed in.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context in which to evaluate this expression.
+ ///
+ /// @param[in] break_loc_sp
+ /// A shared pointer to the location that we are testing thsi condition for.
+ ///
+ /// @param[in] error
+ /// Error messages will be written to this stream.
+ ///
+ /// @return
+ /// A thread plan to run to test the condition or NULL if no condition.
+ //------------------------------------------------------------------
+ ThreadPlan *GetThreadPlanToTestCondition (ExecutionContext &exe_ctx,
+ lldb::BreakpointLocationSP break_loc_sp,
+ Stream &error);
+
+ //------------------------------------------------------------------
+ /// Return a pointer to the text of the condition expression.
+ ///
+ /// @return
+ /// A pointer to the condition expression text, or NULL if no
+ // condition has been set.
+ //------------------------------------------------------------------
+ const char *GetConditionText ();
//------------------------------------------------------------------
// The next section are various utility functions.
diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
index 179d39a33dc..b3444cfa9c4 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointLocation.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
@@ -160,13 +160,35 @@ public:
ClearCallback ();
//------------------------------------------------------------------
- /// Set the condition expression to be checked when the breakpoint is hit.
+ /// Set the breakpoint location's condition.
///
- /// @param[in] expression
- /// The method that will get called when the breakpoint is hit.
+ /// @param[in] condition
+ /// The condition expression to evaluate when the breakpoint is hit.
//------------------------------------------------------------------
- void
- SetCondition (void *condition);
+ void SetCondition (const char *condition);
+
+ //------------------------------------------------------------------
+ /// Test the breakpoint location's condition in the Execution context passed in.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context in which to evaluate this expression.
+ ///
+ /// @param[in] error
+ /// Error messages will be written to this stream.
+ ///
+ /// @return
+ /// A thread plan to run to test the condition, or NULL if there is no condition.
+ //------------------------------------------------------------------
+ ThreadPlan *GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, Stream &error);
+
+ //------------------------------------------------------------------
+ /// Return a pointer to the text of the condition expression.
+ ///
+ /// @return
+ /// A pointer to the condition expression text, or NULL if no
+ // condition has been set.
+ //------------------------------------------------------------------
+ const char *GetConditionText ();
//------------------------------------------------------------------
@@ -211,6 +233,9 @@ public:
//------------------------------------------------------------------
bool
IsResolved () const;
+
+ lldb::BreakpointSiteSP
+ GetBreakpointSite() const;
//------------------------------------------------------------------
// The next section are generic report functions.
diff --git a/lldb/include/lldb/Breakpoint/BreakpointOptions.h b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
index 5e8157a5517..721598d83f6 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointOptions.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointOptions.h
@@ -18,6 +18,7 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/Baton.h"
#include "lldb/Core/StringList.h"
+#include "lldb/Expression/ClangUserExpression.h"
namespace lldb_private {
@@ -88,7 +89,46 @@ public:
Baton *GetBaton ();
const Baton *GetBaton () const;
void ClearCallback ();
-
+
+ //------------------------------------------------------------------
+ // Condition
+ //------------------------------------------------------------------
+ //------------------------------------------------------------------
+ /// Set the breakpoint option's condition.
+ ///
+ /// @param[in] condition
+ /// The condition expression to evaluate when the breakpoint is hit.
+ //------------------------------------------------------------------
+ void SetCondition (const char *condition);
+
+ //------------------------------------------------------------------
+ /// Test the breakpoint condition in the Execution context passed in.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context in which to evaluate this expression.
+ ///
+ /// @param[in] break_loc_sp
+ /// A shared pointer to the location that we are testing thsi condition for.
+ ///
+ /// @param[in] error
+ /// Error messages will be written to this stream.
+ ///
+ /// @return
+ /// A thread plan to run to test the condition, or NULL if there is no thread plan.
+ //------------------------------------------------------------------
+ ThreadPlan *GetThreadPlanToTestCondition (ExecutionContext &exe_ctx,
+ lldb::BreakpointLocationSP break_loc_sp,
+ Stream &error);
+
+ //------------------------------------------------------------------
+ /// Return a pointer to the text of the condition expression.
+ ///
+ /// @return
+ /// A pointer to the condition expression text, or NULL if no
+ // condition has been set.
+ //------------------------------------------------------------------
+ const char *GetConditionText ();
+
//------------------------------------------------------------------
// Enabled/Ignore Count
//------------------------------------------------------------------
@@ -107,6 +147,12 @@ public:
void
SetEnabled (bool enabled);
+ //------------------------------------------------------------------
+ /// Set the breakpoint to ignore the next \a count breakpoint hits.
+ /// @param[in] count
+ /// The number of breakpoint hits to ignore.
+ //------------------------------------------------------------------
+
void
SetIgnoreCount (uint32_t n);
@@ -119,12 +165,6 @@ public:
GetIgnoreCount () const;
//------------------------------------------------------------------
- /// Set the breakpoint to ignore the next \a count breakpoint hits.
- /// @param[in] count
- /// The number of breakpoint hits to ignore.
- //------------------------------------------------------------------
-
- //------------------------------------------------------------------
/// Return the current thread spec for this option. This will return NULL if the no thread
/// specifications have been set for this Option yet.
/// @return
@@ -218,6 +258,7 @@ private:
bool m_enabled;
uint32_t m_ignore_count; // Number of times to ignore this breakpoint
std::auto_ptr<ThreadSpec> m_thread_spec_ap; // Thread for which this breakpoint will take
+ std::auto_ptr<ClangUserExpression> m_condition_ap; // The condition to test.
};
diff --git a/lldb/include/lldb/Core/Event.h b/lldb/include/lldb/Core/Event.h
index 66c5fbd7afa..dd6988daaba 100644
--- a/lldb/include/lldb/Core/Event.h
+++ b/lldb/include/lldb/Core/Event.h
@@ -134,22 +134,52 @@ public:
Dump (Stream *s) const;
EventData *
- GetData ();
+ GetData ()
+ {
+ return m_data_ap.get();
+ }
const EventData *
- GetData () const;
+ GetData () const
+ {
+ return m_data_ap.get();
+ }
+
+ void
+ SetData (EventData *new_data)
+ {
+ m_data_ap.reset (new_data);
+ }
uint32_t
- GetType () const;
+ GetType () const
+ {
+ return m_type;
+ }
+
+ void
+ SetType (uint32_t new_type)
+ {
+ m_type = new_type;
+ }
Broadcaster *
- GetBroadcaster () const;
-
+ GetBroadcaster () const
+ {
+ return m_broadcaster;
+ }
+
bool
- BroadcasterIs (Broadcaster *broadcaster);
+ BroadcasterIs (Broadcaster *broadcaster)
+ {
+ return broadcaster == m_broadcaster;
+ }
void
- Clear();
+ Clear()
+ {
+ m_data_ap.reset();
+ }
private:
@@ -164,7 +194,11 @@ private:
// know about it update the contained broadcaster so that events can be
// popped off one queue and re-broadcast to others.
void
- SetBroadcaster (Broadcaster *broadcaster);
+ SetBroadcaster (Broadcaster *broadcaster)
+ {
+ m_broadcaster = broadcaster;
+ }
+
Broadcaster * m_broadcaster; // The broadcaster that sent this event
uint32_t m_type; // The bit describing this event
diff --git a/lldb/include/lldb/Expression/ClangExpressionVariable.h b/lldb/include/lldb/Expression/ClangExpressionVariable.h
index 543efb65ae2..4e388be7db8 100644
--- a/lldb/include/lldb/Expression/ClangExpressionVariable.h
+++ b/lldb/include/lldb/Expression/ClangExpressionVariable.h
@@ -89,7 +89,8 @@ struct ClangExpressionVariable
/// The following values should stay valid for the life of the variable
//----------------------------------------------------------------------
std::string m_name; ///< The name of the variable
- TypeFromUser m_user_type; ///< The type of the variable according to some LLDB context; NULL if the type hasn't yet been migrated to one
+ TypeFromUser m_user_type; ///< The type of the variable according to some LLDB context;
+ ///< NULL if the type hasn't yet been migrated to one
//----------------------------------------------------------------------
/// The following values indicate where the variable originally came from
diff --git a/lldb/include/lldb/Expression/ClangUserExpression.h b/lldb/include/lldb/Expression/ClangUserExpression.h
index f193446b8a8..dee47519eaf 100644
--- a/lldb/include/lldb/Expression/ClangUserExpression.h
+++ b/lldb/include/lldb/Expression/ClangUserExpression.h
@@ -24,6 +24,7 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionVariable.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
@@ -90,7 +91,15 @@ public:
bool
Execute (Stream &error_stream,
ExecutionContext &exe_ctx,
- ClangExpressionVariable *& result);
+ ClangExpressionVariable *&result);
+
+ ThreadPlan *
+ GetThreadPlanToExecuteJITExpression (Stream &error_stream,
+ ExecutionContext &exe_ctx);
+ bool
+ FinalizeJITExecution (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ ClangExpressionVariable *&result);
//------------------------------------------------------------------
/// Return the string that the parser should parse. Must be a full
@@ -103,6 +112,15 @@ public:
}
//------------------------------------------------------------------
+ /// Return the string that the user typed.
+ //------------------------------------------------------------------
+ const char *
+ GetUserText ()
+ {
+ return m_expr_text.c_str();
+ }
+
+ //------------------------------------------------------------------
/// Return the function name that should be used for executing the
/// expression. Text() should contain the definition of this
/// function.
@@ -181,6 +199,12 @@ private:
//------------------------------------------------------------------
void
ScanContext(ExecutionContext &exe_ctx);
+
+ bool
+ PrepareToExecuteJITExpression (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb::addr_t &struct_address,
+ lldb::addr_t object_ptr);
std::string m_expr_text; ///< The text of the expression, as typed by the user
std::string m_transformed_text; ///< The text of the expression, as send to the parser
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index beb8bcde61f..51fb04bfdd0 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -232,6 +232,7 @@ class Process :
public ProcessInstanceSettings
{
friend class ThreadList;
+friend class ClangFunction; // For WaitForStateChangeEventsPrivate
public:
@@ -316,7 +317,6 @@ public:
static bool
SetUpdateStateOnRemoval (Event *event_ptr);
-
private:
void
@@ -1592,12 +1592,12 @@ public:
DynamicCheckerFunctions *GetDynamicCheckers()
{
- return m_dynamic_checkers.get();
+ return m_dynamic_checkers_ap.get();
}
void SetDynamicCheckers(DynamicCheckerFunctions *dynamic_checkers)
{
- m_dynamic_checkers.reset(dynamic_checkers);
+ m_dynamic_checkers_ap.reset(dynamic_checkers);
}
//------------------------------------------------------------------
@@ -1646,7 +1646,7 @@ protected:
BreakpointSiteList m_breakpoint_site_list; ///< This is the list of breakpoint locations we intend
///< to insert in the target.
ClangPersistentVariables m_persistent_vars; ///< These are the persistent variables associated with this process for the expression parser.
- std::auto_ptr<DynamicCheckerFunctions> m_dynamic_checkers; ///< The functions used by the expression parser to validate data that expressions use.
+ std::auto_ptr<DynamicCheckerFunctions> m_dynamic_checkers_ap; ///< The functions used by the expression parser to validate data that expressions use.
UnixSignals m_unix_signals; /// This is the current signal set for this process.
ConstString m_target_triple;
lldb::ABISP m_abi_sp;
diff --git a/lldb/include/lldb/Target/StopInfo.h b/lldb/include/lldb/Target/StopInfo.h
index d348ae9b3b7..080aaa37011 100644
--- a/lldb/include/lldb/Target/StopInfo.h
+++ b/lldb/include/lldb/Target/StopInfo.h
@@ -90,6 +90,10 @@ public:
static lldb::StopInfoSP
CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id);
+ // This creates a StopInfo for the thread where the should_stop is already set, and won't be recalculated.
+ static lldb::StopInfoSP
+ CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id, bool should_stop);
+
static lldb::StopInfoSP
CreateStopReasonWithWatchpointID (Thread &thread, lldb::break_id_t watch_id);
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index d8bc8a43178..32fe250f893 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -204,6 +204,12 @@ public:
const BreakpointList &
GetBreakpointList(bool internal = false) const;
+
+ lldb::BreakpointSP
+ GetLastCreatedBreakpoint ()
+ {
+ return m_last_created_breakpoint;
+ }
lldb::BreakpointSP
GetBreakpointByID (lldb::break_id_t break_id);
@@ -443,6 +449,7 @@ protected:
SectionLoadList m_section_load_list;
BreakpointList m_breakpoint_list;
BreakpointList m_internal_breakpoint_list;
+ lldb::BreakpointSP m_last_created_breakpoint;
// We want to tightly control the process destruction process so
// we can correctly tear down everything that we need to, so the only
// class that knows about the process lifespan is this target class.
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index 80b86d16753..8b520dbf139 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -238,6 +238,12 @@ public:
StopInfo *
GetStopInfo ();
+ void
+ SetStopInfo (lldb::StopInfoSP stop_info_sp)
+ {
+ m_public_stop_info_sp = stop_info_sp;
+ }
+
bool
ThreadStoppedForAReason ();
diff --git a/lldb/include/lldb/Target/ThreadPlan.h b/lldb/include/lldb/Target/ThreadPlan.h
index d20be6505b8..1f8bb8cd47e 100644
--- a/lldb/include/lldb/Target/ThreadPlan.h
+++ b/lldb/include/lldb/Target/ThreadPlan.h
@@ -179,6 +179,8 @@ public:
eThisThread
} ThreadScope;
+ // We use these enums so that we can cast a base thread plan to it's real type without having to resort
+ // to dynamic casting.
typedef enum
{
eKindGeneric,
@@ -191,7 +193,8 @@ public:
eKindStepInRange,
eKindRunToAddress,
eKindStepThrough,
- eKindStepUntil
+ eKindStepUntil,
+ eKindTestCondition
} ThreadPlanKind;
diff --git a/lldb/include/lldb/Target/ThreadPlanTestCondition.h b/lldb/include/lldb/Target/ThreadPlanTestCondition.h
new file mode 100644
index 00000000000..cedc277f58f
--- /dev/null
+++ b/lldb/include/lldb/Target/ThreadPlanTestCondition.h
@@ -0,0 +1,65 @@
+//===-- ThreadPlanTestCondition.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_ThreadPlanTestCondition_h_
+#define liblldb_ThreadPlanTestCondition_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Target/StackID.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanShouldStopHere.h"
+
+namespace lldb_private {
+
+class ThreadPlanTestCondition : public ThreadPlan
+{
+public:
+ virtual ~ThreadPlanTestCondition ();
+
+ ThreadPlanTestCondition (Thread &thread,
+ ExecutionContext &exe_ctx,
+ ClangUserExpression *expression,
+ lldb::BreakpointLocationSP break_loc_sp,
+ bool stop_others);
+
+ virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
+ virtual bool ValidatePlan (Stream *error);
+ virtual bool PlanExplainsStop ();
+ virtual bool ShouldStop (Event *event_ptr);
+ virtual lldb::Vote ShouldReportStop (Event *event_ptr);
+ virtual bool StopOthers ();
+ virtual lldb::StateType RunState ();
+ virtual bool WillStop ();
+ virtual bool MischiefManaged ();
+ virtual void DidPush ();
+
+protected:
+
+private:
+ ClangUserExpression *m_expression;
+ ExecutionContext m_exe_ctx;
+ lldb::ThreadPlanSP m_expression_plan_sp;
+ lldb::BreakpointLocationSP m_break_loc_sp;
+ bool m_did_stop;
+ bool m_stop_others;
+
+ DISALLOW_COPY_AND_ASSIGN (ThreadPlanTestCondition);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ThreadPlanTestCondition_h_
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index 516bb859d2f..ba7b079f100 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -356,6 +356,8 @@
4C0A91DB12511CB900CA6636 /* AppleThreadPlanStepThroughObjCTrampoline.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0A91D712511CB900CA6636 /* AppleThreadPlanStepThroughObjCTrampoline.h */; };
4C139EA5124A8B03000BFF8D /* AppleObjCRuntimeV2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C139EA3124A8B03000BFF8D /* AppleObjCRuntimeV2.cpp */; };
4C139EA6124A8B03000BFF8D /* AppleObjCRuntimeV2.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C139EA4124A8B03000BFF8D /* AppleObjCRuntimeV2.h */; };
+ 4C1AB23B1263E5F400D0F04A /* ThreadPlanTestCondition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C1AB23A1263E5F400D0F04A /* ThreadPlanTestCondition.cpp */; };
+ 4C1AB23F1263E61100D0F04A /* ThreadPlanTestCondition.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C1AB23E1263E61100D0F04A /* ThreadPlanTestCondition.h */; };
4C5DBBC811E3FEC60035160F /* CommandObjectCommands.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C5DBBC611E3FEC60035160F /* CommandObjectCommands.cpp */; };
4C5DBBC911E3FEC60035160F /* CommandObjectCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5DBBC711E3FEC60035160F /* CommandObjectCommands.h */; };
4C74CB6312288704006A8171 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C74CB6212288704006A8171 /* Carbon.framework */; };
@@ -980,6 +982,8 @@
4C0A91D712511CB900CA6636 /* AppleThreadPlanStepThroughObjCTrampoline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppleThreadPlanStepThroughObjCTrampoline.h; path = LanguageRuntime/ObjC/AppleObjCRuntimeV2/AppleThreadPlanStepThroughObjCTrampoline.h; sourceTree = "<group>"; };
4C139EA3124A8B03000BFF8D /* AppleObjCRuntimeV2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AppleObjCRuntimeV2.cpp; path = LanguageRuntime/ObjC/AppleObjCRuntimeV2/AppleObjCRuntimeV2.cpp; sourceTree = "<group>"; };
4C139EA4124A8B03000BFF8D /* AppleObjCRuntimeV2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppleObjCRuntimeV2.h; path = LanguageRuntime/ObjC/AppleObjCRuntimeV2/AppleObjCRuntimeV2.h; sourceTree = "<group>"; };
+ 4C1AB23A1263E5F400D0F04A /* ThreadPlanTestCondition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanTestCondition.cpp; path = source/Target/ThreadPlanTestCondition.cpp; sourceTree = "<group>"; };
+ 4C1AB23E1263E61100D0F04A /* ThreadPlanTestCondition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanTestCondition.h; path = include/lldb/Target/ThreadPlanTestCondition.h; sourceTree = "<group>"; };
4C43DEF9110641F300E55CBF /* ThreadPlanShouldStopHere.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanShouldStopHere.h; path = include/lldb/Target/ThreadPlanShouldStopHere.h; sourceTree = "<group>"; };
4C43DEFA110641F300E55CBF /* ThreadPlanShouldStopHere.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanShouldStopHere.cpp; path = source/Target/ThreadPlanShouldStopHere.cpp; sourceTree = "<group>"; };
4C43DF8511069BFD00E55CBF /* ThreadPlanStepInRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepInRange.h; path = include/lldb/Target/ThreadPlanStepInRange.h; sourceTree = "<group>"; };
@@ -1155,7 +1159,6 @@
children = (
26C9DF02113C5B80006B0F94 /* Include */,
26F5C32810F3DF7D009D5894 /* Libraries */,
- 266960581199F4230075C61A /* Scripts */,
08FB7795FE84155DC02AAC07 /* Source */,
26F5C22410F3D950009D5894 /* Tools */,
1AB674ADFE9D54B511CA2CBB /* Products */,
@@ -1166,6 +1169,7 @@
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
+ 266960581199F4230075C61A /* Scripts */,
26BC7E7410F1B85900F91463 /* lldb.cpp */,
26BC7E7510F1B85900F91463 /* lldb-log.cpp */,
26BC7C2A10F1B3BC00F91463 /* lldb-private.h */,
@@ -2064,6 +2068,8 @@
260C847510F50EFC00BB2B04 /* ThreadPlanStepThrough.cpp */,
4CEDAED311754F5E00E875A6 /* ThreadPlanStepUntil.h */,
2660D9FE11922A7F00958FBD /* ThreadPlanStepUntil.cpp */,
+ 4C1AB23E1263E61100D0F04A /* ThreadPlanTestCondition.h */,
+ 4C1AB23A1263E5F400D0F04A /* ThreadPlanTestCondition.cpp */,
4C08CDEB11C81F1E001610A8 /* ThreadSpec.h */,
4C08CDE711C81EF8001610A8 /* ThreadSpec.cpp */,
4C00986F11500B4300F316B0 /* UnixSignals.h */,
@@ -2384,6 +2390,7 @@
4C0A91D912511CB900CA6636 /* AppleObjCTrampolineHandler.h in Headers */,
4C0A91DB12511CB900CA6636 /* AppleThreadPlanStepThroughObjCTrampoline.h in Headers */,
26424E3F125986D30016D82C /* ValueObjectConstResult.h in Headers */,
+ 4C1AB23F1263E61100D0F04A /* ThreadPlanTestCondition.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2438,7 +2445,6 @@
isa = PBXProject;
buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */;
compatibilityVersion = "Xcode 3.1";
- developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
en,
@@ -2856,6 +2862,7 @@
4C0A91D812511CB900CA6636 /* AppleObjCTrampolineHandler.cpp in Sources */,
4C0A91DA12511CB900CA6636 /* AppleThreadPlanStepThroughObjCTrampoline.cpp in Sources */,
26424E3D125986CB0016D82C /* ValueObjectConstResult.cpp in Sources */,
+ 4C1AB23B1263E5F400D0F04A /* ThreadPlanTestCondition.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp
index c79b1a89afe..fd2296df681 100644
--- a/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/lldb/source/Breakpoint/Breakpoint.cpp
@@ -185,6 +185,24 @@ Breakpoint::GetThreadID ()
return m_options.GetThreadSpec()->GetTID();
}
+void
+Breakpoint::SetCondition (const char *condition)
+{
+ m_options.SetCondition (condition);
+}
+
+ThreadPlan *
+Breakpoint::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, lldb::BreakpointLocationSP loc_sp, Stream &error)
+{
+ return m_options.GetThreadPlanToTestCondition (exe_ctx, loc_sp, error);
+}
+
+const char *
+Breakpoint::GetConditionText ()
+{
+ return m_options.GetConditionText();
+}
+
// This function is used when "baton" doesn't need to be freed
void
Breakpoint::SetCallback (BreakpointHitCallback callback, void *baton, bool is_synchronous)
diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp
index dc45654a77c..609a41ef43f 100644
--- a/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -18,6 +18,7 @@
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Log.h"
#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Core/StreamString.h"
#include "lldb/lldb-private-log.h"
@@ -131,12 +132,35 @@ BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &
GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous);
}
+
void
BreakpointLocation::ClearCallback ()
{
GetLocationOptions()->ClearCallback();
}
+void
+BreakpointLocation::SetCondition (const char *condition)
+{
+ GetLocationOptions()->SetCondition (condition);
+}
+
+ThreadPlan *
+BreakpointLocation::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, Stream &error)
+{
+ lldb::BreakpointLocationSP my_sp(m_owner.GetLocationSP(this));
+ if (m_options_ap.get())
+ return m_options_ap->GetThreadPlanToTestCondition (exe_ctx, my_sp, error);
+ else
+ return m_owner.GetThreadPlanToTestCondition (exe_ctx, my_sp, error);
+}
+
+const char *
+BreakpointLocation::GetConditionText ()
+{
+ return GetLocationOptions()->GetConditionText();
+}
+
uint32_t
BreakpointLocation::GetIgnoreCount ()
{
@@ -185,6 +209,7 @@ bool
BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
{
bool should_stop = true;
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
m_hit_count++;
@@ -194,13 +219,31 @@ BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
if (m_hit_count <= GetIgnoreCount())
return false;
- // Tell if the callback is synchronous here.
+ // Next in order of importance is the condition. See if it is true:
+ StreamString errors;
+
+ // We only run synchronous callbacks in ShouldStop:
context->is_synchronous = true;
should_stop = InvokeCallback (context);
-
+
+ // The SYNCHRONOUS callback says we should stop, next try the condition.
+
+ if (should_stop)
+ {
+ ThreadPlanSP condition_plan_sp(GetThreadPlanToTestCondition(context->exe_ctx, errors));
+ if (log && errors.GetSize() > 0)
+ {
+ log->Printf("Error evaluating condition: \"%s\".\n", errors.GetData());
+ }
+ else if (condition_plan_sp != NULL)
+ {
+ context->exe_ctx.thread->QueueThreadPlan(condition_plan_sp, false);
+ return false;
+ }
+ }
+
if (should_stop)
{
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
if (log)
{
StreamString s;
@@ -217,6 +260,12 @@ BreakpointLocation::IsResolved () const
return m_bp_site_sp.get() != NULL;
}
+lldb::BreakpointSiteSP
+BreakpointLocation::GetBreakpointSite() const
+{
+ return m_bp_site_sp;
+}
+
bool
BreakpointLocation::ResolveBreakpointSite ()
{
diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp
index 9054f3b89a6..b3aa1152761 100644
--- a/lldb/source/Breakpoint/BreakpointOptions.cpp
+++ b/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -15,8 +15,11 @@
// Project includes
#include "lldb/Core/Stream.h"
#include "lldb/Core/StringList.h"
+#include "lldb/Core/Value.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/ThreadSpec.h"
+#include "lldb/Target/ThreadPlanTestCondition.h"
using namespace lldb;
using namespace lldb_private;
@@ -36,7 +39,8 @@ BreakpointOptions::BreakpointOptions() :
m_callback_is_synchronous (false),
m_enabled (true),
m_ignore_count (0),
- m_thread_spec_ap (NULL)
+ m_thread_spec_ap (NULL),
+ m_condition_ap()
{
}
@@ -49,10 +53,13 @@ BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) :
m_callback_is_synchronous (rhs.m_callback_is_synchronous),
m_enabled (rhs.m_enabled),
m_ignore_count (rhs.m_ignore_count),
- m_thread_spec_ap (NULL)
+ m_thread_spec_ap (NULL),
+ m_condition_ap (NULL)
{
if (rhs.m_thread_spec_ap.get() != NULL)
m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get()));
+ if (rhs.m_condition_ap.get())
+ m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText()));
}
//----------------------------------------------------------------------
@@ -68,6 +75,8 @@ BreakpointOptions::operator=(const BreakpointOptions& rhs)
m_ignore_count = rhs.m_ignore_count;
if (rhs.m_thread_spec_ap.get() != NULL)
m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
+ if (rhs.m_condition_ap.get())
+ m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText()));
return *this;
}
@@ -107,7 +116,8 @@ BreakpointOptions::SetCallback (BreakpointHitCallback callback, const BatonSP &c
void
BreakpointOptions::ClearCallback ()
{
- m_callback = NULL;
+ m_callback = BreakpointOptions::NullCallback;
+ m_callback_is_synchronous = false;
m_callback_baton_sp.reset();
}
@@ -145,6 +155,71 @@ BreakpointOptions::HasCallback ()
return m_callback != BreakpointOptions::NullCallback;
}
+void
+BreakpointOptions::SetCondition (const char *condition)
+{
+ if (condition == NULL || condition[0] == '\0')
+ {
+ if (m_condition_ap.get())
+ m_condition_ap.reset();
+ }
+ else
+ {
+ m_condition_ap.reset(new ClangUserExpression (condition));
+ }
+}
+
+ThreadPlan *
+BreakpointOptions::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx,
+ lldb::BreakpointLocationSP break_loc_sp,
+ Stream &error_stream)
+{
+ // No condition means we should stop, so return NULL.
+ if (!m_condition_ap.get())
+ return NULL;
+
+ // FIXME: I shouldn't have to do this, the process should handle it for me:
+ if (!exe_ctx.process->GetDynamicCheckers())
+ {
+ DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
+
+ StreamString install_errors;
+
+ if (!dynamic_checkers->Install(install_errors, exe_ctx))
+ {
+ error_stream.Printf("Couldn't install dynamic checkers into the execution context: %s\n", install_errors.GetData());
+ return NULL;
+ }
+
+ exe_ctx.process->SetDynamicCheckers(dynamic_checkers);
+ }
+
+ if (!m_condition_ap->Parse (error_stream, exe_ctx))
+ {
+ // Errors mean we should stop.
+ return NULL;
+ }
+ // FIXME: When we can execute static expressions without running the target, we should check that here,
+ // and return something to indicate we should stop or just continue.
+
+ ThreadPlan *new_plan = new ThreadPlanTestCondition (*exe_ctx.thread,
+ exe_ctx,
+ m_condition_ap.get(),
+ break_loc_sp,
+ true);
+
+ return new_plan;
+}
+
+const char *
+BreakpointOptions::GetConditionText ()
+{
+ if (m_condition_ap.get())
+ return m_condition_ap->GetUserText();
+ else
+ return "<No Condition>";
+}
+
//------------------------------------------------------------------
// Enabled/Ignore Count
//------------------------------------------------------------------
@@ -234,6 +309,14 @@ BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) cons
if (level != eDescriptionLevelBrief)
s->EOL();
m_callback_baton_sp->GetDescription (s, level);
+ }
+ if (m_condition_ap.get())
+ {
+ if (level != eDescriptionLevelBrief)
+ {
+ s->EOL();
+ s->Printf("Condition: %s\n", m_condition_ap->GetUserText());
+ }
}
}
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
index a9d1615dfca..c642ae5551f 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -547,9 +547,25 @@ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *targe
// 2). the full breakpoint & location canonical representation
// 3). the word "to" or a hyphen, representing a range (in which case there
// had *better* be an entry both before & after of one of the first two types.
+ // If args is empty, we will use the last created breakpoint (if there is one.)
Args temp_args;
+ if (args.GetArgumentCount() == 0)
+ {
+ if (target->GetLastCreatedBreakpoint() != NULL)
+ {
+ valid_ids->AddBreakpointID (BreakpointID(target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError("No breakpoint specified and no last created breakpoint.");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return;
+ }
+
// Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff directly from the old ARGS to
// the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead generate a list of strings for
// all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS.
@@ -1076,16 +1092,15 @@ CommandObjectBreakpointDelete::Execute
if (args.GetArgumentCount() == 0)
{
- // No breakpoint selected; disable all currently set breakpoints.
- if (args.GetArgumentCount() != 0)
+ if (!m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true))
{
- result.AppendErrorWithFormat ("Specify breakpoints to delete with the -i option.\n");
- result.SetStatus (eReturnStatusFailed);
- return false;
+ result.AppendMessage("Operation cancelled...");
+ }
+ else
+ {
+ target->RemoveAllBreakpoints ();
+ result.AppendMessageWithFormat ("All breakpoints removed. (%d breakpoints)\n", num_breakpoints);
}
-
- target->RemoveAllBreakpoints ();
- result.AppendMessageWithFormat ("All breakpoints removed. (%d breakpoints)\n", num_breakpoints);
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
@@ -1143,10 +1158,12 @@ CommandObjectBreakpointModify::CommandOptions::CommandOptions() :
m_thread_index (UINT32_MAX),
m_thread_name(),
m_queue_name(),
+ m_condition (),
m_enable_passed (false),
m_enable_value (false),
m_name_passed (false),
- m_queue_passed (false)
+ m_queue_passed (false),
+ m_condition_passed (false)
{
}
@@ -1162,9 +1179,10 @@ CommandObjectBreakpointModify::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, NULL, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."},
{ LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, NULL, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."},
{ LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, NULL, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."},
+{ LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, NULL, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."},
{ LLDB_OPT_SET_1, false, "enable", 'e', no_argument, NULL, NULL, eArgTypeNone, "Enable the breakpoint."},
{ LLDB_OPT_SET_2, false, "disable", 'd', no_argument, NULL, NULL, eArgTypeNone, "Disable the breakpoint."},
-{ 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
+{ 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
};
const lldb::OptionDefinition*
@@ -1181,6 +1199,13 @@ CommandObjectBreakpointModify::CommandOptions::SetOptionValue (int option_idx, c
switch (short_option)
{
+ case 'c':
+ if (option_arg != NULL)
+ m_condition = option_arg;
+ else
+ m_condition.clear();
+ m_condition_passed = true;
+ break;
case 'd':
m_enable_passed = true;
m_enable_value = false;
@@ -1243,9 +1268,11 @@ CommandObjectBreakpointModify::CommandOptions::ResetOptionValues ()
m_thread_index = UINT32_MAX;
m_thread_name.clear();
m_queue_name.clear();
+ m_condition.clear();
m_enable_passed = false;
m_queue_passed = false;
m_name_passed = false;
+ m_condition_passed = false;
}
//-------------------------------------------------------------------------
@@ -1297,13 +1324,6 @@ CommandObjectBreakpointModify::Execute
CommandReturnObject &result
)
{
- if (command.GetArgumentCount() == 0)
- {
- result.AppendError ("No breakpoints specified.");
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target == NULL)
{
@@ -1351,6 +1371,9 @@ CommandObjectBreakpointModify::Execute
if (m_options.m_enable_passed)
location->SetEnabled (m_options.m_enable_value);
+
+ if (m_options.m_condition_passed)
+ location->SetCondition (m_options.m_condition.c_str());
}
}
else
@@ -1372,7 +1395,9 @@ CommandObjectBreakpointModify::Execute
if (m_options.m_enable_passed)
bp->SetEnabled (m_options.m_enable_value);
-
+
+ if (m_options.m_condition_passed)
+ bp->SetCondition (m_options.m_condition.c_str());
}
}
}
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h
index cdff75a0b48..45bdb16a255 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.h
+++ b/lldb/source/Commands/CommandObjectBreakpoint.h
@@ -167,10 +167,12 @@ public:
uint32_t m_thread_index;
std::string m_thread_name;
std::string m_queue_name;
+ std::string m_condition;
bool m_enable_passed;
bool m_enable_value;
bool m_name_passed;
bool m_queue_passed;
+ bool m_condition_passed;
};
diff --git a/lldb/source/Core/Event.cpp b/lldb/source/Core/Event.cpp
index 8ca2a9fb800..8bf28f259f3 100644
--- a/lldb/source/Core/Event.cpp
+++ b/lldb/source/Core/Event.cpp
@@ -49,12 +49,6 @@ Event::~Event ()
}
void
-Event::Clear()
-{
- m_data_ap.reset();
-}
-
-void
Event::Dump (Stream *s) const
{
s->Printf("%p Event: broadcaster = %p, type = 0x%8.8x, data = ", this, m_broadcaster, m_type);
@@ -69,37 +63,6 @@ Event::Dump (Stream *s) const
}
}
-Broadcaster *
-Event::GetBroadcaster () const
-{
- return m_broadcaster;
-}
-
-bool
-Event::BroadcasterIs (Broadcaster *broadcaster)
-{
- return broadcaster == m_broadcaster;
-}
-
-uint32_t
-Event::GetType() const
-{
- return m_type;
-}
-
-
-EventData *
-Event::GetData ()
-{
- return m_data_ap.get();
-}
-
-const EventData *
-Event::GetData () const
-{
- return m_data_ap.get();
-}
-
void
Event::DoOnRemoval ()
{
@@ -107,12 +70,6 @@ Event::DoOnRemoval ()
m_data_ap->DoOnRemoval (this);
}
-void
-Event::SetBroadcaster (Broadcaster *broadcaster)
-{
- m_broadcaster = broadcaster;
-}
-
EventData::EventData()
{
}
diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp
index 7085f407170..506f2f5ffd9 100644
--- a/lldb/source/Expression/ClangExpressionParser.cpp
+++ b/lldb/source/Expression/ClangExpressionParser.cpp
@@ -447,7 +447,7 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_addr,
return err;
}
- if (m_expr.NeedsValidation())
+ if (m_expr.NeedsValidation() && exe_ctx.process->GetDynamicCheckers())
{
/*
Disabled temporarily - TODO Centralize and re-enable this inside Process to avoid race conditions
diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp
index 3d5e8383f9a..4ef26d1cb2e 100644
--- a/lldb/source/Expression/ClangFunction.cpp
+++ b/lldb/source/Expression/ClangFunction.cpp
@@ -539,9 +539,11 @@ ClangFunction::ExecuteFunction (
// 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);
+ 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);
+ log->Printf ("Running function with timeout: %d timed out, abandoning execution.",
+ single_thread_timeout_usec);
if (exe_ctx.process->Halt().Success())
{
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp
index 4aabf521511..c1eeb24e273 100644
--- a/lldb/source/Expression/ClangUserExpression.cpp
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -215,27 +215,18 @@ ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
}
bool
-ClangUserExpression::Execute (Stream &error_stream,
- ExecutionContext &exe_ctx,
- ClangExpressionVariable *&result)
+ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb::addr_t &struct_address,
+ lldb::addr_t object_ptr)
{
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
- if (m_dwarf_opcodes.get())
- {
- // TODO execute the JITted opcodes
-
- error_stream.Printf("We don't currently support executing DWARF expressions");
-
- return false;
- }
- else if (m_jit_addr != LLDB_INVALID_ADDRESS)
+ if (m_jit_addr != LLDB_INVALID_ADDRESS)
{
- lldb::addr_t struct_address;
Error materialize_error;
- lldb::addr_t object_ptr = NULL;
if (m_needs_object_ptr && !(m_expr_decl_map->GetObjectPointer(object_ptr, &exe_ctx, materialize_error)))
{
@@ -274,6 +265,64 @@ ClangUserExpression::Execute (Stream &error_stream,
}
}
}
+ }
+ return true;
+}
+
+ThreadPlan *
+ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
+ ExecutionContext &exe_ctx)
+{
+ lldb::addr_t struct_address;
+
+ lldb::addr_t object_ptr = NULL;
+
+ PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr);
+
+ return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
+ m_jit_addr,
+ struct_address,
+ error_stream,
+ true,
+ true,
+ (m_needs_object_ptr ? &object_ptr : NULL));
+}
+
+bool
+ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ ClangExpressionVariable *&result)
+{
+ Error expr_error;
+
+ if (!m_expr_decl_map->Dematerialize(&exe_ctx, result, expr_error))
+ {
+ error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
+ return false;
+ }
+ return true;
+}
+
+bool
+ClangUserExpression::Execute (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ ClangExpressionVariable *&result)
+{
+ if (m_dwarf_opcodes.get())
+ {
+ // TODO execute the JITted opcodes
+
+ error_stream.Printf("We don't currently support executing DWARF expressions");
+
+ return false;
+ }
+ else if (m_jit_addr != LLDB_INVALID_ADDRESS)
+ {
+ lldb::addr_t struct_address;
+
+ lldb::addr_t object_ptr = NULL;
+
+ PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr);
ClangFunction::ExecutionResults execution_result =
ClangFunction::ExecuteFunction (exe_ctx,
@@ -312,15 +361,7 @@ ClangUserExpression::Execute (Stream &error_stream,
return false;
}
- Error expr_error;
-
- if (!m_expr_decl_map->Dematerialize(&exe_ctx, result, expr_error))
- {
- error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
- return false;
- }
-
- return true;
+ return FinalizeJITExecution (error_stream, exe_ctx, result);
}
else
{
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 5b789dc24ee..7c9a841a5e8 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -82,9 +82,9 @@ Process::Process(Target &target, Listener &listener) :
m_exit_string (),
m_thread_list (this),
m_notifications (),
+ m_persistent_vars(),
m_listener(listener),
- m_unix_signals (),
- m_persistent_vars()
+ m_unix_signals ()
{
UpdateInstanceName();
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 49f07926715..877988f5812 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -56,6 +56,14 @@ public:
{
}
+ StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) :
+ StopInfo (thread, break_id),
+ m_description(),
+ m_should_stop (should_stop),
+ m_should_stop_is_valid (true)
+ {
+ }
+
virtual ~StopInfoBreakpoint ()
{
}
@@ -367,6 +375,12 @@ StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break
}
StopInfoSP
+StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop)
+{
+ return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop));
+}
+
+StopInfoSP
StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id)
{
return StopInfoSP (new StopInfoWatchpoint (thread, watch_id));
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 57d044987e9..4a5ce2fa21b 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -252,6 +252,12 @@ Target::CreateBreakpoint (SearchFilterSP &filter_sp, BreakpointResolverSP &resol
bp_sp->ResolveBreakpoint();
}
+
+ if (!internal && bp_sp)
+ {
+ m_last_created_breakpoint = bp_sp;
+ }
+
return bp_sp;
}
@@ -265,6 +271,8 @@ Target::RemoveAllBreakpoints (bool internal_also)
m_breakpoint_list.RemoveAll (true);
if (internal_also)
m_internal_breakpoint_list.RemoveAll (false);
+
+ m_last_created_breakpoint.reset();
}
void
@@ -303,7 +311,11 @@ Target::RemoveBreakpointByID (break_id_t break_id)
if (LLDB_BREAK_ID_IS_INTERNAL (break_id))
m_internal_breakpoint_list.Remove(break_id, false);
else
+ {
+ if (m_last_created_breakpoint->GetID() == break_id)
+ m_last_created_breakpoint.reset();
m_breakpoint_list.Remove(break_id, true);
+ }
return true;
}
return false;
diff --git a/lldb/source/Target/ThreadPlanTestCondition.cpp b/lldb/source/Target/ThreadPlanTestCondition.cpp
new file mode 100644
index 00000000000..30fe739136f
--- /dev/null
+++ b/lldb/source/Target/ThreadPlanTestCondition.cpp
@@ -0,0 +1,182 @@
+//===-- ThreadPlanTestCondition.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/ThreadPlanTestCondition.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-private-log.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//----------------------------------------------------------------------
+// ThreadPlanTestCondition: Step through a stack range, either stepping over or into
+// based on the value of \a type.
+//----------------------------------------------------------------------
+
+ThreadPlanTestCondition::ThreadPlanTestCondition (
+ Thread& thread,
+ ExecutionContext &exe_ctx,
+ ClangUserExpression *expression,
+ lldb::BreakpointLocationSP break_loc_sp,
+ bool stop_others) :
+ ThreadPlan (ThreadPlan::eKindTestCondition, "test condition", thread, eVoteNoOpinion, eVoteNoOpinion),
+ m_exe_ctx (exe_ctx),
+ m_expression (expression),
+ m_break_loc_sp (break_loc_sp),
+ m_did_stop (false),
+ m_stop_others (stop_others)
+{
+}
+
+ThreadPlanTestCondition::~ThreadPlanTestCondition ()
+{
+}
+
+bool
+ThreadPlanTestCondition::ValidatePlan (Stream *error)
+{
+ return true;
+}
+
+void
+ThreadPlanTestCondition::GetDescription (Stream *s, lldb::DescriptionLevel level)
+{
+
+}
+
+bool
+ThreadPlanTestCondition::ShouldStop (Event *event_ptr)
+{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+ if (m_thread.IsThreadPlanDone(m_expression_plan_sp.get()))
+ {
+ ClangExpressionVariable *expr_result = NULL;
+ StreamString error_stream;
+ m_expression->FinalizeJITExecution(error_stream, m_exe_ctx, expr_result);
+
+ ValueObjectSP result_sp (expr_result->GetExpressionResult(&m_exe_ctx));
+ if (result_sp)
+ {
+ // FIXME: This is not the right answer, we should have a "GetValueAsBoolean..."
+ Scalar scalar_value = result_sp->GetValue().ResolveValue (&m_exe_ctx, result_sp->GetClangAST());
+ if (scalar_value.IsValid())
+ {
+ if (scalar_value.ULongLong(1) == 0)
+ m_did_stop = false;
+ else
+ m_did_stop = true;
+ }
+ if (log)
+ log->Printf("Condition successfully evaluated, result is %s.\n", m_did_stop ? "true" : "false");
+ }
+ else
+ {
+ if (log)
+ log->Printf("Failed to get a result from the expression, error: \"%s\"\n", error_stream.GetData());
+ m_did_stop = true;
+ }
+ }
+ else if (m_exe_ctx.thread->WasThreadPlanDiscarded (m_expression_plan_sp.get()))
+ {
+ if (log)
+ log->Printf("ExecuteExpression thread plan was discarded.\n");
+ m_did_stop = true;
+ }
+
+ // Now we have to change the event to a breakpoint event and mark it up appropriately:
+ Process::ProcessEventData *new_data = new Process::ProcessEventData (m_thread.GetProcess().GetSP(), eStateStopped);
+ event_ptr->SetData(new_data);
+ event_ptr->SetType(Process::eBroadcastBitStateChanged);
+ m_thread.SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID (m_thread,
+ m_break_loc_sp->GetBreakpointSite()->GetID(),
+ m_did_stop));
+ if (m_did_stop)
+ {
+ Process::ProcessEventData::SetRestartedInEvent (event_ptr, false);
+ }
+ else
+ {
+ Process::ProcessEventData::SetRestartedInEvent (event_ptr, true);
+ }
+
+ SetPlanComplete();
+ return m_did_stop;
+}
+
+bool
+ThreadPlanTestCondition::PlanExplainsStop ()
+{
+ // We explain all stops, and we just can the execution and return true if we stop for any
+ // reason other than that our expression execution is done.
+ return true;
+}
+
+Vote
+ThreadPlanTestCondition::ShouldReportStop (Event *event_ptr)
+{
+ if (m_did_stop)
+ {
+ return eVoteYes;
+ }
+ else
+ {
+ return eVoteNo;
+ }
+}
+
+void
+ThreadPlanTestCondition::DidPush()
+{
+ StreamString error_stream;
+ m_expression_plan_sp.reset(m_expression->GetThreadPlanToExecuteJITExpression (error_stream, m_exe_ctx));
+ m_thread.QueueThreadPlan (m_expression_plan_sp, false);
+}
+
+bool
+ThreadPlanTestCondition::StopOthers ()
+{
+ return m_stop_others;
+}
+
+bool
+ThreadPlanTestCondition::WillStop ()
+{
+ return true;
+}
+
+StateType
+ThreadPlanTestCondition::RunState ()
+{
+ return eStateRunning;
+}
+
+bool
+ThreadPlanTestCondition::MischiefManaged ()
+{
+ // If we get a stop we're done, we don't puase in the middle of
+ // condition execution.
+ return true;
+}
OpenPOWER on IntegriCloud