diff --git a/pkg/proc/amd64_arch.go b/pkg/proc/amd64_arch.go index 223c120f564704865e115af50776a00c918f0211..f7735b73342fe6ff71bb0b18d3e6d7209b4b2483 100644 --- a/pkg/proc/amd64_arch.go +++ b/pkg/proc/amd64_arch.go @@ -59,6 +59,13 @@ func (a *AMD64) BreakpointInstruction() []byte { return amd64BreakInstruction } +// BreakInstrMovesPC returns whether the +// breakpoint instruction will change the value +// of PC after being executed +func (a *AMD64) BreakInstrMovesPC() bool { + return true +} + // BreakpointSize returns the size of the // breakpoint instruction on this architecture. func (a *AMD64) BreakpointSize() int { diff --git a/pkg/proc/arch.go b/pkg/proc/arch.go index 7c14a64179403054fd8acf83b9243814bc427d84..30d80f27b613d8261a5b63b08aa55c3d937debcc 100644 --- a/pkg/proc/arch.go +++ b/pkg/proc/arch.go @@ -11,6 +11,7 @@ type Arch interface { PtrSize() int MinInstructionLength() int BreakpointInstruction() []byte + BreakInstrMovesPC() bool BreakpointSize() int DerefTLS() bool FixFrameUnwindContext(*frame.FrameContext, uint64, *BinaryInfo) *frame.FrameContext diff --git a/pkg/proc/arm64_arch.go b/pkg/proc/arm64_arch.go index b9474bd8e34cfbe304ef5fe0bc8a72f5194394b7..c44a85d0ad80fb8e22c7cd61e80db225e1a93837 100644 --- a/pkg/proc/arm64_arch.go +++ b/pkg/proc/arm64_arch.go @@ -59,6 +59,13 @@ func (a *ARM64) BreakpointInstruction() []byte { return arm64BreakInstruction } +// BreakInstrMovesPC returns whether the +// breakpoint instruction will change the value +// of PC after being executed +func (a *ARM64) BreakInstrMovesPC() bool { + return false +} + // BreakpointSize returns the size of the // breakpoint instruction on this architecture. func (a *ARM64) BreakpointSize() int { diff --git a/pkg/proc/native/threads.go b/pkg/proc/native/threads.go index 5034d63ba53c671ed009d903a0b4fa38f91a43f5..a3c4f61a89aae4cb5ff618684a232854c86c8959 100644 --- a/pkg/proc/native/threads.go +++ b/pkg/proc/native/threads.go @@ -119,9 +119,18 @@ func (t *Thread) SetCurrentBreakpoint(adjustPC bool) error { if err != nil { return err } + + // If the breakpoint instruction does not change the value + // of PC after being executed we should look for breakpoints + // with bp.Addr == PC and there is no need to call SetPC + // after finding one. + adjustPC = adjustPC && t.Arch().BreakInstrMovesPC() + if bp, ok := t.dbp.FindBreakpoint(pc, adjustPC); ok { - if err = t.SetPC(bp.Addr); err != nil { - return err + if adjustPC { + if err = t.SetPC(bp.Addr); err != nil { + return err + } } t.CurrentBreakpoint = bp.CheckCondition(t) if t.CurrentBreakpoint.Breakpoint != nil && t.CurrentBreakpoint.Active { diff --git a/pkg/proc/proc.go b/pkg/proc/proc.go index 3fdf9ad375ccce68abce7452d31b19bf4c58262a..8ae3d72ef00b945cd8de0ef6986c44e1fb3a34e6 100644 --- a/pkg/proc/proc.go +++ b/pkg/proc/proc.go @@ -213,8 +213,8 @@ func Continue(dbp Process) error { case loc.Fn.Name == "runtime.breakpoint": // In linux-arm64, PtraceSingleStep seems cannot step over BRK instruction // (linux-arm64 feature or kernel bug maybe). - if arch, ok := curthread.Arch().(*ARM64); ok { - curthread.SetPC(loc.PC + uint64(arch.BreakpointSize())) + if !curthread.Arch().BreakInstrMovesPC() { + curthread.SetPC(loc.PC + uint64(curthread.Arch().BreakpointSize())) } // Single-step current thread until we exit runtime.breakpoint and // runtime.Breakpoint. diff --git a/scripts/make.go b/scripts/make.go index bdba288d8ffb9c762a132f5688d2bb256601837e..dbb29e555c1012ca6a7f2c6a30d29585f754e0f6 100644 --- a/scripts/make.go +++ b/scripts/make.go @@ -79,7 +79,7 @@ Use the flags -s, -r and -b to specify which tests to run. Specifying nothing is `, Run: testCmd, } - test.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "Verbose tests") + test.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", true, "Verbose tests") test.PersistentFlags().StringVarP(&TestSet, "test-set", "s", "", `Select the set of tests to run, one of either: all tests all packages basic tests proc, integration and terminal