Skip to content

Commit

Permalink
proc/native: separate amd64-arch code
Browse files Browse the repository at this point in the history
As proc/native is arch related, it should move some functions to arch-relate file. And this patch can help us to separate the architecture code, make code tidy. So that the merge of arm64 code later will not cause chaos.(go-delve#118)
  • Loading branch information
hengwu0 authored and derekparker committed Nov 27, 2019
1 parent b3d2cbb commit ba29709
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 72 deletions.
33 changes: 0 additions & 33 deletions pkg/proc/native/ptrace_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"unsafe"

sys "golang.org/x/sys/unix"

"github.com/go-delve/delve/pkg/proc/linutil"
)

// PtraceAttach executes the sys.PtraceAttach call.
Expand Down Expand Up @@ -51,34 +49,3 @@ func PtracePeekUser(tid int, off uintptr) (uintptr, error) {
}
return val, nil
}

// PtraceGetRegset returns floating point registers of the specified thread
// using PTRACE.
// See amd64_linux_fetch_inferior_registers in gdb/amd64-linux-nat.c.html
// and amd64_supply_xsave in gdb/amd64-tdep.c.html
// and Section 13.1 (and following) of Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1: Basic Architecture
func PtraceGetRegset(tid int) (regset linutil.AMD64Xstate, err error) {
_, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETFPREGS, uintptr(tid), uintptr(0), uintptr(unsafe.Pointer(&regset.AMD64PtraceFpRegs)), 0, 0)
if err == syscall.Errno(0) || err == syscall.ENODEV {
// ignore ENODEV, it just means this CPU doesn't have X87 registers (??)
err = nil
}

var xstateargs [_X86_XSTATE_MAX_SIZE]byte
iov := sys.Iovec{Base: &xstateargs[0], Len: _X86_XSTATE_MAX_SIZE}
_, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETREGSET, uintptr(tid), _NT_X86_XSTATE, uintptr(unsafe.Pointer(&iov)), 0, 0)
if err != syscall.Errno(0) {
if err == syscall.ENODEV || err == syscall.EIO {
// ignore ENODEV, it just means this CPU or kernel doesn't support XSTATE, see https://github.com/go-delve/delve/issues/1022
// also ignore EIO, it means that we are running on an old kernel (pre 2.6.34) and PTRACE_GETREGSET is not implemented
err = nil
}
return
} else {
err = nil
}

regset.Xsave = xstateargs[:iov.Len]
err = linutil.AMD64XstateRead(regset.Xsave, false, &regset)
return
}
41 changes: 41 additions & 0 deletions pkg/proc/native/ptrace_linux_amd64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package native

import (
"syscall"
"unsafe"

sys "golang.org/x/sys/unix"

"github.com/go-delve/delve/pkg/proc/linutil"
)

// PtraceGetRegset returns floating point registers of the specified thread
// using PTRACE.
// See amd64_linux_fetch_inferior_registers in gdb/amd64-linux-nat.c.html
// and amd64_supply_xsave in gdb/amd64-tdep.c.html
// and Section 13.1 (and following) of Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1: Basic Architecture
func PtraceGetRegset(tid int) (regset linutil.AMD64Xstate, err error) {
_, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETFPREGS, uintptr(tid), uintptr(0), uintptr(unsafe.Pointer(&regset.AMD64PtraceFpRegs)), 0, 0)
if err == syscall.Errno(0) || err == syscall.ENODEV {
// ignore ENODEV, it just means this CPU doesn't have X87 registers (??)
err = nil
}

var xstateargs [_X86_XSTATE_MAX_SIZE]byte
iov := sys.Iovec{Base: &xstateargs[0], Len: _X86_XSTATE_MAX_SIZE}
_, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETREGSET, uintptr(tid), _NT_X86_XSTATE, uintptr(unsafe.Pointer(&iov)), 0, 0)
if err != syscall.Errno(0) {
if err == syscall.ENODEV || err == syscall.EIO {
// ignore ENODEV, it just means this CPU or kernel doesn't support XSTATE, see https://github.com/go-delve/delve/issues/1022
// also ignore EIO, it means that we are running on an old kernel (pre 2.6.34) and PTRACE_GETREGSET is not implemented
err = nil
}
return
} else {
err = nil
}

