]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/wasm: correct return PC for frameless wasmexport wrappers
authorCherry Mui <cherryyz@google.com>
Fri, 1 Nov 2024 16:04:49 +0000 (12:04 -0400)
committerCherry Mui <cherryyz@google.com>
Wed, 13 Nov 2024 20:09:36 +0000 (20:09 +0000)
For a wasmexport wrapper, we generate a call to the actual
exported Go function, and use the wrapper function's PC 1 as the
(fake) return address. This address is not used for returning,
which is handled by the Wasm call stack. It is used for stack
unwinding, and PC 1 makes it past the prologue and therefore has
the right SP delta. But if the function has no arguments and
results, the wrapper is frameless, with no prologue, and PC 1
doesn't exist. This causes the unwinder to fail. In this case, we
put PC 0, which also has the correct SP delta (0).

Fixes #69584.

Change-Id: Ic047a6e62100db540b5099cc5a56a1d0f16d58b9
Reviewed-on: https://go-review.googlesource.com/c/go/+/624000
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

lib/wasm/wasm_exec.js
src/cmd/internal/obj/wasm/wasmobj.go
src/syscall/js/js_test.go

index af7e28f5f48e07f58ab71ba5fbe4cf8575e89dfd..ec96d42db52cc7639e6817e27395317900e63640 100644 (file)
                        }
 
                        const testCallExport = (a, b) => {
+                               this._inst.exports.testExport0();
                                return this._inst.exports.testExport(a, b);
                        }
 
index 28ecd20cd0e51d40661fe602c4cb1e3cb0743c28..48eee4e3ea12de20f887ca22cbb058cd5de3b37f 100644 (file)
@@ -974,6 +974,10 @@ func genWasmExportWrapper(s *obj.LSym, appendp func(p *obj.Prog, as obj.As, args
                Sym:    s, // PC_F
                Offset: 1, // PC_B=1, past the prologue, so we have the right SP delta
        }
+       if framesize == 0 {
+               // Frameless function, no prologue.
+               retAddr.Offset = 0
+       }
        p = appendp(p, AI64Const, retAddr)
        p = appendp(p, AI64Store, constAddr(0))
        // Set PC_B parameter to function entry
@@ -1014,11 +1018,13 @@ func genWasmExportWrapper(s *obj.LSym, appendp func(p *obj.Prog, as obj.As, args
        }
 
        // Epilogue. Cannot use ARET as we don't follow Go calling convention.
-       // SP += framesize
-       p = appendp(p, AGet, regAddr(REG_SP))
-       p = appendp(p, AI32Const, constAddr(framesize))
-       p = appendp(p, AI32Add)
-       p = appendp(p, ASet, regAddr(REG_SP))
+       if framesize > 0 {
+               // SP += framesize
+               p = appendp(p, AGet, regAddr(REG_SP))
+               p = appendp(p, AI32Const, constAddr(framesize))
+               p = appendp(p, AI32Add)
+               p = appendp(p, ASet, regAddr(REG_SP))
+       }
        p = appendp(p, AReturn)
 }
 
index 76fa44244259c9a10c70639634220bbd336e84c4..9ab913f2abf71475c808ab8015e440bd1cbbdd46 100644 (file)
@@ -75,6 +75,11 @@ func testExport(a int32, b int64) int64 {
        return <-ch + <-ch
 }
 
+//go:wasmexport testExport0
+func testExport0() { // no arg or result (see issue 69584)
+       runtime.GC()
+}
+
 var testExportCalled bool
 
 func growStack(n int64) {