[Lldb-commits] [lldb] r332922 - Work around some odd instruction single-step behavior on macOS.

Jim Ingham via lldb-commits lldb-commits at lists.llvm.org
Tue May 22 09:37:01 PDT 2018


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 <labath at 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 at 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 at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits



More information about the lldb-commits mailing list