gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/proc/native/threads_windows.go (about) 1 package native 2 3 import ( 4 "errors" 5 "syscall" 6 7 sys "golang.org/x/sys/windows" 8 ) 9 10 const enableHardwareBreakpoints = false // see https://gitlab.com/Raven-IO/raven-delve/issues/2768 11 12 // waitStatus is a synonym for the platform-specific WaitStatus 13 type waitStatus sys.WaitStatus 14 15 // osSpecificDetails holds information specific to the Windows 16 // operating system / kernel. 17 type osSpecificDetails struct { 18 hThread syscall.Handle 19 dbgUiRemoteBreakIn bool // whether thread is an auxiliary DbgUiRemoteBreakIn thread created by Windows 20 delayErr error 21 setbp bool 22 } 23 24 func (procgrp *processGroup) singleStep(t *nativeThread) error { 25 context := newContext() 26 context.SetFlags(_CONTEXT_ALL) 27 28 // Set the processor TRAP flag 29 err := t.getContext(context) 30 if err != nil { 31 return err 32 } 33 34 context.SetTrap(true) 35 36 err = t.setContext(context) 37 if err != nil { 38 return err 39 } 40 41 suspendcnt := 0 42 43 // If a thread simultaneously hits a breakpoint and is suspended by the Go 44 // runtime it will have a suspend count greater than 1 and to actually take 45 // a single step we have to resume it multiple times here. 46 // We keep a counter of how many times it was suspended so that after 47 // single-stepping we can re-suspend it the correct number of times. 48 for { 49 n, err := _ResumeThread(t.os.hThread) 50 if err != nil { 51 return err 52 } 53 suspendcnt++ 54 if n == 1 { 55 break 56 } 57 } 58 59 for { 60 var tid int 61 t.dbp.execPtraceFunc(func() { 62 tid, err = procgrp.waitForDebugEvent(waitBlocking | waitSuspendNewThreads) 63 }) 64 if err != nil { 65 return err 66 } 67 68 ep := procgrp.procForThread(tid) 69 70 if ep.pid == t.dbp.pid && tid == t.ID { 71 break 72 } 73 74 ep.execPtraceFunc(func() { 75 err = _ContinueDebugEvent(uint32(ep.pid), uint32(ep.os.breakThread), _DBG_CONTINUE) 76 }) 77 } 78 79 for i := 0; i < suspendcnt; i++ { 80 if !t.os.dbgUiRemoteBreakIn { 81 _, err = _SuspendThread(t.os.hThread) 82 if err != nil { 83 return err 84 } 85 } 86 } 87 88 t.dbp.execPtraceFunc(func() { 89 err = _ContinueDebugEvent(uint32(t.dbp.pid), uint32(t.ID), _DBG_CONTINUE) 90 }) 91 if err != nil { 92 return err 93 } 94 95 // Unset the processor TRAP flag 96 err = t.getContext(context) 97 if err != nil { 98 return err 99 } 100 101 context.SetTrap(false) 102 103 return t.setContext(context) 104 } 105 106 func (t *nativeThread) WriteMemory(addr uint64, data []byte) (int, error) { 107 if ok, err := t.dbp.Valid(); !ok { 108 return 0, err 109 } 110 if len(data) == 0 { 111 return 0, nil 112 } 113 var count uintptr 114 err := _WriteProcessMemory(t.dbp.os.hProcess, uintptr(addr), &data[0], uintptr(len(data)), &count) 115 if err != nil { 116 return 0, err 117 } 118 return int(count), nil 119 } 120 121 var ErrShortRead = errors.New("short read") 122 123 func (t *nativeThread) ReadMemory(buf []byte, addr uint64) (int, error) { 124 if ok, err := t.dbp.Valid(); !ok { 125 return 0, err 126 } 127 if len(buf) == 0 { 128 return 0, nil 129 } 130 var count uintptr 131 err := _ReadProcessMemory(t.dbp.os.hProcess, uintptr(addr), &buf[0], uintptr(len(buf)), &count) 132 if err == nil && count != uintptr(len(buf)) { 133 err = ErrShortRead 134 } 135 return int(count), err 136 } 137 138 // SoftExc returns true if this thread received a software exception during the last resume. 139 func (t *nativeThread) SoftExc() bool { 140 return t.os.setbp 141 }