gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/proc/native/threads_darwin.go (about) 1 //go:build darwin && macnative 2 3 package native 4 5 // #include "threads_darwin.h" 6 // #include "proc_darwin.h" 7 import "C" 8 import ( 9 "errors" 10 "fmt" 11 "unsafe" 12 13 sys "golang.org/x/sys/unix" 14 15 "gitlab.com/Raven-IO/raven-delve/pkg/proc" 16 "gitlab.com/Raven-IO/raven-delve/pkg/proc/amd64util" 17 ) 18 19 // waitStatus is a synonym for the platform-specific WaitStatus 20 type waitStatus sys.WaitStatus 21 22 // osSpecificDetails holds information specific to the OSX/Darwin 23 // operating system / kernel. 24 type osSpecificDetails struct { 25 threadAct C.thread_act_t 26 registers C.x86_thread_state64_t 27 exists bool 28 } 29 30 // ErrContinueThread is the error returned when a thread could not 31 // be continued. 32 var ErrContinueThread = fmt.Errorf("could not continue thread") 33 34 func (t *nativeThread) stop() (err error) { 35 kret := C.thread_suspend(t.os.threadAct) 36 if kret != C.KERN_SUCCESS { 37 errStr := C.GoString(C.mach_error_string(C.mach_error_t(kret))) 38 // check that the thread still exists before complaining 39 err2 := t.dbp.updateThreadList() 40 if err2 != nil { 41 err = fmt.Errorf("could not suspend thread %d %s (additionally could not update thread list: %v)", t.ID, errStr, err2) 42 return 43 } 44 45 if _, ok := t.dbp.threads[t.ID]; ok { 46 err = fmt.Errorf("could not suspend thread %d %s", t.ID, errStr) 47 return 48 } 49 } 50 return 51 } 52 53 func (procgrp *processGroup) singleStep(t *nativeThread) error { 54 kret := C.single_step(t.os.threadAct) 55 if kret != C.KERN_SUCCESS { 56 return fmt.Errorf("could not single step") 57 } 58 for { 59 twthread, err := t.dbp.trapWait(t.dbp.pid) 60 if err != nil { 61 return err 62 } 63 if twthread.ID == t.ID { 64 break 65 } 66 } 67 68 kret = C.clear_trap_flag(t.os.threadAct) 69 if kret != C.KERN_SUCCESS { 70 return fmt.Errorf("could not clear CPU trap flag") 71 } 72 return nil 73 } 74 75 func (t *nativeThread) resume() error { 76 // TODO(dp) set flag for ptrace stops 77 var err error 78 t.dbp.execPtraceFunc(func() { err = ptraceCont(t.dbp.pid, 0) }) 79 if err == nil { 80 return nil 81 } 82 kret := C.resume_thread(t.os.threadAct) 83 if kret != C.KERN_SUCCESS { 84 return ErrContinueThread 85 } 86 return nil 87 } 88 89 // Stopped returns whether the thread is stopped at 90 // the operating system level. 91 func (t *nativeThread) Stopped() bool { 92 return C.thread_blocked(t.os.threadAct) > C.int(0) 93 } 94 95 func (t *nativeThread) WriteMemory(addr uint64, data []byte) (int, error) { 96 if ok, err := t.dbp.Valid(); !ok { 97 return 0, err 98 } 99 if len(data) == 0 { 100 return 0, nil 101 } 102 var ( 103 vmData = unsafe.Pointer(&data[0]) 104 vmAddr = C.mach_vm_address_t(addr) 105 length = C.mach_msg_type_number_t(len(data)) 106 ) 107 if ret := C.write_memory(t.dbp.os.task, vmAddr, vmData, length); ret < 0 { 108 return 0, fmt.Errorf("could not write memory") 109 } 110 return len(data), nil 111 } 112 113 func (t *nativeThread) ReadMemory(buf []byte, addr uint64) (int, error) { 114 if ok, err := t.dbp.Valid(); !ok { 115 return 0, err 116 } 117 if len(buf) == 0 { 118 return 0, nil 119 } 120 var ( 121 vmData = unsafe.Pointer(&buf[0]) 122 vmAddr = C.mach_vm_address_t(addr) 123 length = C.mach_msg_type_number_t(len(buf)) 124 ) 125 126 ret := C.read_memory(t.dbp.os.task, vmAddr, vmData, length) 127 if ret < 0 { 128 return 0, fmt.Errorf("could not read memory") 129 } 130 return len(buf), nil 131 } 132 133 func (t *nativeThread) restoreRegisters(sr proc.Registers) error { 134 return errors.New("not implemented") 135 } 136 137 func (t *nativeThread) withDebugRegisters(f func(*amd64util.DebugRegisters) error) error { 138 return proc.ErrHWBreakUnsupported 139 } 140 141 // SoftExc returns true if this thread received a software exception during the last resume. 142 func (t *nativeThread) SoftExc() bool { 143 return false 144 }