]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: minimal mingw version of syscall to call windows dlls
authorAlex Brainman <alex.brainman@gmail.com>
Tue, 9 Mar 2010 23:09:09 +0000 (15:09 -0800)
committerRuss Cox <rsc@golang.org>
Tue, 9 Mar 2010 23:09:09 +0000 (15:09 -0800)
lots of missing parts, but builds and can call dlls, see a sample code in syscall_mingw.go

R=rsc
CC=golang-dev
https://golang.org/cl/218042

12 files changed:
src/pkg/runtime/Makefile
src/pkg/runtime/mingw/os.h
src/pkg/runtime/mingw/syscall.cgo [new file with mode: 0644]
src/pkg/runtime/mingw/thread.c
src/pkg/syscall/asm_mingw_386.s [new file with mode: 0644]
src/pkg/syscall/mkall.sh
src/pkg/syscall/syscall_mingw.go [new file with mode: 0644]
src/pkg/syscall/syscall_mingw_386.go [new file with mode: 0644]
src/pkg/syscall/zerrors_mingw_386.go [new file with mode: 0644]
src/pkg/syscall/zsyscall_mingw_386.go [new file with mode: 0644]
src/pkg/syscall/zsysnum_mingw_386.go [new file with mode: 0644]
src/pkg/syscall/ztypes_mingw_386.go [new file with mode: 0644]

index 103515c13a58ae2ddc99a6bfda9318051da118e1..bc8a2d8bfa2ad4aa70d3d2e082268769521bd22b 100644 (file)
@@ -27,6 +27,9 @@ GOFILES=\
 GOFILES_pchw=\
        pchw/io.go\
 
+OFILES_mingw=\
+       syscall.$O\
+
 # 386-specific object files
 OFILES_386=\
        vlop.$O\
index 3864dbf8f12058f95a900f9247e8063f3fa78028..0de38852439656ab994ebd9a90e9fd7fb2fa2951 100644 (file)
@@ -12,6 +12,9 @@ void *stdcall(void *fn, ...);
 void *stdcall_raw(void *fn, ...);
 
 extern void *VirtualAlloc;
+extern void *LoadLibraryEx;
+extern void *GetProcAddress;
+extern void *GetLastError;
 
 #define goargs mingw_goargs
 void mingw_goargs(void);
diff --git a/src/pkg/runtime/mingw/syscall.cgo b/src/pkg/runtime/mingw/syscall.cgo
new file mode 100644 (file)
index 0000000..1553c61
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+#include "runtime.h"
+#include "os.h"
+
+func loadlibraryex(filename uintptr) (handle uint32) {
+       handle = (uint32)stdcall(LoadLibraryEx, filename, 0, 0);
+}
+
+func getprocaddress(handle uint32, procname uintptr) (proc uintptr) {
+       proc = (uintptr)stdcall(GetProcAddress, handle, procname);
+}
+
+func Syscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+       ·entersyscall();
+       r1 = (uintptr)stdcall_raw((void*)trap, a1, a2, a3);
+       r2 = 0;
+       err = (uintptr)stdcall_raw(GetLastError);
+       ·exitsyscall();
+}
+
+func Syscall6(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+       ·entersyscall();
+       r1 = (uintptr)stdcall_raw((void*)trap, a1, a2, a3, a4, a5, a6);
+       r2 = 0;
+       err = (uintptr)stdcall_raw(GetLastError);
+       ·exitsyscall();
+}
+
+func RawSyscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+       r1 = (uintptr)stdcall_raw((void*)trap, a1, a2, a3);
+       r2 = 0;
+       err = (uintptr)stdcall_raw(GetLastError);
+}
index 89f33f8a4a1b858640be5e6a1708cd0cc3b23c9e..94ffc27521e9d86bdb2345ab8c752006cb5e2c65 100644 (file)
@@ -16,12 +16,13 @@ void *GetStdHandle;
 void *SetEvent;
 void *WriteFile;
 void *VirtualAlloc;
