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

     1  package native
     2  
     3  import (
     4  	"bytes"
     5  
     6  	sys "golang.org/x/sys/unix"
     7  
     8  	"gitlab.com/Raven-IO/raven-delve/pkg/proc"
     9  	"gitlab.com/Raven-IO/raven-delve/pkg/proc/amd64util"
    10  	"gitlab.com/Raven-IO/raven-delve/pkg/proc/fbsdutil"
    11  )
    12  
    13  type waitStatus sys.WaitStatus
    14  
    15  // osSpecificDetails hold FreeBSD specific process details.
    16  type osSpecificDetails struct {
    17  	registers sys.Reg
    18  }
    19  
    20  func (procgrp *processGroup) singleStep(t *nativeThread) (err error) {
    21  	t.dbp.execPtraceFunc(func() { err = ptraceSetStep(t.ID) })
    22  	if err != nil {
    23  		return err
    24  	}
    25  	defer func() {
    26  		t.dbp.execPtraceFunc(func() { ptraceClearStep(t.ID) })
    27  	}()
    28  
    29  	t.dbp.execPtraceFunc(func() { err = ptraceResume(t.ID) })
    30  	if err != nil {
    31  		return err
    32  	}
    33  	defer func() {
    34  		t.dbp.execPtraceFunc(func() { ptraceSuspend(t.ID) })
    35  	}()
    36  
    37  	sig := 0
    38  	for {
    39  		err = t.dbp.ptraceCont(sig)
    40  		sig = 0
    41  		if err != nil {
    42  			return err
    43  		}
    44  
    45  		trapthread, err := t.dbp.trapWaitInternal(-1, trapWaitStepping)
    46  		if err != nil {
    47  			return err
    48  		}
    49  
    50  		status := ((*sys.WaitStatus)(trapthread.Status))
    51  
    52  		if trapthread.ID == t.ID {
    53  			switch s := status.StopSignal(); s {
    54  			case sys.SIGTRAP:
    55  				return nil
    56  			case sys.SIGSTOP:
    57  				// delayed SIGSTOP, ignore it
    58  			case sys.SIGILL, sys.SIGBUS, sys.SIGFPE, sys.SIGSEGV:
    59  				// propagate signals that can be caused by current instruction
    60  				sig = int(s)
    61  			default:
    62  				t.dbp.os.delayedSignal = s
    63  			}
    64  		} else {
    65  			if status.StopSignal() == sys.SIGTRAP {
    66  				t.dbp.os.trapThreads = append(t.dbp.os.trapThreads, trapthread.ID)
    67  			} else {
    68  				t.dbp.os.delayedSignal = status.StopSignal()
    69  			}
    70  		}
    71  	}
    72  }
    73  
    74  func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error {
    75  	sr := savedRegs.(*fbsdutil.AMD64Registers)
    76  	return setRegisters(t, sr, true)
    77  }
    78  
    79  func (t *nativeThread) WriteMemory(addr uint64, data []byte) (written int, err error) {
    80  	if ok, err := t.dbp.Valid(); !ok {
    81  		return 0, err
    82  	}
    83  	if len(data) == 0 {
    84  		return 0, nil
    85  	}
    86  	t.dbp.execPtraceFunc(func() { written, err = ptraceWriteData(t.ID, uintptr(addr), data) })
    87  	return written, err
    88  }
    89  
    90  func (t *nativeThread) ReadMemory(data []byte, addr uint64) (n int, err error) {
    91  	if ok, err := t.dbp.Valid(); !ok {
    92  		return 0, err
    93  	}
    94  	if len(data) == 0 {
    95  		return 0, nil
    96  	}
    97  	t.dbp.execPtraceFunc(func() { n, err = ptraceReadData(t.ID, uintptr(addr), data) })
    98  	return n, err
    99  }
   100  
   101  func (t *nativeThread) withDebugRegisters(f func(*amd64util.DebugRegisters) error) error {
   102  	return proc.ErrHWBreakUnsupported
   103  }
   104  
   105  // SoftExc returns true if this thread received a software exception during the last resume.
   106  func (t *nativeThread) SoftExc() bool {
   107  	return false
   108  }
   109  
   110  func (t *nativeThread) atHardcodedBreakpoint(pc uint64) bool {
   111  	for _, bpinstr := range [][]byte{
   112  		t.dbp.BinInfo().Arch.BreakpointInstruction(),
   113  		t.dbp.BinInfo().Arch.AltBreakpointInstruction()} {
   114  		if bpinstr == nil {
   115  			continue
   116  		}
   117  		buf := make([]byte, len(bpinstr))
   118  		_, _ = t.ReadMemory(buf, pc-uint64(len(buf)))
   119  		if bytes.Equal(buf, bpinstr) {
   120  			return true
   121  		}
   122  	}
   123  	return false
   124  }