gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/proc/native/registers_linux_ppc64le.go (about)

     1  package native
     2  
     3  import (
     4  	"debug/elf"
     5  	"syscall"
     6  	"unsafe"
     7  
     8  	"gitlab.com/Raven-IO/raven-delve/pkg/dwarf/op"
     9  	"gitlab.com/Raven-IO/raven-delve/pkg/proc"
    10  	"gitlab.com/Raven-IO/raven-delve/pkg/proc/linutil"
    11  	sys "golang.org/x/sys/unix"
    12  )
    13  
    14  const (
    15  	_PPC64LE_GPREGS_SIZE = 44 * 8
    16  	_PPC64LE_FPREGS_SIZE = 33*8 + 8
    17  )
    18  
    19  func ptraceGetGRegs(pid int, regs *linutil.PPC64LEPtraceRegs) (err error) {
    20  	sys.PtraceGetRegs(pid, (*sys.PtraceRegs)(regs))
    21  	if err == syscall.Errno(0) {
    22  		err = nil
    23  	}
    24  	return
    25  }
    26  
    27  func ptraceSetGRegs(pid int, regs *linutil.PPC64LEPtraceRegs) (err error) {
    28  	sys.PtraceSetRegs(pid, (*sys.PtraceRegs)(regs))
    29  	if err == syscall.Errno(0) {
    30  		err = nil
    31  	}
    32  	return
    33  }
    34  
    35  func ptraceGetFpRegset(tid int) (fpregset []byte, err error) {
    36  	var ppc64leFpregs [_PPC64LE_FPREGS_SIZE]byte
    37  	iov := sys.Iovec{Base: &ppc64leFpregs[0], Len: _PPC64LE_FPREGS_SIZE}
    38  	_, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETREGSET, uintptr(tid), uintptr(elf.NT_FPREGSET), uintptr(unsafe.Pointer(&iov)), 0, 0)
    39  	if err != syscall.Errno(0) {
    40  		if err == syscall.ENODEV {
    41  			err = nil
    42  		}
    43  		return
    44  	} else {
    45  		err = nil
    46  	}
    47  
    48  	fpregset = ppc64leFpregs[:iov.Len-8]
    49  	return fpregset, err
    50  }
    51  
    52  // SetPC sets PC to the value specified by 'pc'.
    53  func (t *nativeThread) setPC(pc uint64) error {
    54  	ir, err := registers(t)
    55  	if err != nil {
    56  		return err
    57  	}
    58  	r := ir.(*linutil.PPC64LERegisters)
    59  	r.Regs.Nip = pc
    60  	t.dbp.execPtraceFunc(func() { err = ptraceSetGRegs(t.ID, r.Regs) })
    61  	return err
    62  }
    63  
    64  // SetReg changes the value of the specified register.
    65  func (thread *nativeThread) SetReg(regNum uint64, reg *op.DwarfRegister) error {
    66  	ir, err := registers(thread)
    67  	if err != nil {
    68  		return err
    69  	}
    70  	r := ir.(*linutil.PPC64LERegisters)
    71  
    72  	fpchanged, err := r.SetReg(regNum, reg)
    73  	if err != nil {
    74  		return err
    75  	}
    76  	thread.dbp.execPtraceFunc(func() {
    77  		err = ptraceSetGRegs(thread.ID, r.Regs)
    78  		if err != syscall.Errno(0) && err != nil {
    79  			return
    80  		}
    81  		if fpchanged && r.Fpregset != nil {
    82  			iov := sys.Iovec{Base: &r.Fpregset[0], Len: uint64(len(r.Fpregset))}
    83  			_, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETREGSET, uintptr(thread.ID), uintptr(elf.NT_FPREGSET), uintptr(unsafe.Pointer(&iov)), 0, 0)
    84  		}
    85  	})
    86  	if err == syscall.Errno(0) {
    87  		err = nil
    88  	}
    89  	return err
    90  }
    91  
    92  func registers(thread *nativeThread) (proc.Registers, error) {
    93  	var (
    94  		regs linutil.PPC64LEPtraceRegs
    95  		err  error
    96  	)
    97  
    98  	thread.dbp.execPtraceFunc(func() { err = ptraceGetGRegs(thread.ID, &regs) })
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	r := linutil.NewPPC64LERegisters(&regs, func(r *linutil.PPC64LERegisters) error {
   103  		var floatLoadError error
   104  		r.Fpregs, r.Fpregset, floatLoadError = thread.fpRegisters()
   105  		return floatLoadError
   106  	})
   107  	return r, nil
   108  }