+void *LoadLibraryEx;
+void *GetProcAddress;
+void *GetLastError;
 
 static void *CreateEvent;
 static void *CreateThread;
 static void *GetModuleHandle;
-static void *GetProcAddress;
-static void *LoadLibraryEx;
 static void *WaitForSingleObject;
 
 static void*
@@ -65,6 +66,7 @@ osinit(void)
        VirtualAlloc = get_proc_addr("kernel32.dll", "VirtualAlloc");
        WaitForSingleObject = get_proc_addr("kernel32.dll", "WaitForSingleObject");
        WriteFile = get_proc_addr("kernel32.dll", "WriteFile");
+       GetLastError = get_proc_addr("kernel32.dll", "GetLastError");
 }
 
 // The arguments are strings.
diff --git a/src/pkg/syscall/asm_mingw_386.s b/src/pkg/syscall/asm_mingw_386.s
new file mode 100644 (file)
index 0000000..c1bd3cc
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//
+// System calls for 386, Windows are implemented in ../runtime/mingw/syscall.cgo
+//
index cfefc671982eb1562e59d76c7330050d6e7086a0..b1650d7ca82fac56cea2b1d0fc1ff6f6846c7f42 100755 (executable)
@@ -144,6 +144,13 @@ linux_arm)
        mktypes="godefs -gsyscall -carm-gcc"
        mkerrors="mkerrors.sh"
        ;;
+mingw_386)
+       # TODO(brainman): create proper mksyscall / mksysnum / mktypes
+       mksyscall="mksyscall.sh -l32"
+       mksysnum="XXXXXX_mksysnum.sh"
+       mktypes="XXXXXX_godefs -gsyscall -f-m32"
+       exit 1
+       ;;
 *)
        echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
        exit 1