regset.Xsave = xstateargs[:iov.Len]
err = linutil.AMD64XstateRead(regset.Xsave, false, &regset)
return
}
39 changes: 0 additions & 39 deletions pkg/proc/native/threads_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ package native

import (
"fmt"
"syscall"
"unsafe"

sys "golang.org/x/sys/unix"

"github.com/go-delve/delve/pkg/proc"
"github.com/go-delve/delve/pkg/proc/linutil"
)

type WaitStatus sys.WaitStatus
Expand Down Expand Up @@ -86,42 +83,6 @@ func (t *Thread) Blocked() bool {
return false
}

func (t *Thread) restoreRegisters(savedRegs proc.Registers) error {
sr := savedRegs.(*linutil.AMD64Registers)

var restoreRegistersErr error
t.dbp.execPtraceFunc(func() {
oldRegs := (*sys.PtraceRegs)(sr.Regs)

var currentRegs sys.PtraceRegs
restoreRegistersErr = sys.PtraceGetRegs(t.ID, &currentRegs)
if restoreRegistersErr != nil {
return
}
// restoreRegisters is only supposed to restore CPU registers, not FS_BASE and GS_BASE
oldRegs.Fs_base = currentRegs.Fs_base
oldRegs.Gs_base = currentRegs.Gs_base

restoreRegistersErr = sys.PtraceSetRegs(t.ID, oldRegs)

if restoreRegistersErr != nil {
return
}
if sr.Fpregset.Xsave != nil {
iov := sys.Iovec{Base: &sr.Fpregset.Xsave[0], Len: uint64(len(sr.Fpregset.Xsave))}
_, _, restoreRegistersErr = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETREGSET, uintptr(t.ID), _NT_X86_XSTATE, uintptr(unsafe.Pointer(&iov)), 0, 0)
return
}

_, _, restoreRegistersErr = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETFPREGS, uintptr(t.ID), uintptr(0), uintptr(unsafe.Pointer(&sr.Fpregset.AMD64PtraceFpRegs)), 0, 0)
return
})
if restoreRegistersErr == syscall.Errno(0) {
restoreRegistersErr = nil
}
return restoreRegistersErr
}

func (t *Thread) WriteMemory(addr uintptr, data []byte) (written int, err error) {
if t.dbp.exited {
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
Expand Down
47 changes: 47 additions & 0 deletions pkg/proc/native/threads_linux_amd64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package native

import (
"syscall"
"unsafe"

sys "golang.org/x/sys/unix"

"github.com/go-delve/delve/pkg/proc"
"github.com/go-delve/delve/pkg/proc/linutil"
)

func (t *Thread) restoreRegisters(savedRegs proc.Registers) error {
sr := savedRegs.(*linutil.AMD64Registers)

var restoreRegistersErr error
t.dbp.execPtraceFunc(func() {
oldRegs := (*sys.PtraceRegs)(sr.Regs)

var currentRegs sys.PtraceRegs
restoreRegistersErr = sys.PtraceGetRegs(t.ID, &currentRegs)
if restoreRegistersErr != nil {
return
}
// restoreRegisters is only supposed to restore CPU registers, not FS_BASE and GS_BASE
oldRegs.Fs_base = currentRegs.Fs_base
oldRegs.Gs_base = currentRegs.Gs_base

restoreRegistersErr = sys.PtraceSetRegs(t.ID, oldRegs)

if restoreRegistersErr != nil {
return
}
if sr.Fpregset.Xsave != nil {
iov := sys.Iovec{Base: &sr.Fpregset.Xsave[0], Len: uint64(len(sr.Fpregset.Xsave))}
_, _, restoreRegistersErr = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETREGSET, uintptr(t.ID), _NT_X86_XSTATE, uintptr(unsafe.Pointer(&iov)), 0, 0)
return
}

_, _, restoreRegistersErr = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETFPREGS, uintptr(t.ID), uintptr(0), uintptr(unsafe.Pointer(&sr.Fpregset.AMD64PtraceFpRegs)), 0, 0)
return
})
if restoreRegistersErr == syscall.Errno(0) {
restoreRegistersErr = nil
}
return restoreRegistersErr
}

0 comments on commit ba29709

Please sign in to comment.