aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/syscall_windows.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2021-05-21 20:30:02 +0000
committerMichael Knyszek <mknyszek@google.com>2021-05-24 16:47:51 +0000
commit4356e7e85fcd8f59de6bc1fd1db6e4f01a92f19e (patch)
treebd1c1fcd59d30d700f410321dee30c20d87f4a73 /src/runtime/syscall_windows.go
parent52d7033ff6d56094b7fa852bbdf51b4525bd6bb2 (diff)
downloadgo-4356e7e85fcd8f59de6bc1fd1db6e4f01a92f19e.tar.gz
go-4356e7e85fcd8f59de6bc1fd1db6e4f01a92f19e.zip
runtime: account for spill slots in Windows callback compilation
The Go ABI, as it stands, requires spill space to be reserved for register arguments. syscall.NewCallback (because of compileCallback) does not actually reserve this space, leading to issues if the Go code it invokes actually makes use of it. Fixes #46301. Change-Id: Idbc3578accaaaa29e4ba32291ef08d464da0b7b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/322029 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Egon Elbre <egonelbre@gmail.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/runtime/syscall_windows.go')
-rw-r--r--src/runtime/syscall_windows.go23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
index 6b9195bcd5..4763a440e7 100644
--- a/src/runtime/syscall_windows.go
+++ b/src/runtime/syscall_windows.go
@@ -64,6 +64,7 @@ type abiDesc struct {
srcStackSize uintptr // stdcall/fastcall stack space tracking
dstStackSize uintptr // Go stack space used
+ dstSpill uintptr // Extra stack space for argument spill slots
dstRegisters int // Go ABI int argument registers used
// retOffset is the offset of the uintptr-sized result in the Go
@@ -110,7 +111,14 @@ func (p *abiDesc) assignArg(t *_type) {
// arguments. The same is true on arm.
oldParts := p.parts
- if !p.tryRegAssignArg(t, 0) {
+ if p.tryRegAssignArg(t, 0) {
+ // Account for spill space.
+ //
+ // TODO(mknyszek): Remove this when we no longer have
+ // caller reserved spill space.
+ p.dstSpill = alignUp(p.dstSpill, uintptr(t.align))
+ p.dstSpill += t.size
+ } else {
// Register assignment failed.
// Undo the work and stack assign.
p.parts = oldParts
@@ -277,7 +285,11 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
abiMap.dstStackSize += sys.PtrSize
}
- if abiMap.dstStackSize > callbackMaxFrame {
+ // TODO(mknyszek): Remove dstSpill from this calculation when we no longer have
+ // caller reserved spill space.
+ frameSize := alignUp(abiMap.dstStackSize, sys.PtrSize)
+ frameSize += abiMap.dstSpill
+ if frameSize > callbackMaxFrame {
panic("compileCallback: function argument frame too large")
}
@@ -356,9 +368,14 @@ func callbackWrap(a *callbackArgs) {
}
}
+ // TODO(mknyszek): Remove this when we no longer have
+ // caller reserved spill space.
+ frameSize := alignUp(c.abiMap.dstStackSize, sys.PtrSize)
+ frameSize += c.abiMap.dstSpill
+
// Even though this is copying back results, we can pass a nil
// type because those results must not require write barriers.
- reflectcall(nil, unsafe.Pointer(c.fn), noescape(goArgs), uint32(c.abiMap.dstStackSize), uint32(c.abiMap.retOffset), uint32(c.abiMap.dstStackSize), &regs)
+ reflectcall(nil, unsafe.Pointer(c.fn), noescape(goArgs), uint32(c.abiMap.dstStackSize), uint32(c.abiMap.retOffset), uint32(frameSize), &regs)
// Extract the result.
//