rdar://problem/12007576
Record the snapshot of our watched value when the watchpoint is set or hit.
And report the old/new values when watchpoint is triggered. Add some test scenarios.
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@161785 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp
index 96c1739..a902ee8 100644
--- a/source/Target/StopInfo.cpp
+++ b/source/Target/StopInfo.cpp
@@ -451,7 +451,7 @@
virtual void
PerformAction (Event *event_ptr)
{
- LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+ LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS);
// We're going to calculate if we should stop or not in some way during the course of
// this code. Also by default we're going to stop, so set that here.
m_should_stop = true;
@@ -461,11 +461,11 @@
if (wp_sp)
{
ExecutionContext exe_ctx (m_thread.GetStackFrameAtIndex(0));
+ Process* process = exe_ctx.GetProcessPtr();
{
// check if this process is running on an architecture where watchpoints trigger
// before the associated instruction runs. if so, disable the WP, single-step and then
// re-enable the watchpoint
- Process* process = exe_ctx.GetProcessPtr();
if (process)
{
uint32_t num; bool wp_triggers_after;
@@ -491,7 +491,62 @@
}
}
}
- StoppointCallbackContext context (event_ptr, exe_ctx, false);
+
+ // Record the snapshot of our watchpoint.
+ VariableSP var_sp;
+ ValueObjectSP valobj_sp;
+ StackFrame *frame = exe_ctx.GetFramePtr();
+ if (frame)
+ {
+ if (!wp_sp->IsWatchVariable())
+ {
+ assert (process);
+ Error error;
+ uint64_t val = process->ReadUnsignedIntegerFromMemory(wp_sp->GetLoadAddress(),
+ wp_sp->GetByteSize(),
+ 0,
+ error);
+ if (log)
+ {
+ if (error.Success())
+ log->Printf("Watchpoint snapshot val taken: 0x%llx\n", val);
+ else
+ log->Printf("Watchpoint snapshot val taking failed.\n");
+ }
+ wp_sp->SetNewSnapshotVal(val);
+ }
+ else if (!wp_sp->GetWatchSpec().empty())
+ {
+ // Things have checked out ok...
+ Error error;
+ uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember |
+ StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
+ valobj_sp = frame->GetValueForVariableExpressionPath (wp_sp->GetWatchSpec().c_str(),
+ eNoDynamicValues,
+ expr_path_options,
+ var_sp,
+ error);
+ if (valobj_sp)
+ {
+ // We're in business.
+ StreamString ss;
+ ValueObject::DumpValueObject(ss, valobj_sp.get());
+ wp_sp->SetNewSnapshot(ss.GetString());
+ }
+ else
+ wp_sp->SetNewSnapshot("snapshot attempt failed.");
+
+ if (log)
+ log->Printf("Watchpoint snapshot taken: '%s'\n", wp_sp->GetNewSnapshot().c_str());
+ }
+
+ // Now dump the snapshots we have taken.
+ Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
+ StreamSP output_sp = debugger.GetAsyncOutputStream ();
+ wp_sp->DumpSnapshots("!!! ", output_sp.get());
+ //output_sp->EOL();
+ output_sp->Flush();
+ }
if (m_should_stop && wp_sp->GetConditionText() != NULL)
{
@@ -564,6 +619,7 @@
// If the condition says to stop, we run the callback to further decide whether to stop.
if (m_should_stop)
{
+ StoppointCallbackContext context (event_ptr, exe_ctx, false);
bool stop_requested = wp_sp->InvokeCallback (&context);
// Also make sure that the callback hasn't continued the target.
// If it did, when we'll set m_should_stop to false and get out of here.