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 }