* pkg/proc: convert freebsd ptrace code to cgo There is little point in having cgo call a custom C function, when the same can be done directly from cgo (with less code and effort). Split the amd64 specific code into ptrace_freebsd_amd64.go. Also avoid mixing C.ptrace() with syscall.SYS_PTRACE. This will make further changes easier - no functional change intended. * pkg/proc: check return values of ptrace calls on freebsd The return values of the PT_GETNUMLWPS and PT_GETLWPLIST ptrace calls were previously unchecked. While these should not fail, panic instead of using -1 with slice allocation/handling. * pkg/proc: return *amd64util.AMD64Xstate from freebsd ptraceGetRegset Return a pointer to a struct, rather than a struct - this simplifies the code in both the caller and the ptraceGetRegset function, while also avoiding struct copying. * pkg/proc: fix floating point register setting on freebsd The original code could never work - PT_SETREGS on freebsd does not take an iovec, nor does it set FP registers. Furthermore, the xsave bytes were not stored in the amd64util.AMD64Xstate struct. Updates #3001 * pkg/proc: re-enable function call injection on freebsd Floating point registers can now be set and restored correctly. This is a partial revert of 51090f003bace1f8cc37b8480ffdb6f6cc91fa5a. Fixes #3001 * pkg/proc: deduplicate register setting code on freebsd
83 lines
2.1 KiB
Go
83 lines
2.1 KiB
Go
package native
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
sys "golang.org/x/sys/unix"
|
|
|
|
"github.com/go-delve/delve/pkg/dwarf/op"
|
|
"github.com/go-delve/delve/pkg/proc"
|
|
"github.com/go-delve/delve/pkg/proc/amd64util"
|
|
"github.com/go-delve/delve/pkg/proc/fbsdutil"
|
|
)
|
|
|
|
// SetPC sets RIP to the value specified by 'pc'.
|
|
func (thread *nativeThread) setPC(pc uint64) error {
|
|
ir, err := registers(thread)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r := ir.(*fbsdutil.AMD64Registers)
|
|
r.Regs.Rip = int64(pc)
|
|
thread.dbp.execPtraceFunc(func() { err = sys.PtraceSetRegs(thread.ID, (*sys.Reg)(r.Regs)) })
|
|
return err
|
|
}
|
|
|
|
// SetReg changes the value of the specified register.
|
|
func (thread *nativeThread) SetReg(regNum uint64, reg *op.DwarfRegister) error {
|
|
ir, err := registers(thread)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r := ir.(*fbsdutil.AMD64Registers)
|
|
fpchanged, err := r.SetReg(regNum, reg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return setRegisters(thread, r, fpchanged)
|
|
}
|
|
|
|
func registers(thread *nativeThread) (proc.Registers, error) {
|
|
var (
|
|
regs fbsdutil.AMD64PtraceRegs
|
|
err error
|
|
)
|
|
thread.dbp.execPtraceFunc(func() { err = sys.PtraceGetRegs(thread.ID, (*sys.Reg)(®s)) })
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var fsbase int64
|
|
thread.dbp.execPtraceFunc(func() { err = sys.PtraceGetFsBase(thread.ID, &fsbase) })
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r := fbsdutil.NewAMD64Registers(®s, uint64(fsbase), func(r *fbsdutil.AMD64Registers) error {
|
|
var floatLoadError error
|
|
r.Fpregs, r.Fpregset, floatLoadError = thread.fpRegisters()
|
|
return floatLoadError
|
|
})
|
|
return r, nil
|
|
}
|
|
|
|
func (thread *nativeThread) fpRegisters() (regs []proc.Register, fpregs *amd64util.AMD64Xstate, err error) {
|
|
thread.dbp.execPtraceFunc(func() { fpregs, err = ptraceGetRegset(thread.ID) })
|
|
if err != nil {
|
|
err = fmt.Errorf("could not get floating point registers: %v", err.Error())
|
|
}
|
|
regs = fpregs.Decode()
|
|
return
|
|
}
|
|
|
|
func setRegisters(thread *nativeThread, r *fbsdutil.AMD64Registers, setFP bool) (err error) {
|
|
thread.dbp.execPtraceFunc(func() {
|
|
err = sys.PtraceSetRegs(thread.ID, (*sys.Reg)(r.Regs))
|
|
if err != nil {
|
|
return
|
|
}
|
|
if setFP && r.Fpregset != nil {
|
|
err = ptraceSetRegset(thread.ID, r.Fpregset)
|
|
}
|
|
})
|
|
return
|
|
}
|