proc/native: support watchpoints on Windows (#2651)
This commit is contained in:
parent
2b306e32a6
commit
b50052cc17
@ -25,7 +25,6 @@ Tests skipped by each supported backend:
|
|||||||
* 2 upstream issue - https://github.com/golang/go/issues/29322
|
* 2 upstream issue - https://github.com/golang/go/issues/29322
|
||||||
* rr skipped = 3
|
* rr skipped = 3
|
||||||
* 3 not implemented
|
* 3 not implemented
|
||||||
* windows skipped = 5
|
* windows skipped = 2
|
||||||
* 1 broken
|
* 1 broken
|
||||||
* 3 not implemented
|
|
||||||
* 1 upstream issue
|
* 1 upstream issue
|
||||||
|
|||||||
39
pkg/proc/native/hwbreak_amd64.go
Normal file
39
pkg/proc/native/hwbreak_amd64.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package native
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-delve/delve/pkg/proc"
|
||||||
|
"github.com/go-delve/delve/pkg/proc/amd64util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t *nativeThread) writeHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
||||||
|
return t.withDebugRegisters(func(drs *amd64util.DebugRegisters) error {
|
||||||
|
return drs.SetBreakpoint(idx, addr, wtype.Read(), wtype.Write(), wtype.Size())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *nativeThread) clearHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
||||||
|
return t.withDebugRegisters(func(drs *amd64util.DebugRegisters) error {
|
||||||
|
drs.ClearBreakpoint(idx)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *nativeThread) findHardwareBreakpoint() (*proc.Breakpoint, error) {
|
||||||
|
var retbp *proc.Breakpoint
|
||||||
|
err := t.withDebugRegisters(func(drs *amd64util.DebugRegisters) error {
|
||||||
|
ok, idx := drs.GetActiveBreakpoint()
|
||||||
|
if ok {
|
||||||
|
for _, bp := range t.dbp.Breakpoints().M {
|
||||||
|
if bp.WatchType != 0 && bp.HWBreakIndex == idx {
|
||||||
|
retbp = bp
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return retbp, nil
|
||||||
|
}
|
||||||
21
pkg/proc/native/hwbreak_other.go
Normal file
21
pkg/proc/native/hwbreak_other.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// +build !amd64
|
||||||
|
|
||||||
|
package native
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/go-delve/delve/pkg/proc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t *nativeThread) findHardwareBreakpoint() (*proc.Breakpoint, error) {
|
||||||
|
return nil, errors.New("hardware breakpoints not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *nativeThread) writeHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
||||||
|
return errors.New("hardware breakpoints not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *nativeThread) clearHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
||||||
|
return errors.New("hardware breakpoints not supported")
|
||||||
|
}
|
||||||
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/go-delve/delve/pkg/dwarf/op"
|
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||||
"github.com/go-delve/delve/pkg/proc"
|
"github.com/go-delve/delve/pkg/proc"
|
||||||
|
"github.com/go-delve/delve/pkg/proc/amd64util"
|
||||||
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -130,16 +131,8 @@ func (t *nativeThread) restoreRegisters(sr proc.Registers) error {
|
|||||||
panic(ErrNativeBackendDisabled)
|
panic(ErrNativeBackendDisabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) findHardwareBreakpoint() (*proc.Breakpoint, error) {
|
func (t *nativeThread) withDebugRegisters(f func(*amd64util.DebugRegisters) error) error {
|
||||||
panic(ErrNativeBackendDisabled)
|
return proc.ErrHWBreakUnsupported
|
||||||
}
|
|
||||||
|
|
||||||
func (t *nativeThread) writeHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
|
||||||
panic(ErrNativeBackendDisabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *nativeThread) clearHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
|
||||||
panic(ErrNativeBackendDisabled)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stopped returns whether the thread is stopped at
|
// Stopped returns whether the thread is stopped at
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import (
|
|||||||
sys "golang.org/x/sys/unix"
|
sys "golang.org/x/sys/unix"
|
||||||
|
|
||||||
"github.com/go-delve/delve/pkg/proc"
|
"github.com/go-delve/delve/pkg/proc"
|
||||||
|
"github.com/go-delve/delve/pkg/proc/amd64util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// waitStatus is a synonym for the platform-specific WaitStatus
|
// waitStatus is a synonym for the platform-specific WaitStatus
|
||||||
@ -133,14 +134,6 @@ func (t *nativeThread) restoreRegisters(sr proc.Registers) error {
|
|||||||
return errors.New("not implemented")
|
return errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) writeHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
func (t *nativeThread) withDebugRegisters(f func(*amd64util.DebugRegisters) error) error {
|
||||||
return proc.ErrHWBreakUnsupported
|
return proc.ErrHWBreakUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) clearHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
|
||||||
return proc.ErrHWBreakUnsupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *nativeThread) findHardwareBreakpoint() (*proc.Breakpoint, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import (
|
|||||||
sys "golang.org/x/sys/unix"
|
sys "golang.org/x/sys/unix"
|
||||||
|
|
||||||
"github.com/go-delve/delve/pkg/proc"
|
"github.com/go-delve/delve/pkg/proc"
|
||||||
|
"github.com/go-delve/delve/pkg/proc/amd64util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type waitStatus sys.WaitStatus
|
type waitStatus sys.WaitStatus
|
||||||
@ -121,14 +122,6 @@ func (t *nativeThread) ReadMemory(data []byte, addr uint64) (n int, err error) {
|
|||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) writeHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
func (t *nativeThread) withDebugRegisters(f func(*amd64util.DebugRegisters) error) error {
|
||||||
return proc.ErrHWBreakUnsupported
|
return proc.ErrHWBreakUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) clearHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
|
||||||
return proc.ErrHWBreakUnsupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *nativeThread) findHardwareBreakpoint() (*proc.Breakpoint, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@ -8,15 +8,3 @@ import (
|
|||||||
func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error {
|
func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error {
|
||||||
return fmt.Errorf("restore regs not supported on i386")
|
return fmt.Errorf("restore regs not supported on i386")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) writeHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
|
||||||
return proc.ErrHWBreakUnsupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *nativeThread) clearHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
|
||||||
return proc.ErrHWBreakUnsupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *nativeThread) findHardwareBreakpoint() (*proc.Breakpoint, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@ -86,36 +86,3 @@ func (t *nativeThread) withDebugRegisters(f func(*amd64util.DebugRegisters) erro
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) writeHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
|
||||||
return t.withDebugRegisters(func(drs *amd64util.DebugRegisters) error {
|
|
||||||
return drs.SetBreakpoint(idx, addr, wtype.Read(), wtype.Write(), wtype.Size())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *nativeThread) clearHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
|
||||||
return t.withDebugRegisters(func(drs *amd64util.DebugRegisters) error {
|
|
||||||
drs.ClearBreakpoint(idx)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *nativeThread) findHardwareBreakpoint() (*proc.Breakpoint, error) {
|
|
||||||
var retbp *proc.Breakpoint
|
|
||||||
err := t.withDebugRegisters(func(drs *amd64util.DebugRegisters) error {
|
|
||||||
ok, idx := drs.GetActiveBreakpoint()
|
|
||||||
if ok {
|
|
||||||
for _, bp := range t.dbp.Breakpoints().M {
|
|
||||||
if bp.WatchType != 0 && bp.HWBreakIndex == idx {
|
|
||||||
retbp = bp
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return retbp, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@ -42,15 +42,3 @@ func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error {
|
|||||||
}
|
}
|
||||||
return restoreRegistersErr
|
return restoreRegistersErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) writeHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
|
||||||
return proc.ErrHWBreakUnsupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *nativeThread) clearHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
|
||||||
return proc.ErrHWBreakUnsupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *nativeThread) findHardwareBreakpoint() (*proc.Breakpoint, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
sys "golang.org/x/sys/windows"
|
sys "golang.org/x/sys/windows"
|
||||||
|
|
||||||
"github.com/go-delve/delve/pkg/proc"
|
"github.com/go-delve/delve/pkg/proc"
|
||||||
|
"github.com/go-delve/delve/pkg/proc/amd64util"
|
||||||
"github.com/go-delve/delve/pkg/proc/winutil"
|
"github.com/go-delve/delve/pkg/proc/winutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -157,14 +158,25 @@ func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error {
|
|||||||
return _SetThreadContext(t.os.hThread, savedRegs.(*winutil.AMD64Registers).Context)
|
return _SetThreadContext(t.os.hThread, savedRegs.(*winutil.AMD64Registers).Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) writeHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
func (t *nativeThread) withDebugRegisters(f func(*amd64util.DebugRegisters) error) error {
|
||||||
return proc.ErrHWBreakUnsupported
|
context := winutil.NewCONTEXT()
|
||||||
}
|
context.ContextFlags = _CONTEXT_DEBUG_REGISTERS
|
||||||
|
|
||||||
func (t *nativeThread) clearHardwareBreakpoint(addr uint64, wtype proc.WatchType, idx uint8) error {
|
err := _GetThreadContext(t.os.hThread, context)
|
||||||
return proc.ErrHWBreakUnsupported
|
if err != nil {
|
||||||
}
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (t *nativeThread) findHardwareBreakpoint() (*proc.Breakpoint, error) {
|
drs := amd64util.NewDebugRegisters(&context.Dr0, &context.Dr1, &context.Dr2, &context.Dr3, &context.Dr6, &context.Dr7)
|
||||||
return nil, nil
|
|
||||||
|
err = f(drs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if drs.Dirty {
|
||||||
|
return _SetThreadContext(t.os.hThread, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5332,7 +5332,6 @@ func TestVariablesWithExternalLinking(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWatchpointsBasic(t *testing.T) {
|
func TestWatchpointsBasic(t *testing.T) {
|
||||||
skipOn(t, "not implemented", "windows")
|
|
||||||
skipOn(t, "not implemented", "freebsd")
|
skipOn(t, "not implemented", "freebsd")
|
||||||
skipOn(t, "not implemented", "darwin")
|
skipOn(t, "not implemented", "darwin")
|
||||||
skipOn(t, "not implemented", "386")
|
skipOn(t, "not implemented", "386")
|
||||||
@ -5378,7 +5377,6 @@ func TestWatchpointsBasic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWatchpointCounts(t *testing.T) {
|
func TestWatchpointCounts(t *testing.T) {
|
||||||
skipOn(t, "not implemented", "windows")
|
|
||||||
skipOn(t, "not implemented", "freebsd")
|
skipOn(t, "not implemented", "freebsd")
|
||||||
skipOn(t, "not implemented", "darwin")
|
skipOn(t, "not implemented", "darwin")
|
||||||
skipOn(t, "not implemented", "386")
|
skipOn(t, "not implemented", "386")
|
||||||
@ -5496,7 +5494,6 @@ func TestDwrapStartLocation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWatchpointStack(t *testing.T) {
|
func TestWatchpointStack(t *testing.T) {
|
||||||
skipOn(t, "not implemented", "windows")
|
|
||||||
skipOn(t, "not implemented", "freebsd")
|
skipOn(t, "not implemented", "freebsd")
|
||||||
skipOn(t, "not implemented", "darwin")
|
skipOn(t, "not implemented", "darwin")
|
||||||
skipOn(t, "not implemented", "386")
|
skipOn(t, "not implemented", "386")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user