proc: skip trapthread for harcoded breakpoints after manual stop (#3582)

When using debugserver as a backend a manual stop request can end up
looking like an hardcoded breakpoint if the thread that receives the
stop request happens to be stopped right after a hardcoded breakpoint
(and the space between functions is filled with hardcoded breakpoints).
When creating hardcoded breakpoints we should ignore the trapthread if
a manual stop has been requested.

This problem made TestSetBreakpointWhileRunning and
TestSetFunctionBreakpointWhileRunning fail on macOS between 1.7% and 6%
of the time.

TestIssue1376 in rr_test.go used to pass accidentally, the stop when
the start of the recording was reached was mistaken for a hardcoded
breakpoint.
This commit is contained in:
Alessandro Arzilli 2023-11-27 18:17:58 +01:00 committed by GitHub
parent 4ed41e9060
commit 37db3e8e68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -221,6 +221,8 @@ func (grp *TargetGroup) Continue() error {
dbp.StopReason = StopWatchpoint
}
return conditionErrors(grp)
case stopReason == StopLaunched:
return nil
default:
// not a manual stop, not on runtime.Breakpoint, not on a breakpoint, just repeat
}
@ -1342,6 +1344,9 @@ func (t *Target) handleHardcodedBreakpoints(grp *TargetGroup, trapthread Thread,
if (thread.ThreadID() != trapthread.ThreadID()) && !thread.SoftExc() {
continue
}
if (thread.ThreadID() == trapthread.ThreadID()) && grp.cctx.GetManualStopRequested() {
continue
}
loc, err := thread.Location()
if err != nil || loc.Fn == nil {
@ -1371,7 +1376,11 @@ func (t *Target) handleHardcodedBreakpoints(grp *TargetGroup, trapthread Thread,
}
setHardcodedBreakpoint(thread, loc)
case g == nil || t.fncallForG[g.ID] == nil:
if isHardcodedBreakpoint(thread, loc.PC) > 0 {
// Check that PC is inside a function (not the entry point) and the
// preceding instruction is a hardcoded breakpoint.
// We explicitly check for entry points of functions because the space
// between functions is usually filled with hardcoded breakpoints.
if (loc.Fn == nil || loc.Fn.Entry != loc.PC) && isHardcodedBreakpoint(thread, loc.PC) > 0 {
stepOverBreak(thread, loc.PC)
setHardcodedBreakpoint(thread, loc)
}