//go:linkname syscall_loadlibrary syscall.loadlibrary
//go:nosplit
func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
- var c libcall
+ c := &getg().m.syscall
c.fn = getLoadLibrary()
c.n = 1
- c.args = uintptr(unsafe.Pointer(&filename))
- cgocall(asmstdcallAddr, unsafe.Pointer(&c))
+ c.args = uintptr(noescape(unsafe.Pointer(&filename)))
+ cgocall(asmstdcallAddr, unsafe.Pointer(c))
handle = c.r1
if handle == 0 {
err = c.err
//go:linkname syscall_getprocaddress syscall.getprocaddress
//go:nosplit
func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {
- var c libcall
+ c := &getg().m.syscall
c.fn = getGetProcAddress()
c.n = 2
- c.args = uintptr(unsafe.Pointer(&handle))
- cgocall(asmstdcallAddr, unsafe.Pointer(&c))
+ c.args = uintptr(noescape(unsafe.Pointer(&handle)))
+ cgocall(asmstdcallAddr, unsafe.Pointer(c))
outhandle = c.r1
if outhandle == 0 {
err = c.err
//go:linkname syscall_Syscall syscall.Syscall
//go:nosplit
func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
- var c libcall
+ c := &getg().m.syscall
c.fn = fn
c.n = nargs
- c.args = uintptr(unsafe.Pointer(&a1))
- cgocall(asmstdcallAddr, unsafe.Pointer(&c))
+ c.args = uintptr(noescape(unsafe.Pointer(&a1)))
+ cgocall(asmstdcallAddr, unsafe.Pointer(c))
return c.r1, c.r2, c.err
}
//go:linkname syscall_Syscall6 syscall.Syscall6
//go:nosplit
func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
- var c libcall
+ c := &getg().m.syscall
c.fn = fn
c.n = nargs
- c.args = uintptr(unsafe.Pointer(&a1))
- cgocall(asmstdcallAddr, unsafe.Pointer(&c))
+ c.args = uintptr(noescape(unsafe.Pointer(&a1)))
+ cgocall(asmstdcallAddr, unsafe.Pointer(c))
return c.r1, c.r2, c.err
}
//go:linkname syscall_Syscall9 syscall.Syscall9
//go:nosplit
func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
- var c libcall
+ c := &getg().m.syscall
c.fn = fn
c.n = nargs
- c.args = uintptr(unsafe.Pointer(&a1))
- cgocall(asmstdcallAddr, unsafe.Pointer(&c))
+ c.args = uintptr(noescape(unsafe.Pointer(&a1)))
+ cgocall(asmstdcallAddr, unsafe.Pointer(c))
return c.r1, c.r2, c.err
}
//go:linkname syscall_Syscall12 syscall.Syscall12
//go:nosplit
func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) {
- var c libcall
+ c := &getg().m.syscall
c.fn = fn
c.n = nargs
- c.args = uintptr(unsafe.Pointer(&a1))
- cgocall(asmstdcallAddr, unsafe.Pointer(&c))
+ c.args = uintptr(noescape(unsafe.Pointer(&a1)))
+ cgocall(asmstdcallAddr, unsafe.Pointer(c))
return c.r1, c.r2, c.err
}
//go:linkname syscall_Syscall15 syscall.Syscall15
//go:nosplit
func syscall_Syscall15(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
- var c libcall
+ c := &getg().m.syscall
c.fn = fn
c.n = nargs
- c.args = uintptr(unsafe.Pointer(&a1))
- cgocall(asmstdcallAddr, unsafe.Pointer(&c))
+ c.args = uintptr(noescape(unsafe.Pointer(&a1)))
+ cgocall(asmstdcallAddr, unsafe.Pointer(c))
return c.r1, c.r2, c.err
}
// Child process should not open WER dialogue, but return immediately instead.
cmd.CombinedOutput()
}
+
+var used byte
+
+func use(buf []byte) {
+ for _, c := range buf {
+ used += c
+ }
+}
+
+func forceStackCopy() (r int) {
+ var f func(int) int
+ f = func(i int) int {
+ var buf [256]byte
+ use(buf[:])
+ if i == 0 {
+ return 0
+ }
+ return i + f(i-1)
+ }
+ r = f(128)
+ return
+}
+
+func TestReturnAfterStackGrowInCallback(t *testing.T) {
+
+ const src = `
+#include <stdint.h>
+#include <windows.h>
+
+typedef uintptr_t __stdcall (*callback)(uintptr_t);
+
+uintptr_t cfunc(callback f, uintptr_t n) {
+ uintptr_t r;
+ r = f(n);
+ SetLastError(333);
+ return r;
+}
+`
+ tmpdir, err := ioutil.TempDir("", "TestReturnAfterStackGrowInCallback")
+ if err != nil {
+ t.Fatal("TempDir failed: ", err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ srcname := "mydll.c"
+ err = ioutil.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ outname := "mydll.dll"
+ cmd := exec.Command("gcc", "-shared", "-s", "-Werror", "-o", outname, srcname)
+ cmd.Dir = tmpdir
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("failed to build dll: %v - %v", err, string(out))
+ }
+ dllpath := filepath.Join(tmpdir, outname)
+
+ dll := syscall.MustLoadDLL(dllpath)
+ defer dll.Release()
+
+ proc := dll.MustFindProc("cfunc")
+
+ cb := syscall.NewCallback(func(n uintptr) uintptr {
+ forceStackCopy()
+ return n
+ })
+
+ // Use a new goroutine so that we get a small stack.
+ type result struct {
+ r uintptr
+ err syscall.Errno
+ }
+ c := make(chan result)
+ go func() {
+ r, _, err := proc.Call(cb, 100)
+ c <- result{r, err.(syscall.Errno)}
+ }()
+ want := result{r: 100, err: 333}
+ if got := <-c; got != want {
+ t.Errorf("got %d want %d", got, want)
+ }
+}