Skip to content

Commit 0932b0f

Browse files
committed
runtime: add crash stack support for wasm
Currently if morestack on g0 happens the wasm runtime prints "RuntimeError: memory access out of bounds", which is quite misleading. By switching to a crash stack we can get better stacktraces for the error. There is no way to automate tests for this feature on wasm, since TestG0StackOverflow relies on spawning a subprocess which is not supported by the wasm port. The way I got this tested manually is to comment everything in TestG0StackOverflow, leaving just runtime.G0StackOverflow(). Then it is a matter of invoking the test: GOOS=js GOARCH=wasm go test runtime -v -run=TestG0StackOverflow Change-Id: If2819938d6424da1b4fd7e8e5dc53e8efeeebb6d
1 parent d72f454 commit 0932b0f

File tree

3 files changed

+44
-9
lines changed

3 files changed

+44
-9
lines changed

src/runtime/asm.s

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ TEXT ·mapinitnoop<ABIInternal>(SB),NOSPLIT,$0-0
1616
#ifndef GOARCH_amd64
1717
#ifndef GOARCH_arm64
1818
#ifndef GOARCH_riscv64
19+
#ifndef GOARCH_wasm
1920
// stub to appease shared build mode.
2021
TEXT ·switchToCrashStack0<ABIInternal>(SB),NOSPLIT,$0-0
2122
UNDEF
2223
#endif
2324
#endif
2425
#endif
26+
#endif

src/runtime/asm_wasm.s

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-8
140140
I64Ne
141141
If
142142
CALLNORESUME runtime·badsystemstack(SB)
143+
UNDEF
143144
End
144145

145146
// switch:
@@ -181,6 +182,9 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-8
181182
TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
182183
RET
183184

185+
TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
186+
UNDEF
187+
184188
// AES hashing not implemented for wasm
185189
TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32
186190
JMP runtime·memhashFallback(SB)
@@ -208,6 +212,33 @@ TEXT runtime·procyield(SB), NOSPLIT, $0-0 // FIXME
208212
TEXT runtime·breakpoint(SB), NOSPLIT, $0-0
209213
UNDEF
210214

215+
// func switchToCrashStack0(fn func())
216+
TEXT runtime·switchToCrashStack0(SB), NOSPLIT, $0-8
217+
MOVD fn+0(FP), CTXT // context register
218+
MOVD g_m(g), R2 // curm
219+
220+
// set g to gcrash
221+
MOVD $runtime·gcrash(SB), g // g = &gcrash
222+
MOVD R2, g_m(g) // g.m = curm
223+
MOVD g, m_g0(R2) // curm.g0 = g
224+
225+
// switch to crashstack
226+
I64Load (g_stack+stack_hi)(g)
227+
I64Const $(-4*8)
228+
I64Add
229+
I32WrapI64
230+
Set SP
231+
232+
// call target function
233+
Get CTXT
234+
I32WrapI64
235+
I64Load $0
236+
CALL
237+
238+
// should never return
239+
CALL runtime·abort(SB)
240+
UNDEF
241+
211242
// Called during function prolog when more stack is needed.
212243
//
213244
// The traceback routines see morestack on a g0 as being
@@ -221,12 +252,19 @@ TEXT runtime·morestack(SB), NOSPLIT, $0-0
221252
// R2 = g0
222253
MOVD m_g0(R1), R2
223254

255+
// Set g->sched to context in f.
256+
NOP SP // tell vet SP changed - stop checking offsets
257+
MOVD 0(SP), g_sched+gobuf_pc(g)
258+
MOVD $8(SP), g_sched+gobuf_sp(g) // f's SP
259+
MOVD CTXT, g_sched+gobuf_ctxt(g)
260+
224261
// Cannot grow scheduler stack (m->g0).
225262
Get g
226-
Get R1
263+
Get R2
227264
I64Eq
228265
If
229266
CALLNORESUME runtime·badmorestackg0(SB)
267+
CALLNORESUME runtime·abort(SB)
230268
End
231269

232270
// Cannot grow signal stack (m->gsignal).
@@ -235,20 +273,15 @@ TEXT runtime·morestack(SB), NOSPLIT, $0-0
235273
I64Eq
236274
If
237275
CALLNORESUME runtime·badmorestackgsignal(SB)
276+
CALLNORESUME runtime·abort(SB)
238277
End
239278

240279
// Called from f.
241280
// Set m->morebuf to f's caller.
242-
NOP SP // tell vet SP changed - stop checking offsets
243281
MOVD 8(SP), m_morebuf+gobuf_pc(R1)
244282
MOVD $16(SP), m_morebuf+gobuf_sp(R1) // f's caller's SP
245283
MOVD g, m_morebuf+gobuf_g(R1)
246284

247-
// Set g->sched to context in f.
248-
MOVD 0(SP), g_sched+gobuf_pc(g)
249-
MOVD $8(SP), g_sched+gobuf_sp(g) // f's SP
250-
MOVD CTXT, g_sched+gobuf_ctxt(g)
251-
252285
// Call newstack on m->g0's stack.
253286
MOVD R2, g
254287
MOVD g_sched+gobuf_sp(R2), SP

src/runtime/proc.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,10 +574,10 @@ func switchToCrashStack(fn func()) {
574574
abort()
575575
}
576576

577-
const crashStackImplemented = GOARCH == "amd64" || GOARCH == "arm64" || GOARCH == "riscv64"
577+
const crashStackImplemented = GOARCH == "amd64" || GOARCH == "arm64" || GOARCH == "riscv64" || GOARCH == "wasm"
578578

579579
//go:noescape
580-
func switchToCrashStack0(func()) // in assembly
580+
func switchToCrashStack0(fn func()) // in assembly
581581

582582
func lockedOSThread() bool {
583583
gp := getg()

0 commit comments

Comments
 (0)