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

     1  package native
     2  
     3  // #include <sys/thr.h>
     4  import "C"
     5  
     6  import (
     7  	"fmt"
     8  	"github.com/undoio/delve/pkg/proc/fbsdutil"
     9  
    10  	sys "golang.org/x/sys/unix"
    11  
    12  	"github.com/undoio/delve/pkg/proc"
    13  	"github.com/undoio/delve/pkg/proc/amd64util"
    14  )
    15  
    16  type waitStatus sys.WaitStatus
    17  
    18  // osSpecificDetails hold FreeBSD specific process details.
    19  type osSpecificDetails struct {
    20  	registers sys.Reg
    21  }
    22  
    23  func (t *nativeThread) stop() (err error) {
    24  	_, err = C.thr_kill2(C.pid_t(t.dbp.pid), C.long(t.ID), C.int(sys.SIGSTOP))
    25  	if err != nil {
    26  		err = fmt.Errorf("stop err %s on thread %d", err, t.ID)
    27  		return
    28  	}
    29  	// If the process is stopped, we must continue it so it can receive the
    30  	// signal
    31  	t.dbp.execPtraceFunc(func() { err = ptraceCont(t.dbp.pid, 0) })
    32  	if err != nil {
    33  		return err
    34  	}
    35  	_, _, err = t.dbp.waitFast(t.dbp.pid)
    36  	if err != nil {
    37  		err = fmt.Errorf("wait err %s on thread %d", err, t.ID)
    38  		return
    39  	}
    40  	return
    41  }
    42  
    43  func (t *nativeThread) Stopped() bool {
    44  	state := status(t.dbp.pid)
    45  	return state == statusStopped
    46  }
    47  
    48  func (t *nativeThread) resume() error {
    49  	return t.resumeWithSig(0)
    50  }
    51  
    52  func (t *nativeThread) resumeWithSig(sig int) (err error) {
    53  	t.dbp.execPtraceFunc(func() { err = ptraceCont(t.ID, sig) })
    54  	return
    55  }
    56  
    57  func (t *nativeThread) singleStep() (err error) {
    58  	t.dbp.execPtraceFunc(func() { err = ptraceSingleStep(t.ID) })
    59  	if err != nil {
    60  		return err
    61  	}
    62  	for {
    63  		th, err := t.dbp.trapWait(t.dbp.pid)
    64  		if err != nil {
    65  			return err
    66  		}
    67  		if th.ID == t.ID {
    68  			break
    69  		}
    70  		t.dbp.execPtraceFunc(func() { err = ptraceCont(th.ID, 0) })
    71  		if err != nil {
    72  			return err
    73  		}
    74  	}
    75  	return nil
    76  }
    77  
    78  func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error {
    79  	sr := savedRegs.(*fbsdutil.AMD64Registers)
    80  	return setRegisters(t, sr, true)
    81  }
    82  
    83  func (t *nativeThread) WriteMemory(addr uint64, data []byte) (written int, err error) {
    84  	if t.dbp.exited {
    85  		return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
    86  	}
    87  	if len(data) == 0 {
    88  		return 0, nil
    89  	}
    90  	t.dbp.execPtraceFunc(func() { written, err = ptraceWriteData(t.ID, uintptr(addr), data) })
    91  	return written, err
    92  }
    93  
    94  func (t *nativeThread) ReadMemory(data []byte, addr uint64) (n int, err error) {
    95  	if t.dbp.exited {
    96  		return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
    97  	}
    98  	if len(data) == 0 {
    99  		return 0, nil
   100  	}
   101  	t.dbp.execPtraceFunc(func() { n, err = ptraceReadData(t.ID, uintptr(addr), data) })
   102  	return n, err
   103  }
   104  
   105  func (t *nativeThread) withDebugRegisters(f func(*amd64util.DebugRegisters) error) error {
   106  	return proc.ErrHWBreakUnsupported
   107  }
   108  
   109  // SoftExc returns true if this thread received a software exception during the last resume.
   110  func (t *nativeThread) SoftExc() bool {
   111  	return false
   112  }