90 lines
2.3 KiB
Go
90 lines
2.3 KiB
Go
![]() |
package native
|
||
|
|
||
|
/*
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/ptrace.h>
|
||
|
*/
|
||
|
import "C"
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"unsafe"
|
||
|
|
||
|
"github.com/go-delve/delve/pkg/proc/amd64util"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
xsaveLen int
|
||
|
xsaveErr error
|
||
|
)
|
||
|
|
||
|
func ptraceGetXsaveLen(tid int) (int, error) {
|
||
|
var info C.struct_ptrace_xstate_info
|
||
|
ret, err := C.ptrace(C.PT_GETXSTATE_INFO, C.pid_t(tid), C.caddr_t(unsafe.Pointer(&info)), C.int(unsafe.Sizeof(info)))
|
||
|
if ret == 0 {
|
||
|
xsaveLen = int(info.xsave_len)
|
||
|
} else {
|
||
|
xsaveLen, xsaveErr = -1, err
|
||
|
return xsaveLen, fmt.Errorf("failed to get xstate info: %v", err)
|
||
|
}
|
||
|
return xsaveLen, nil
|
||
|
}
|
||
|
|
||
|
func ptraceXsaveLen(tid int) (int, error) {
|
||
|
if xsaveLen > 0 {
|
||
|
return xsaveLen, nil
|
||
|
}
|
||
|
if xsaveLen < 0 {
|
||
|
return xsaveLen, fmt.Errorf("failed to get xstate info: %v", xsaveErr)
|
||
|
}
|
||
|
return ptraceGetXsaveLen(tid)
|
||
|
}
|
||
|
|
||
|
// ptraceGetXsave gets the X86 XSAVE data for the given tid.
|
||
|
func ptraceGetXsave(tid int) ([]byte, error) {
|
||
|
len, err := ptraceXsaveLen(tid)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
xsaveBuf := make([]byte, len)
|
||
|
ret, err := C.ptrace(C.PT_GETXSTATE, C.pid_t(tid), C.caddr_t(unsafe.Pointer(&xsaveBuf[0])), C.int(len))
|
||
|
if ret != 0 {
|
||
|
return nil, fmt.Errorf("failed to get xstate: %v", err)
|
||
|
}
|
||
|
return xsaveBuf, nil
|
||
|
}
|
||
|
|
||
|
// ptraceSetXsave sets the X86 XSAVE data for the given tid.
|
||
|
func ptraceSetXsave(tid int, xsaveBuf []byte) error {
|
||
|
ret, err := C.ptrace(C.PT_SETXSTATE, C.pid_t(tid), C.caddr_t(unsafe.Pointer(&xsaveBuf[0])), C.int(len(xsaveBuf)))
|
||
|
if ret != 0 {
|
||
|
return fmt.Errorf("failed to set xstate: %v", err)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func ptraceGetRegset(id int) (*amd64util.AMD64Xstate, error) {
|
||
|
var regset amd64util.AMD64Xstate
|
||
|
ret, err := C.ptrace(C.PT_GETFPREGS, C.pid_t(id), C.caddr_t(unsafe.Pointer(®set.AMD64PtraceFpRegs)), C.int(0))
|
||
|
if ret != 0 {
|
||
|
return nil, fmt.Errorf("failed to get FP registers: %v", err)
|
||
|
}
|
||
|
regset.Xsave, err = ptraceGetXsave(id)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
err = amd64util.AMD64XstateRead(regset.Xsave, false, ®set)
|
||
|
return ®set, err
|
||
|
}
|
||
|
|
||
|
func ptraceSetRegset(id int, regset *amd64util.AMD64Xstate) error {
|
||
|
ret, err := C.ptrace(C.PT_SETFPREGS, C.pid_t(id), C.caddr_t(unsafe.Pointer(®set.AMD64PtraceFpRegs)), C.int(0))
|
||
|
if ret != 0 {
|
||
|
return fmt.Errorf("failed to set FP registers: %v", err)
|
||
|
}
|
||
|
if regset.Xsave != nil {
|
||
|
return ptraceSetXsave(id, regset.Xsave)
|
||
|
}
|
||
|
return nil
|
||
|
}
|