proc: replace cgo with syscalls on windows

Unrelated to conversion, I have also changed (*Thread).readMemory
to return only first count bytes of memory just as advised
by ReadProcessMemory.

Fixes #409
Fixes #412
Fixes #416
This commit is contained in:
Alex Brainman
2016-02-17 21:23:17 +11:00
parent 6242c4388e
commit 8d4d0871cf
6 changed files with 366 additions and 130 deletions

View File

@ -1,7 +1,5 @@
package proc
// #include "windows.h"
import "C"
import (
"debug/gosym"
"debug/pe"
@ -30,7 +28,7 @@ const (
// OSProcessDetails holds Windows specific information.
type OSProcessDetails struct {
hProcess sys.Handle
hProcess syscall.Handle
breakThread int
}
@ -121,17 +119,13 @@ func (dbp *Process) Kill() error {
// TODO: Should not have to ignore failures here,
// but some tests appear to Kill twice causing
// this to fail on second attempt.
_ = C.TerminateProcess(C.HANDLE(dbp.os.hProcess), 1)
_ = syscall.TerminateProcess(dbp.os.hProcess, 1)
dbp.exited = true
return nil
}
func (dbp *Process) requestManualStop() error {
res := C.DebugBreakProcess(C.HANDLE(dbp.os.hProcess))
if res == C.FALSE {
return fmt.Errorf("failed to break process %d", dbp.Pid)
}
return nil
return _DebugBreakProcess(dbp.os.hProcess)
}
func (dbp *Process) updateThreadList() error {
@ -140,7 +134,7 @@ func (dbp *Process) updateThreadList() error {
return nil
}
func (dbp *Process) addThread(hThread sys.Handle, threadID int, attach bool) (*Thread, error) {
func (dbp *Process) addThread(hThread syscall.Handle, threadID int, attach bool) (*Thread, error) {
if thread, ok := dbp.Threads[threadID]; ok {
return thread, nil
}
@ -341,76 +335,76 @@ func dwarfFromPE(f *pe.File) (*dwarf.Data, error) {
}
func (dbp *Process) waitForDebugEvent() (threadID, exitCode int, err error) {
var debugEvent C.DEBUG_EVENT
var debugEvent _DEBUG_EVENT
shouldExit := false
for {
// Wait for a debug event...
res := C.WaitForDebugEvent(&debugEvent, C.INFINITE)
if res == C.FALSE {
return 0, 0, fmt.Errorf("could not WaitForDebugEvent")
err := _WaitForDebugEvent(&debugEvent, syscall.INFINITE)
if err != nil {
return 0, 0, err
}
// ... handle each event kind ...
unionPtr := unsafe.Pointer(&debugEvent.u[0])
switch debugEvent.dwDebugEventCode {
case C.CREATE_PROCESS_DEBUG_EVENT:
debugInfo := (*C.CREATE_PROCESS_DEBUG_INFO)(unionPtr)
hFile := debugInfo.hFile
if hFile != C.HANDLE(uintptr(0)) /* NULL */ && hFile != C.HANDLE(uintptr(0xFFFFFFFFFFFFFFFF)) /* INVALID_HANDLE_VALUE */ {
res = C.CloseHandle(hFile)
if res == C.FALSE {
return 0, 0, fmt.Errorf("could not close create process file handle")
unionPtr := unsafe.Pointer(&debugEvent.U[0])
switch debugEvent.DebugEventCode {
case _CREATE_PROCESS_DEBUG_EVENT:
debugInfo := (*_CREATE_PROCESS_DEBUG_INFO)(unionPtr)
hFile := debugInfo.File
if hFile != 0 && hFile != syscall.InvalidHandle {
err = syscall.CloseHandle(hFile)
if err != nil {
return 0, 0, err
}
}
dbp.os.hProcess = sys.Handle(debugInfo.hProcess)
_, err = dbp.addThread(sys.Handle(debugInfo.hThread), int(debugEvent.dwThreadId), false)
dbp.os.hProcess = debugInfo.Process
_, err = dbp.addThread(debugInfo.Thread, int(debugEvent.ThreadId), false)
if err != nil {
return 0, 0, err
}
break
case C.CREATE_THREAD_DEBUG_EVENT:
debugInfo := (*C.CREATE_THREAD_DEBUG_INFO)(unionPtr)
_, err = dbp.addThread(sys.Handle(debugInfo.hThread), int(debugEvent.dwThreadId), false)
case _CREATE_THREAD_DEBUG_EVENT:
debugInfo := (*_CREATE_THREAD_DEBUG_INFO)(unionPtr)
_, err = dbp.addThread(debugInfo.Thread, int(debugEvent.ThreadId), false)
if err != nil {
return 0, 0, err
}
break
case C.EXIT_THREAD_DEBUG_EVENT:
delete(dbp.Threads, int(debugEvent.dwThreadId))
case _EXIT_THREAD_DEBUG_EVENT:
delete(dbp.Threads, int(debugEvent.ThreadId))
break
case C.OUTPUT_DEBUG_STRING_EVENT:
case _OUTPUT_DEBUG_STRING_EVENT:
//TODO: Handle debug output strings
break
case C.LOAD_DLL_DEBUG_EVENT:
debugInfo := (*C.LOAD_DLL_DEBUG_INFO)(unionPtr)
hFile := debugInfo.hFile
if hFile != C.HANDLE(uintptr(0)) /* NULL */ && hFile != C.HANDLE(uintptr(0xFFFFFFFFFFFFFFFF)) /* INVALID_HANDLE_VALUE */ {
res = C.CloseHandle(hFile)
if res == C.FALSE {
return 0, 0, fmt.Errorf("could not close DLL load file handle")
case _LOAD_DLL_DEBUG_EVENT:
debugInfo := (*_LOAD_DLL_DEBUG_INFO)(unionPtr)
hFile := debugInfo.File
if hFile != 0 && hFile != syscall.InvalidHandle {
err = syscall.CloseHandle(hFile)
if err != nil {
return 0, 0, err
}
}
break
case C.UNLOAD_DLL_DEBUG_EVENT:
case _UNLOAD_DLL_DEBUG_EVENT:
break
case C.RIP_EVENT:
case _RIP_EVENT:
break
case C.EXCEPTION_DEBUG_EVENT:
tid := int(debugEvent.dwThreadId)
case _EXCEPTION_DEBUG_EVENT:
tid := int(debugEvent.ThreadId)
dbp.os.breakThread = tid
return tid, 0, nil
case C.EXIT_PROCESS_DEBUG_EVENT:
debugInfo := (*C.EXIT_PROCESS_DEBUG_INFO)(unionPtr)
exitCode = int(debugInfo.dwExitCode)
case _EXIT_PROCESS_DEBUG_EVENT:
debugInfo := (*_EXIT_PROCESS_DEBUG_INFO)(unionPtr)
exitCode = int(debugInfo.ExitCode)
shouldExit = true
default:
return 0, 0, fmt.Errorf("unknown debug event code: %d", debugEvent.dwDebugEventCode)
return 0, 0, fmt.Errorf("unknown debug event code: %d", debugEvent.DebugEventCode)
}
// .. and then continue unless we received an event that indicated we should break into debugger.
res = C.ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, C.DBG_CONTINUE)
if res == C.WINBOOL(0) {
return 0, 0, fmt.Errorf("could not ContinueDebugEvent")
err = _ContinueDebugEvent(debugEvent.ProcessId, debugEvent.ThreadId, _DBG_CONTINUE)
if err != nil {
return 0, 0, err
}
if shouldExit {

View File

@ -1,12 +1,9 @@
package proc
// #include <windows.h>
import "C"
import (
"bytes"
"fmt"
"rsc.io/x86/x86asm"
"syscall"
"unsafe"
)
@ -97,22 +94,17 @@ func (r *Regs) TLS() uint64 {
// SetPC sets the RIP register to the value specified by `pc`.
func (r *Regs) SetPC(thread *Thread, pc uint64) error {
var context C.CONTEXT
context.ContextFlags = C.CONTEXT_ALL
context := newCONTEXT()
context.ContextFlags = _CONTEXT_ALL
res := C.GetThreadContext(C.HANDLE(thread.os.hThread), &context)
if res == C.FALSE {
return fmt.Errorf("could not GetThreadContext")
err := _GetThreadContext(thread.os.hThread, context)
if err != nil {
return err
}
context.Rip = C.DWORD64(pc)
context.Rip = pc
res = C.SetThreadContext(C.HANDLE(thread.os.hThread), &context)
if res == C.FALSE {
return fmt.Errorf("could not SetThreadContext")
}
return nil
return _SetThreadContext(thread.os.hThread, context)
}
func (r *Regs) Get(n int) (uint64, error) {
@ -273,18 +265,18 @@ func (r *Regs) Get(n int) (uint64, error) {
}
func registers(thread *Thread) (Registers, error) {
var context C.CONTEXT
context := newCONTEXT()
context.ContextFlags = C.CONTEXT_ALL
res := C.GetThreadContext(C.HANDLE(thread.os.hThread), &context)
if res == C.FALSE {
return nil, fmt.Errorf("failed to read ThreadContext")
context.ContextFlags = _CONTEXT_ALL
err := _GetThreadContext(thread.os.hThread, context)
if err != nil {
return nil, err
}
var threadInfo _THREAD_BASIC_INFORMATION
status := _NtQueryInformationThread(syscall.Handle(thread.os.hThread), _ThreadBasicInformation, uintptr(unsafe.Pointer(&threadInfo)), uint32(unsafe.Sizeof(threadInfo)), nil)
status := _NtQueryInformationThread(thread.os.hThread, _ThreadBasicInformation, uintptr(unsafe.Pointer(&threadInfo)), uint32(unsafe.Sizeof(threadInfo)), nil)
if !_NT_SUCCESS(status) {
return nil, fmt.Errorf("failed to get thread_basic_information")
return nil, fmt.Errorf("NtQueryInformationThread failed: it returns 0x%x", status)
}
regs := &Regs{

View File

@ -22,8 +22,53 @@ type _THREAD_BASIC_INFORMATION struct {
BasePriority int32
}
type _CREATE_PROCESS_DEBUG_INFO struct {
File syscall.Handle
Process syscall.Handle
Thread syscall.Handle
BaseOfImage uintptr
DebugInfoFileOffset uint32
DebugInfoSize uint32
ThreadLocalBase uintptr
StartAddress uintptr
ImageName uintptr
Unicode uint16
}
type _CREATE_THREAD_DEBUG_INFO struct {
Thread syscall.Handle
ThreadLocalBase uintptr
StartAddress uintptr
}
type _EXIT_PROCESS_DEBUG_INFO struct {
ExitCode uint32
}
type _LOAD_DLL_DEBUG_INFO struct {
File syscall.Handle
BaseOfDll uintptr
DebugInfoFileOffset uint32
DebugInfoSize uint32
ImageName uintptr
Unicode uint16
}
const (
_ThreadBasicInformation = 0
_DBG_CONTINUE = 0x00010002
_DBG_EXCEPTION_NOT_HANDLED = 0x80010001
_EXCEPTION_DEBUG_EVENT = 1
_CREATE_THREAD_DEBUG_EVENT = 2
_CREATE_PROCESS_DEBUG_EVENT = 3
_EXIT_THREAD_DEBUG_EVENT = 4
_EXIT_PROCESS_DEBUG_EVENT = 5
_LOAD_DLL_DEBUG_EVENT = 6
_UNLOAD_DLL_DEBUG_EVENT = 7
_OUTPUT_DEBUG_STRING_EVENT = 8
_RIP_EVENT = 9
)
func _NT_SUCCESS(x _NTSTATUS) bool {
@ -31,3 +76,12 @@ func _NT_SUCCESS(x _NTSTATUS) bool {
}
//sys _NtQueryInformationThread(threadHandle syscall.Handle, infoclass int32, info uintptr, infolen uint32, retlen *uint32) (status _NTSTATUS) = ntdll.NtQueryInformationThread
//sys _GetThreadContext(thread syscall.Handle, context *_CONTEXT) (err error) = kernel32.GetThreadContext
//sys _SetThreadContext(thread syscall.Handle, context *_CONTEXT) (err error) = kernel32.SetThreadContext
//sys _SuspendThread(threadid syscall.Handle) (prevsuspcount uint32, err error) [failretval==0xffffffff] = kernel32.SuspendThread
//sys _ResumeThread(threadid syscall.Handle) (prevsuspcount uint32, err error) [failretval==0xffffffff] = kernel32.ResumeThread
//sys _ContinueDebugEvent(processid uint32, threadid uint32, continuestatus uint32) (err error) = kernel32.ContinueDebugEvent
//sys _WriteProcessMemory(process syscall.Handle, baseaddr uintptr, buffer *byte, size uintptr, byteswritten *uintptr) (err error) = kernel32.WriteProcessMemory
//sys _ReadProcessMemory(process syscall.Handle, baseaddr uintptr, buffer *byte, size uintptr, bytesread *uintptr) (err error) = kernel32.ReadProcessMemory
//sys _DebugBreakProcess(process syscall.Handle) (err error) = kernel32.DebugBreakProcess
//sys _WaitForDebugEvent(debugevent *_DEBUG_EVENT, milliseconds uint32) (err error) = kernel32.WaitForDebugEvent

View File

@ -0,0 +1,95 @@
package proc
import "unsafe"
const (
_CONTEXT_AMD64 = 0x100000
_CONTEXT_CONTROL = (_CONTEXT_AMD64 | 0x1)
_CONTEXT_INTEGER = (_CONTEXT_AMD64 | 0x2)
_CONTEXT_SEGMENTS = (_CONTEXT_AMD64 | 0x4)
_CONTEXT_FLOATING_POINT = (_CONTEXT_AMD64 | 0x8)
_CONTEXT_DEBUG_REGISTERS = (_CONTEXT_AMD64 | 0x10)
_CONTEXT_FULL = (_CONTEXT_CONTROL | _CONTEXT_INTEGER | _CONTEXT_FLOATING_POINT)
_CONTEXT_ALL = (_CONTEXT_CONTROL | _CONTEXT_INTEGER | _CONTEXT_SEGMENTS | _CONTEXT_FLOATING_POINT | _CONTEXT_DEBUG_REGISTERS)
_CONTEXT_EXCEPTION_ACTIVE = 0x8000000
_CONTEXT_SERVICE_ACTIVE = 0x10000000
_CONTEXT_EXCEPTION_REQUEST = 0x40000000
_CONTEXT_EXCEPTION_REPORTING = 0x80000000
)
type _M128A struct {
Low uint64
High int64
}
type _CONTEXT struct {
P1Home uint64
P2Home uint64
P3Home uint64
P4Home uint64
P5Home uint64
P6Home uint64
ContextFlags uint32
MxCsr uint32
SegCs uint16
SegDs uint16
SegEs uint16
SegFs uint16
SegGs uint16
SegSs uint16
EFlags uint32
Dr0 uint64
Dr1 uint64
Dr2 uint64
Dr3 uint64
Dr6 uint64
Dr7 uint64
Rax uint64
Rcx uint64
Rdx uint64
Rbx uint64
Rsp uint64
Rbp uint64
Rsi uint64
Rdi uint64
R8 uint64
R9 uint64
R10 uint64
R11 uint64
R12 uint64
R13 uint64
R14 uint64
R15 uint64
Rip uint64
FltSave [512]byte
VectorRegister [26]_M128A
VectorControl uint64
DebugControl uint64
LastBranchToRip uint64
LastBranchFromRip uint64
LastExceptionToRip uint64
LastExceptionFromRip uint64
}
// newCONTEXT allocates Windows CONTEXT structure aligned to 16 bytes.
func newCONTEXT() *_CONTEXT {
var c *_CONTEXT
buf := make([]byte, unsafe.Sizeof(*c)+15)
return (*_CONTEXT)(unsafe.Pointer((uintptr(unsafe.Pointer(&buf[15]))) &^ 15))
}
type _DEBUG_EVENT struct {
DebugEventCode uint32
ProcessId uint32
ThreadId uint32
_ uint32 // to align Union properly
U [160]byte
}

View File

@ -1,10 +1,8 @@
package proc
// #include <windows.h>
import "C"
import (
"fmt"
"unsafe"
"syscall"
sys "golang.org/x/sys/windows"
)
@ -15,7 +13,7 @@ type WaitStatus sys.WaitStatus
// OSSpecificDetails holds information specific to the Windows
// operating system / kernel.
type OSSpecificDetails struct {
hThread sys.Handle
hThread syscall.Handle
}
func (t *Thread) halt() (err error) {
@ -29,20 +27,20 @@ func (t *Thread) halt() (err error) {
}
func (t *Thread) singleStep() error {
var context C.CONTEXT
context.ContextFlags = C.CONTEXT_ALL
context := newCONTEXT()
context.ContextFlags = _CONTEXT_ALL
// Set the processor TRAP flag
res := C.GetThreadContext(C.HANDLE(t.os.hThread), &context)
if res == C.FALSE {
return fmt.Errorf("could not GetThreadContext")
err := _GetThreadContext(t.os.hThread, context)
if err != nil {
return err
}
context.EFlags |= 0x100
res = C.SetThreadContext(C.HANDLE(t.os.hThread), &context)
if res == C.FALSE {
return fmt.Errorf("could not SetThreadContext")
err = _SetThreadContext(t.os.hThread, context)
if err != nil {
return err
}
// Suspend all threads except this one
@ -50,20 +48,21 @@ func (t *Thread) singleStep() error {
if thread.ID == t.ID {
continue
}
res := C.SuspendThread(C.HANDLE(thread.os.hThread))
if res == C.DWORD(0xFFFFFFFF) {
return fmt.Errorf("could not suspend thread: %d", thread.ID)
_, err := _SuspendThread(thread.os.hThread)
if err != nil {
return fmt.Errorf("could not suspend thread: %d: %v", thread.ID, err)
}
}
// Continue and wait for the step to complete
err = nil
t.dbp.execPtraceFunc(func() {
res = C.ContinueDebugEvent(C.DWORD(t.dbp.Pid), C.DWORD(t.ID), C.DBG_CONTINUE)
err = _ContinueDebugEvent(uint32(t.dbp.Pid), uint32(t.ID), _DBG_CONTINUE)
})
if res == C.FALSE {
return fmt.Errorf("could not ContinueDebugEvent.")
if err != nil {
return err
}
_, err := t.dbp.trapWait(0)
_, err = t.dbp.trapWait(0)
if err != nil {
return err
}
@ -73,40 +72,32 @@ func (t *Thread) singleStep() error {
if thread.ID == t.ID {
continue
}
res := C.ResumeThread(C.HANDLE(thread.os.hThread))
if res == C.DWORD(0xFFFFFFFF) {
return fmt.Errorf("ould not resume thread: %d", thread.ID)
_, err := _ResumeThread(thread.os.hThread)
if err != nil {
return fmt.Errorf("could not resume thread: %d: %v", thread.ID, err)
}
}
// Unset the processor TRAP flag
res = C.GetThreadContext(C.HANDLE(t.os.hThread), &context)
if res == C.FALSE {
return fmt.Errorf("could not GetThreadContext")
err = _GetThreadContext(t.os.hThread, context)
if err != nil {
return err
}
context.EFlags &= ^C.DWORD(0x100)
context.EFlags &= ^uint32(0x100)
res = C.SetThreadContext(C.HANDLE(t.os.hThread), &context)
if res == C.FALSE {
return fmt.Errorf("could not SetThreadContext")
}
return nil
return _SetThreadContext(t.os.hThread, context)
}
func (t *Thread) resume() error {
t.running = true
var res C.WINBOOL
var err error
t.dbp.execPtraceFunc(func() {
//TODO: Note that we are ignoring the thread we were asked to continue and are continuing the
//thread that we last broke on.
res = C.ContinueDebugEvent(C.DWORD(t.dbp.Pid), C.DWORD(t.ID), C.DBG_CONTINUE)
err = _ContinueDebugEvent(uint32(t.dbp.Pid), uint32(t.ID), _DBG_CONTINUE)
})
if res == C.FALSE {
return fmt.Errorf("could not ContinueDebugEvent.")
}
return nil
return err
}
func (t *Thread) blocked() bool {
@ -135,15 +126,10 @@ func (t *Thread) stopped() bool {
}
func (t *Thread) writeMemory(addr uintptr, data []byte) (int, error) {
var (
vmData = C.LPCVOID(unsafe.Pointer(&data[0]))
vmAddr = C.LPVOID(addr)
length = C.SIZE_T(len(data))
count C.SIZE_T
)
ret := C.WriteProcessMemory(C.HANDLE(t.dbp.os.hProcess), vmAddr, vmData, length, &count)
if ret == C.FALSE {
return int(count), fmt.Errorf("could not write memory")
var count uintptr
err := _WriteProcessMemory(t.dbp.os.hProcess, addr, &data[0], uintptr(len(data)), &count)
if err != nil {
return 0, err
}
return int(count), nil
}
@ -152,16 +138,11 @@ func (t *Thread) readMemory(addr uintptr, size int) ([]byte, error) {
if size == 0 {
return nil, nil
}
var (
buf = make([]byte, size)
vmData = C.LPVOID(unsafe.Pointer(&buf[0]))
vmAddr = C.LPCVOID(addr)
length = C.SIZE_T(size)
count C.SIZE_T
)
ret := C.ReadProcessMemory(C.HANDLE(t.dbp.os.hProcess), vmAddr, vmData, length, &count)
if ret == C.FALSE {
return nil, fmt.Errorf("could not read memory")
var count uintptr
buf := make([]byte, size)
err := _ReadProcessMemory(t.dbp.os.hProcess, addr, &buf[0], uintptr(size), &count)
if err != nil {
return nil, err
}
return buf, nil
return buf[:count], nil
}

122
proc/zsyscall_windows.go Executable file → Normal file
View File

@ -8,9 +8,19 @@ import "syscall"
var _ unsafe.Pointer
var (
modntdll = syscall.NewLazyDLL("ntdll.dll")
modntdll = syscall.NewLazyDLL("ntdll.dll")
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procNtQueryInformationThread = modntdll.NewProc("NtQueryInformationThread")
procGetThreadContext = modkernel32.NewProc("GetThreadContext")
procSetThreadContext = modkernel32.NewProc("SetThreadContext")
procSuspendThread = modkernel32.NewProc("SuspendThread")
procResumeThread = modkernel32.NewProc("ResumeThread")
procContinueDebugEvent = modkernel32.NewProc("ContinueDebugEvent")
procWriteProcessMemory = modkernel32.NewProc("WriteProcessMemory")
procReadProcessMemory = modkernel32.NewProc("ReadProcessMemory")
procDebugBreakProcess = modkernel32.NewProc("DebugBreakProcess")
procWaitForDebugEvent = modkernel32.NewProc("WaitForDebugEvent")
)
func _NtQueryInformationThread(threadHandle syscall.Handle, infoclass int32, info uintptr, infolen uint32, retlen *uint32) (status _NTSTATUS) {
@ -18,3 +28,113 @@ func _NtQueryInformationThread(threadHandle syscall.Handle, infoclass int32, inf
status = _NTSTATUS(r0)
return
}
func _GetThreadContext(thread syscall.Handle, context *_CONTEXT) (err error) {
r1, _, e1 := syscall.Syscall(procGetThreadContext.Addr(), 2, uintptr(thread), uintptr(unsafe.Pointer(context)), 0)
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func _SetThreadContext(thread syscall.Handle, context *_CONTEXT) (err error) {
r1, _, e1 := syscall.Syscall(procSetThreadContext.Addr(), 2, uintptr(thread), uintptr(unsafe.Pointer(context)), 0)
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func _SuspendThread(threadid syscall.Handle) (prevsuspcount uint32, err error) {
r0, _, e1 := syscall.Syscall(procSuspendThread.Addr(), 1, uintptr(threadid), 0, 0)
prevsuspcount = uint32(r0)
if prevsuspcount == 0xffffffff {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func _ResumeThread(threadid syscall.Handle) (prevsuspcount uint32, err error) {
r0, _, e1 := syscall.Syscall(procResumeThread.Addr(), 1, uintptr(threadid), 0, 0)
prevsuspcount = uint32(r0)
if prevsuspcount == 0xffffffff {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func _ContinueDebugEvent(processid uint32, threadid uint32, continuestatus uint32) (err error) {
r1, _, e1 := syscall.Syscall(procContinueDebugEvent.Addr(), 3, uintptr(processid), uintptr(threadid), uintptr(continuestatus))
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func _WriteProcessMemory(process syscall.Handle, baseaddr uintptr, buffer *byte, size uintptr, byteswritten *uintptr) (err error) {
r1, _, e1 := syscall.Syscall6(procWriteProcessMemory.Addr(), 5, uintptr(process), uintptr(baseaddr), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(byteswritten)), 0)
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func _ReadProcessMemory(process syscall.Handle, baseaddr uintptr, buffer *byte, size uintptr, bytesread *uintptr) (err error) {
r1, _, e1 := syscall.Syscall6(procReadProcessMemory.Addr(), 5, uintptr(process), uintptr(baseaddr), uintptr(unsafe.Pointer(buffer)), uintptr(size), uintptr(unsafe.Pointer(bytesread)), 0)
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func _DebugBreakProcess(process syscall.Handle) (err error) {
r1, _, e1 := syscall.Syscall(procDebugBreakProcess.Addr(), 1, uintptr(process), 0, 0)
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func _WaitForDebugEvent(debugevent *_DEBUG_EVENT, milliseconds uint32) (err error) {
r1, _, e1 := syscall.Syscall(procWaitForDebugEvent.Addr(), 2, uintptr(unsafe.Pointer(debugevent)), uintptr(milliseconds), 0)
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}