gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/proc/native/threads_linux.go (about) 1 package native 2 3 import ( 4 "fmt" 5 6 sys "golang.org/x/sys/unix" 7 8 "gitlab.com/Raven-IO/raven-delve/pkg/proc" 9 ) 10 11 type waitStatus sys.WaitStatus 12 13 // osSpecificDetails hold Linux specific 14 // process details. 15 type osSpecificDetails struct { 16 delayedSignal int 17 running bool 18 setbp bool 19 phantomBreakpointPC uint64 20 } 21 22 func (t *nativeThread) stop() (err error) { 23 err = sys.Tgkill(t.dbp.pid, t.ID, sys.SIGSTOP) 24 if err != nil { 25 if err == sys.ESRCH { 26 return 27 } 28 err = fmt.Errorf("stop err %s on thread %d", err, t.ID) 29 return 30 } 31 return 32 } 33 34 // Stopped returns whether the thread is stopped at 35 // the operating system level. 36 func (t *nativeThread) Stopped() bool { 37 state := status(t.ID, t.dbp.os.comm) 38 return state == statusTraceStop || state == statusTraceStopT 39 } 40 41 func (t *nativeThread) resume() error { 42 sig := t.os.delayedSignal 43 t.os.delayedSignal = 0 44 return t.resumeWithSig(sig) 45 } 46 47 func (t *nativeThread) resumeWithSig(sig int) (err error) { 48 t.os.running = true 49 t.dbp.execPtraceFunc(func() { err = ptraceCont(t.ID, sig) }) 50 return 51 } 52 53 func (procgrp *processGroup) singleStep(t *nativeThread) (err error) { 54 sig := 0 55 for { 56 t.dbp.execPtraceFunc(func() { err = ptraceSingleStep(t.ID, sig) }) 57 sig = 0 58 if err != nil { 59 return err 60 } 61 wpid, status, err := t.dbp.waitFast(t.ID) 62 if err != nil { 63 return err 64 } 65 if (status == nil || status.Exited()) && wpid == t.dbp.pid { 66 t.dbp.postExit() 67 rs := 0 68 if status != nil { 69 rs = status.ExitStatus() 70 } 71 return proc.ErrProcessExited{Pid: t.dbp.pid, Status: rs} 72 } 73 if wpid == t.ID { 74 switch s := status.StopSignal(); s { 75 case sys.SIGTRAP: 76 return nil 77 case sys.SIGSTOP: 78 // delayed SIGSTOP, ignore it 79 case sys.SIGILL, sys.SIGBUS, sys.SIGFPE, sys.SIGSEGV, sys.SIGSTKFLT: 80 // propagate signals that can have been caused by the current instruction 81 sig = int(s) 82 default: 83 // delay propagation of all other signals 84 t.os.delayedSignal = int(s) 85 } 86 } 87 } 88 } 89 90 func (t *nativeThread) WriteMemory(addr uint64, data []byte) (written int, err error) { 91 if ok, err := t.dbp.Valid(); !ok { 92 return 0, err 93 } 94 if len(data) == 0 { 95 return 96 } 97 // ProcessVmWrite can't poke read-only memory like ptrace, so don't 98 // even bother for small writes -- likely breakpoints and such. 99 if len(data) > sys.SizeofPtr { 100 written, _ = processVmWrite(t.ID, uintptr(addr), data) 101 } 102 if written == 0 { 103 t.dbp.execPtraceFunc(func() { written, err = sys.PtracePokeData(t.ID, uintptr(addr), data) }) 104 } 105 return 106 } 107 108 func (t *nativeThread) ReadMemory(data []byte, addr uint64) (n int, err error) { 109 if ok, err := t.dbp.Valid(); !ok { 110 return 0, err 111 } 112 if len(data) == 0 { 113 return 114 } 115 n, _ = processVmRead(t.ID, uintptr(addr), data) 116 if n == 0 { 117 t.dbp.execPtraceFunc(func() { n, err = sys.PtracePeekData(t.ID, uintptr(addr), data) }) 118 } 119 return 120 } 121 122 // SoftExc returns true if this thread received a software exception during the last resume. 123 func (t *nativeThread) SoftExc() bool { 124 return t.os.setbp 125 }