BTW, I think it is likely that we are being interrupted, but the bug happens very infrequently and generally goes away when I turn on more than a trivial amount of logging, so it's been hard to prove that yet.
Jim > On May 22, 2018, at 9:37 AM, Jim Ingham <jing...@apple.com> wrote: > > I haven't played around with this yet. Can it also provide enough memory to > pretend a stack trace? Most of the thread plan stuff will fall over pretty > early if it doesn't have at least a couple of frames? > > Jim > > >> On May 22, 2018, at 2:41 AM, Pavel Labath <lab...@google.com> wrote: >> >> 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