From 5d88a068eed8625b9668db9f6b254ae5d2a0e187 Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Tue, 16 Oct 2012 00:09:33 +0000 Subject: [PATCH] Patch from Matt Kopec to fix the problem that if two breakpoints were set on consecutive addresses, the continue from the first breakpoint would skip the second. llvm-svn: 166000 --- lldb/include/lldb/Target/Thread.h | 4 +++ lldb/source/Core/Debugger.cpp | 4 +-- .../Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp | 3 +++ .../Plugins/Process/Utility/ThreadMemory.cpp | 3 +++ .../Plugins/Process/gdb-remote/ThreadGDBRemote.cpp | 3 +++ .../Plugins/Process/mach-core/ThreadMachCore.cpp | 3 +++ lldb/source/Target/Process.cpp | 5 ++-- lldb/source/Target/Thread.cpp | 29 +++++++++++++++++++--- lldb/test/lang/cpp/dynamic-value/pass-to-base.cpp | 3 ++- 9 files changed, 48 insertions(+), 9 deletions(-) diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 8ca0729..70f66c2 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -858,6 +858,10 @@ protected: virtual lldb_private::Unwind * GetUnwinder (); + // Check to see whether the thread is still at the last breakpoint hit that stopped it. + virtual const bool + IsStillAtLastBreakpointHit(); + lldb::StackFrameListSP GetStackFrameList (); diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 86b0cf5..5941496 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1952,7 +1952,7 @@ Debugger::FormatPrompt else if (::strncmp (var_name_begin, "stop-reason}", strlen("stop-reason}")) == 0) { StopInfoSP stop_info_sp = thread->GetStopInfo (); - if (stop_info_sp) + if (stop_info_sp && stop_info_sp->IsValid()) { cstr = stop_info_sp->GetDescription(); if (cstr && cstr[0]) @@ -1965,7 +1965,7 @@ Debugger::FormatPrompt else if (::strncmp (var_name_begin, "return-value}", strlen("return-value}")) == 0) { StopInfoSP stop_info_sp = thread->GetStopInfo (); - if (stop_info_sp) + if (stop_info_sp && stop_info_sp->IsValid()) { ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); if (return_valobj_sp) diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp index 567658d..3e42cf5 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp @@ -179,6 +179,9 @@ ThreadKDP::GetPrivateStopReason () if (m_thread_stop_reason_stop_id != process_stop_id || (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid())) { + if (IsStillAtLastBreakpointHit()) + return m_actual_stop_info_sp; + if (m_cached_stop_info_sp) SetStopInfo (m_cached_stop_info_sp); else diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp index 9e4c6d6..cd3bd8c 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp @@ -107,6 +107,9 @@ ThreadMemory::GetPrivateStopReason () if (m_thread_stop_reason_stop_id != process_stop_id || (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid())) { + if (IsStillAtLastBreakpointHit()) + return m_actual_stop_info_sp; + // If GetGDBProcess().SetThreadStopInfo() doesn't find a stop reason // for this thread, then m_actual_stop_info_sp will not ever contain // a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false" diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index b63b42d..36fa418 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -225,6 +225,9 @@ ThreadGDBRemote::GetPrivateStopReason () if (m_thread_stop_reason_stop_id != process_stop_id || (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid())) { + if (IsStillAtLastBreakpointHit()) + return m_actual_stop_info_sp; + // If GetGDBProcess().SetThreadStopInfo() doesn't find a stop reason // for this thread, then m_actual_stop_info_sp will not ever contain // a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false" diff --git a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp index 001cda1..f88c488 100644 --- a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp @@ -136,6 +136,9 @@ ThreadMachCore::GetPrivateStopReason () if (m_thread_stop_reason_stop_id != process_stop_id || (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid())) { + if (IsStillAtLastBreakpointHit()) + return m_actual_stop_info_sp; + // TODO: can we query the initial state of the thread here? // For now I am just going to pretend that a SIGSTOP happened. diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 077b970..3b37796 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -3741,7 +3741,7 @@ Process::ProcessEventData::DoOnRemoval (Event *event_ptr) } StopInfoSP stop_info_sp = thread_sp->GetStopInfo (); - if (stop_info_sp) + if (stop_info_sp && stop_info_sp->IsValid()) { stop_info_sp->PerformAction(event_ptr); // The stop action might restart the target. If it does, then we want to mark that in the @@ -4905,7 +4905,8 @@ Process::GetThreadStatus (Stream &strm, { if (only_threads_with_stop_reason) { - if (thread->GetStopInfo().get() == NULL) + StopInfoSP stop_info_sp = thread->GetStopInfo(); + if (stop_info_sp.get() == NULL || !stop_info_sp->IsValid()) continue; } thread->GetStatus (strm, diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 6e505f2..39157dd 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -440,9 +440,11 @@ Thread::SetupForResume () // telling the current plan it will resume, since we might change what the current // plan is. - lldb::addr_t pc = GetRegisterContext()->GetPC(); - BreakpointSiteSP bp_site_sp = GetProcess()->GetBreakpointSiteList().FindByAddress(pc); - if (bp_site_sp && bp_site_sp->IsEnabled()) + StopReason stop_reason = lldb::eStopReasonInvalid; + StopInfoSP stop_info_sp = GetStopInfo(); + if (stop_info_sp.get()) + stop_reason = stop_info_sp->GetStopReason(); + if (stop_reason == lldb::eStopReasonBreakpoint) { // Note, don't assume there's a ThreadPlanStepOverBreakpoint, the target may not require anything // special to step over a breakpoint. @@ -506,7 +508,7 @@ Thread::WillResume (StateType resume_state) // If the WillResume for the plan says we are faking a resume, then it will have set an appropriate stop info. // In that case, don't reset it here. - if (need_to_resume) + if (need_to_resume && resume_state != eStateSuspended) { m_actual_stop_info_sp.reset(); } @@ -1713,3 +1715,22 @@ Thread::Flush () ClearStackFrames (); m_reg_context_sp.reset(); } + +const bool +Thread::IsStillAtLastBreakpointHit () +{ + // If we are currently stopped at a breakpoint, always return that stopinfo and don't reset it. + // This allows threads to maintain their breakpoint stopinfo, such as when thread-stepping in + // multithreaded programs. + if (m_actual_stop_info_sp) { + StopReason stop_reason = m_actual_stop_info_sp->GetStopReason(); + if (stop_reason == lldb::eStopReasonBreakpoint) { + uint64_t value = m_actual_stop_info_sp->GetValue(); + lldb::addr_t pc = GetRegisterContext()->GetPC(); + BreakpointSiteSP bp_site_sp = GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + if (bp_site_sp && value == bp_site_sp->GetID()) + return true; + } + } + return false; +} diff --git a/lldb/test/lang/cpp/dynamic-value/pass-to-base.cpp b/lldb/test/lang/cpp/dynamic-value/pass-to-base.cpp index a817bad..2bccf33 100644 --- a/lldb/test/lang/cpp/dynamic-value/pass-to-base.cpp +++ b/lldb/test/lang/cpp/dynamic-value/pass-to-base.cpp @@ -23,7 +23,8 @@ public: doSomething (A &anotherA) { printf ("In A %p doing something with %d.\n", this, m_a_value); - printf ("Also have another A at %p: %d.\n", &anotherA, anotherA.Value()); // Break here in doSomething. + int tmp_value = anotherA.Value(); + printf ("Also have another A at %p: %d.\n", &anotherA, tmp_value); // Break here in doSomething. } int -- 2.7.4