This probably isn't what was happening here because you would have seen the extra stops in the logs, but one way I can think of we can end up at the same PC is if the process gets a signal while we're about to single-step it, in which case we need to execute the signal handler first and then get back to the instruction we were about to step over.
Anyway, the reason I am writing this is the testing situation. I think we already have something that should be able to mock a process to a sufficient level to test behavior like this: MockGdbServer in testcases/functionalities/gdb_remote_client. So, I believe it should be possible to trigger this via a sequence like: - connect to mock server (server pretends to be stopped at PC 0x1000) - breakpoint set --address 0x1010 - continue (server pretends to stop at 0x1010) - continue (after the first $s packet, server stays at 0x1010, after the second one it advances to 0x1011, after the final $c, return W00) - verify the expected packets were sent Have you tried using MockGdbServer in this way? regards, pl On Tue, 22 May 2018 at 01:10, Jim Ingham via lldb-commits < lldb-commits@lists.llvm.org> wrote: > Author: jingham > Date: Mon May 21 17:06:55 2018 > New Revision: 332922 > URL: http://llvm.org/viewvc/llvm-project?rev=332922&view=rev > Log: > Work around some odd instruction single-step behavior on macOS. > We've seen some cases on macOS where you go to instruction single > step (over a breakpoint), and single step returns but the instruction > hasn't been executed (and the pc hasn't moved.) The ThreadPlanStepOverBreakpoint > used to handle this case by accident, but the patches to handle two adjacent > breakpoints broke that accident. > This patch fixes the logic of ExplainsStop to explicitly handle the case where > the pc didn't move. It also adds a WillPop that re-enables the breakpoint we > were stepping over. We never want an unexpected path through the plan to > fool us into not doing that. > I have no idea how to make this bug happen. It is very inconsistent when it > occurs IRL. We really need a full MockProcess Plugin before we can start to write > tests for this sort of system hiccup. > <rdar://problem/38505726> > Modified: > lldb/trunk/include/lldb/Target/ThreadPlanStepOverBreakpoint.h > lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/desktop.xcscheme > lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp > Modified: lldb/trunk/include/lldb/Target/ThreadPlanStepOverBreakpoint.h > URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanStepOverBreakpoint.h?rev=332922&r1=332921&r2=332922&view=diff ============================================================================== > --- lldb/trunk/include/lldb/Target/ThreadPlanStepOverBreakpoint.h (original) > +++ lldb/trunk/include/lldb/Target/ThreadPlanStepOverBreakpoint.h Mon May 21 17:06:55 2018 > @@ -31,6 +31,7 @@ public: > bool StopOthers() override; > lldb::StateType GetPlanRunState() override; > bool WillStop() override; > + void WillPop() override; > bool MischiefManaged() override; > void ThreadDestroyed() override; > void SetAutoContinue(bool do_it); > Modified: lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/desktop.xcscheme > URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/desktop.xcscheme?rev=332922&r1=332921&r2=332922&view=diff ============================================================================== > --- lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/desktop.xcscheme (original) > +++ lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/desktop.xcscheme Mon May 21 17:06:55 2018 > @@ -26,10 +26,18 @@ > buildConfiguration = "Debug" > selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" > selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" > - language = "" > shouldUseLaunchSchemeArgsEnv = "YES"> > <Testables> > </Testables> > + <MacroExpansion> > + <BuildableReference > + BuildableIdentifier = "primary" > + BlueprintIdentifier = "26F5C26910F3D9A4009D5894" > + BuildableName = "lldb" > + BlueprintName = "lldb-tool" > + ReferencedContainer = "container:lldb.xcodeproj"> > + </BuildableReference> > + </MacroExpansion> > <AdditionalOptions> > </AdditionalOptions> > </TestAction> > @@ -37,22 +45,22 @@ > buildConfiguration = "DebugClang" > selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" > selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" > - language = "" > - launchStyle = "0" > + launchStyle = "1" > useCustomWorkingDirectory = "NO" > ignoresPersistentStateOnLaunch = "NO" > debugDocumentVersioning = "YES" > debugServiceExtension = "internal" > allowLocationSimulation = "YES"> > - <MacroExpansion> > + <BuildableProductRunnable > + runnableDebuggingMode = "0"> > <BuildableReference > BuildableIdentifier = "primary" > - BlueprintIdentifier = "26CEF3B114FD592B007286B2" > - BuildableName = "desktop" > - BlueprintName = "desktop" > + BlueprintIdentifier = "26F5C26910F3D9A4009D5894" > + BuildableName = "lldb" > + BlueprintName = "lldb-tool" > ReferencedContainer = "container:lldb.xcodeproj"> > </BuildableReference> > - </MacroExpansion> > + </BuildableProductRunnable> > <AdditionalOptions> > </AdditionalOptions> > </LaunchAction> > Modified: lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp > URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp?rev=332922&r1=332921&r2=332922&view=diff ============================================================================== > --- lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp (original) > +++ lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp Mon May 21 17:06:55 2018 > @@ -68,27 +68,47 @@ bool ThreadPlanStepOverBreakpoint::DoPla > // next instruction also contained a breakpoint. > StopReason reason = stop_info_sp->GetStopReason(); > + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); > + > + if (log) > + log->Printf("Step over breakpoint stopped for reason: %s.", > + Thread::StopReasonAsCString(reason)); > + > switch (reason) { > - case eStopReasonTrace: > - case eStopReasonNone: > - return true; > - case eStopReasonBreakpoint: > - // It's a little surprising that we stop here for a breakpoint hit. > - // However, when you single step ONTO a breakpoint we still want to call > - // that a breakpoint hit, and trigger the actions, etc. Otherwise you > - // would see the PC at the breakpoint without having triggered the > - // actions, then you'd continue, the PC wouldn't change, and you'd see > - // the breakpoint hit, which would be odd. So the lower levels fake "step > - // onto breakpoint address" and return that as a breakpoint hit. So our > - // trace step COULD appear as a breakpoint hit if the next instruction > - // also contained a breakpoint. We don't want to handle that, since we > - // really don't know what to do with breakpoint hits. But make sure we > - // don't set ourselves to auto-continue or we'll wrench control away from > - // the plans that can deal with this. > - SetAutoContinue(false); > - return false; > - default: > - return false; > + case eStopReasonTrace: > + case eStopReasonNone: > + return true; > + case eStopReasonBreakpoint: > + { > + // It's a little surprising that we stop here for a breakpoint hit. > + // However, when you single step ONTO a breakpoint we still want to call > + // that a breakpoint hit, and trigger the actions, etc. Otherwise you > + // would see the PC at the breakpoint without having triggered the > + // actions, then you'd continue, the PC wouldn't change, and you'd see > + // the breakpoint hit, which would be odd. So the lower levels fake > + // "step onto breakpoint address" and return that as a breakpoint hit. > + // So our trace step COULD appear as a breakpoint hit if the next > + // instruction also contained a breakpoint. We don't want to handle > + // that, since we really don't know what to do with breakpoint hits. > + // But make sure we don't set ourselves to auto-continue or we'll wrench > + // control away from the plans that can deal with this. > + // Be careful, however, as we may have "seen a breakpoint under the PC > + // because we stopped without changing the PC, in which case we do want > + // to re-claim this stop so we'll try again. > + lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC(); > + > + if (pc_addr == m_breakpoint_addr) { > + if (log) > + log->Printf("Got breakpoint stop reason but pc: %" PRIu64 > + "hasn't changed.", pc_addr); > + return true; > + } > + > + SetAutoContinue(false); > + return false; > + } > + default: > + return false; > } > } > return false; > @@ -110,8 +130,10 @@ bool ThreadPlanStepOverBreakpoint::DoWil > BreakpointSiteSP bp_site_sp( > m_thread.GetProcess()->GetBreakpointSiteList().FindByAddress( > m_breakpoint_addr)); > - if (bp_site_sp && bp_site_sp->IsEnabled()) > + if (bp_site_sp && bp_site_sp->IsEnabled()) { > m_thread.GetProcess()->DisableBreakpointSite(bp_site_sp.get()); > + m_reenabled_breakpoint_site = false; > + } > } > return true; > } > @@ -121,6 +143,10 @@ bool ThreadPlanStepOverBreakpoint::WillS > return true; > } > +void ThreadPlanStepOverBreakpoint::WillPop() { > + ReenableBreakpointSite(); > +} > + > bool ThreadPlanStepOverBreakpoint::MischiefManaged() { > lldb::addr_t pc_addr = m_thread.GetRegisterContext()->GetPC(); > _______________________________________________ > lldb-commits mailing list > lldb-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits