github.com/undoio/delve@v1.9.0/pkg/proc/native/ptrace_freebsd_amd64.go (about)

     1  package native
     2  
     3  /*
     4  #include <sys/types.h>
     5  #include <sys/ptrace.h>
     6  */
     7  import "C"
     8  
     9  import (
    10  	"fmt"
    11  	"unsafe"
    12  
    13  	"github.com/undoio/delve/pkg/proc/amd64util"
    14  )
    15  
    16  var (
    17  	xsaveLen int
    18  	xsaveErr error
    19  )
    20  
    21  func ptraceGetXsaveLen(tid int) (int, error) {
    22  	var info C.struct_ptrace_xstate_info
    23  	ret, err := C.ptrace(C.PT_GETXSTATE_INFO, C.pid_t(tid), C.caddr_t(unsafe.Pointer(&info)), C.int(unsafe.Sizeof(info)))
    24  	if ret == 0 {
    25  		xsaveLen = int(info.xsave_len)
    26  	} else {
    27  		xsaveLen, xsaveErr = -1, err
    28  		return xsaveLen, fmt.Errorf("failed to get xstate info: %v", err)
    29  	}
    30  	return xsaveLen, nil
    31  }
    32  
    33  func ptraceXsaveLen(tid int) (int, error) {
    34  	if xsaveLen > 0 {
    35  		return xsaveLen, nil
    36  	}
    37  	if xsaveLen < 0 {
    38  		return xsaveLen, fmt.Errorf("failed to get xstate info: %v", xsaveErr)
    39  	}
    40  	return ptraceGetXsaveLen(tid)
    41  }
    42  
    43  // ptraceGetXsave gets the X86 XSAVE data for the given tid.
    44  func ptraceGetXsave(tid int) ([]byte, error) {
    45  	len, err := ptraceXsaveLen(tid)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  	xsaveBuf := make([]byte, len)
    50  	ret, err := C.ptrace(C.PT_GETXSTATE, C.pid_t(tid), C.caddr_t(unsafe.Pointer(&xsaveBuf[0])), C.int(len))
    51  	if ret != 0 {
    52  		return nil, fmt.Errorf("failed to get xstate: %v", err)
    53  	}
    54  	return xsaveBuf, nil
    55  }
    56  
    57  // ptraceSetXsave sets the X86 XSAVE data for the given tid.
    58  func ptraceSetXsave(tid int, xsaveBuf []byte) error {
    59  	ret, err := C.ptrace(C.PT_SETXSTATE, C.pid_t(tid), C.caddr_t(unsafe.Pointer(&xsaveBuf[0])), C.int(len(xsaveBuf)))
    60  	if ret != 0 {
    61  		return fmt.Errorf("failed to set xstate: %v", err)
    62  	}
    63  	return nil
    64  }
    65  
    66  func ptraceGetRegset(id int) (*amd64util.AMD64Xstate, error) {
    67  	var regset amd64util.AMD64Xstate
    68  	ret, err := C.ptrace(C.PT_GETFPREGS, C.pid_t(id), C.caddr_t(unsafe.Pointer(&regset.AMD64PtraceFpRegs)), C.int(0))
    69  	if ret != 0 {
    70  		return nil, fmt.Errorf("failed to get FP registers: %v", err)
    71  	}
    72  	regset.Xsave, err = ptraceGetXsave(id)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	err = amd64util.AMD64XstateRead(regset.Xsave, false, &regset)
    77  	return &regset, err
    78  }
    79  
    80  func ptraceSetRegset(id int, regset *amd64util.AMD64Xstate) error {
    81  	ret, err := C.ptrace(C.PT_SETFPREGS, C.pid_t(id), C.caddr_t(unsafe.Pointer(&regset.AMD64PtraceFpRegs)), C.int(0))
    82  	if ret != 0 {
    83  		return fmt.Errorf("failed to set FP registers: %v", err)
    84  	}
    85  	if regset.Xsave != nil {
    86  		return ptraceSetXsave(id, regset.Xsave)
    87  	}
    88  	return nil
    89  }