diff --git a/src/pkg/syscall/syscall_mingw.go b/src/pkg/syscall/syscall_mingw.go
new file mode 100644 (file)
index 0000000..b653a5a
--- /dev/null
@@ -0,0 +1,163 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Windows system calls.
+
+package syscall
+
+import "unsafe"
+
+const OS = "mingw"
+
+/*
+
+small demo to detect version of windows you are running:
+
+package main
+
+import (
+       "syscall"
+)
+
+func print_version(v uint32) {
+       major := byte(v)
+       minor := uint8(v >> 8)
+       build := uint16(v >> 16)
+       print("windows version ", major, ".", minor, " (Build ", build, ")\n")
+}
+
+func main() {
+       h, err := syscall.LoadLibrary("kernel32.dll")
+       if err != 0 {
+               panic("failed to LoadLibrary #", err, "\n")
+       }
+       defer syscall.FreeLibrary(h)
+       proc, err := syscall.GetProcAddress(h, "GetVersion")
+       if err != 0 {
+               panic("could not GetProcAddress #", err, "\n")
+       }
+       r, _, e := syscall.Syscall(uintptr(proc), 0, 0, 0)
+       err = int(e)
+       if err != 0 {
+               panic("GetVersion failed #", err, "\n")
+       }
+       print_version(uint32(r))
+}
+
+*/
+
+//sys  GetLastError() (lasterrno int)
+
+// TODO(brainman): probably should use LoadLibraryW here instead
+//sys  LoadLibraryA(libname string) (handle Module, errno int)
+
+func LoadLibrary(libname string) (handle Module, errno int) {
+       h, e := LoadLibraryA(libname)
+       if int(h) != 0 {
+               return h, 0
+       }
+       return h, e
+}
+
+// TODO(brainman): should handle errors like in LoadLibrary, otherwise will be returning 'old' errors
+//sys  FreeLibrary(handle Module) (ok Bool, errno int)
+//sys  GetProcAddress(module Module, procname string) (proc uint32, errno int)
+//sys  GetVersion() (ver uint32, errno int)
+
+// dll helpers
+
+// implemented in ../pkg/runtime/mingw/syscall.cgo
+func loadlibraryex(filename uintptr) (handle uint32)
+func getprocaddress(handle uint32, procname uintptr) (proc uintptr)
+
+func loadDll(fname string) Module {
+       m := loadlibraryex(uintptr(unsafe.Pointer(StringBytePtr(fname))))
+       if m == 0 {
+               panic("syscall: could not LoadLibraryEx ", fname)
+       }
+       return Module(m)
+}
+
+func getSysProcAddr(m Module, pname string) uintptr {
+       p := getprocaddress(uint32(m), uintptr(unsafe.Pointer(StringBytePtr(pname))))
+       if p == 0 {
+               panic("syscall: could not GetProcAddress for ", pname)
+       }
+       return p
+}
+
+// TODO(brainman): fix all this meaningless code, it is here to compile exec.go
+
+func Pipe(p []int) (errno int) { return EMINGW }
+
+//sys  Close(fd int) (errno int)
+//sys  read(fd int, buf *byte, nbuf int) (n int, errno int)
+
+func fcntl(fd, cmd, arg int) (val int, errno int) {
+       return 0, EMINGW
+}
+
+const (
+       F_SETFD = 1 + iota
+       FD_CLOEXEC
+       F_GETFL
+       F_SETFL
+       O_NONBLOCK
+       SYS_FORK
+       SYS_PTRACE
+       SYS_CHDIR
+       SYS_DUP2
+       SYS_FCNTL
+       SYS_EXECVE
+       PTRACE_TRACEME
+       SYS_CLOSE
+       SYS_WRITE
+       SYS_EXIT
+       SYS_READ
+       EPIPE
+       EINTR
+)
+
+type Rusage struct {
+       Utime    Timeval
+       Stime    Timeval
+       Maxrss   int32
+       Ixrss    int32
+       Idrss    int32
+       Isrss    int32
+       Minflt   int32
+       Majflt   int32
+       Nswap    int32
+       Inblock  int32
+       Oublock  int32
+       Msgsnd   int32
+       Msgrcv   int32
+       Nsignals int32
+       Nvcsw    int32
+       Nivcsw   int32
+}
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+       return 0, EMINGW
+}
+
+type WaitStatus uint32
+
+func (WaitStatus) Exited() bool { return false }
+
+func (WaitStatus) ExitStatus() int { return -1 }
+
+func (WaitStatus) Signal() int { return -1 }
+
+func (WaitStatus) CoreDump() bool { return false }
+
+func (WaitStatus) Stopped() bool { return false }
+
+func (WaitStatus) Continued() bool { return false }
+
+func (WaitStatus) StopSignal() int { return -1 }
+
+func (WaitStatus) Signaled() bool { return false }
+
+func (WaitStatus) TrapCause() int { return -1 }
diff --git a/src/pkg/syscall/syscall_mingw_386.go b/src/pkg/syscall/syscall_mingw_386.go
new file mode 100644 (file)
index 0000000..61d2d8c
--- /dev/null
@@ -0,0 +1,5 @@
+// Copyright 2009 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
diff --git a/src/pkg/syscall/zerrors_mingw_386.go b/src/pkg/syscall/zerrors_mingw_386.go
new file mode 100644 (file)
index 0000000..cd51d22
--- /dev/null
@@ -0,0 +1,15 @@
+// mkerrors_nacl.sh /home/rsc/pub/nacl/native_client/src/trusted/service_runtime/include/sys/errno.h
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package syscall
+
+// TODO(brainman): populate errors in zerrors_mingw.go
+
+const (
+       EMINGW = 99 /* otherwise unused */
+)
+
+// Error table
+var errors = [...]string{
+       EMINGW: "not supported by windows",
+}
diff --git a/src/pkg/syscall/zsyscall_mingw_386.go b/src/pkg/syscall/zsyscall_mingw_386.go
new file mode 100644 (file)
index 0000000..c457eb4
--- /dev/null
@@ -0,0 +1,53 @@
+// mksyscall.sh -l32 syscall_mingw.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package syscall
+
+import "unsafe"
+
+func GetLastError() (lasterrno int) {
+       r0, _, _ := Syscall(SYS_GET_LAST_ERROR, 0, 0, 0)
+       lasterrno = int(r0)
+       return
+}
+
+func LoadLibraryA(libname string) (handle Module, errno int) {
+       r0, _, e1 := Syscall(SYS_LOAD_LIBRARY_A, uintptr(unsafe.Pointer(StringBytePtr(libname))), 0, 0)
+       handle = Module(r0)
+       errno = int(e1)
+       return
+}
+
+func FreeLibrary(handle Module) (ok Bool, errno int) {
+       r0, _, e1 := Syscall(SYS_FREE_LIBRARY, uintptr(handle), 0, 0)
+       ok = Bool(r0)
+       errno = int(e1)
+       return
+}
+
+func GetProcAddress(module Module, procname string) (proc uint32, errno int) {
+       r0, _, e1 := Syscall(SYS_GET_PROC_ADDRESS, uintptr(module), uintptr(unsafe.Pointer(StringBytePtr(procname))), 0)
+       proc = uint32(r0)
+       errno = int(e1)
+       return
+}
+
+func GetVersion() (ver uint32, errno int) {
+       r0, _, e1 := Syscall(SYS_GET_VERSION, 0, 0, 0)
+       ver = uint32(r0)
+       errno = int(e1)
+       return
+}
+
+func Close(fd int) (errno int) {
+       _, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+       errno = int(e1)
+       return
+}
+
+func read(fd int, buf *byte, nbuf int) (n int, errno int) {
+       r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf))
+       n = int(r0)
+       errno = int(e1)
+       return
+}
diff --git a/src/pkg/syscall/zsysnum_mingw_386.go b/src/pkg/syscall/zsysnum_mingw_386.go
new file mode 100644 (file)
index 0000000..144cf2b
--- /dev/null
@@ -0,0 +1,15 @@
+// mksysnum_nacl.sh /home/rsc/pub/nacl/native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+// TODO(brainman): autogenerate winapi proc pointers in zsysnum_mingw.go
+
+var (
+       SYS_KERNEL32         = loadDll("kernel32.dll")
+       SYS_GET_LAST_ERROR   = getSysProcAddr(SYS_KERNEL32, "GetLastError")
+       SYS_LOAD_LIBRARY_A   = getSysProcAddr(SYS_KERNEL32, "LoadLibraryA")
+       SYS_FREE_LIBRARY     = getSysProcAddr(SYS_KERNEL32, "FreeLibrary")
+       SYS_GET_PROC_ADDRESS = getSysProcAddr(SYS_KERNEL32, "GetProcAddress")
+       SYS_GET_VERSION      = getSysProcAddr(SYS_KERNEL32, "GetVersion")
+)
diff --git a/src/pkg/syscall/ztypes_mingw_386.go b/src/pkg/syscall/ztypes_mingw_386.go
new file mode 100644 (file)
index 0000000..24e9f40
--- /dev/null
@@ -0,0 +1,44 @@
+// godefs -gsyscall -f-m32 types_linux.c
+
+// MACHINE GENERATED - DO NOT EDIT.
+
+package syscall
+
+// TODO(brainman): autogenerate types in ztypes_mingw_386.go
+
+//import "unsafe"
+
+// Constants
+const (
+       sizeofPtr           = 0x4
+       sizeofShort         = 0x2
+       sizeofInt           = 0x4
+       sizeofLong          = 0x4
+       sizeofLongLong      = 0x8
+       PathMax             = 0x1000
+       SizeofSockaddrInet4 = 0x10
+       SizeofSockaddrInet6 = 0x1c
+       SizeofSockaddrAny   = 0x70
+       SizeofSockaddrUnix  = 0x6e
+       SizeofLinger        = 0x8
+       SizeofMsghdr        = 0x1c
+       SizeofCmsghdr       = 0xc
+)
+
+// Types
+
+type _C_short int16
+
+type _C_int int32
+
+type _C_long int32
+
+type _C_long_long int64
+
+type Bool uint32
+type Module uint32
+
+type Timeval struct {
+       Sec  int32
+       Usec int32
+}