1
0
mirror of https://github.com/golang/go synced 2024-11-07 12:36:27 -07:00
go/src/runtime/rt0_js_wasm.s
Cherry Zhang e9c994954f runtime: fix past-the-end write of wasmStack
On Wasm, at program start, we set the SP to
wasmStack+sizeof(wasmStack), and start to write on it. This write
is actually past the end of wasmStack. This may scribble to some
other variable next to it in the data segment. Or if wasmStack
happens to be the last object in the data segment, we'll scribble
to unreserved memory and cause the next sysReserve return
non-zero memory. Either way, this is bad. Fix this by subtracting
16 before writing.

Found while debugging the new page allocator (CL 190622 and the
stack) with Michael. We found that on Wasm, the first sysReserve
may return memory with the first a few words being non-zero.

Change-Id: I2d76dd3fee85bddb2ff6a902b5876dea3f2969a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/202086
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2019-10-19 04:45:10 +00:00

108 lines
2.3 KiB
ArmAsm

// Copyright 2018 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.
#include "go_asm.h"
#include "textflag.h"
// _rt0_wasm_js is not used itself. It only exists to mark the exported functions as alive.
TEXT _rt0_wasm_js(SB),NOSPLIT,$0
I32Const $wasm_export_run(SB)
Drop
I32Const $wasm_export_resume(SB)
Drop
I32Const $wasm_export_getsp(SB)
Drop
// wasm_export_run gets called from JavaScript. It initializes the Go runtime and executes Go code until it needs
// to wait for an event. It does NOT follow the Go ABI. It has two WebAssembly parameters:
// R0: argc (i32)
// R1: argv (i32)
TEXT wasm_export_run(SB),NOSPLIT,$0
MOVD $runtime·wasmStack+(m0Stack__size-16)(SB), SP
Get SP
Get R0 // argc
I64ExtendI32U
I64Store $0
Get SP
Get R1 // argv
I64ExtendI32U
I64Store $8
I32Const $0 // entry PC_B
Call runtime·rt0_go(SB)
Drop
Call wasm_pc_f_loop(SB)
Return
// wasm_export_resume gets called from JavaScript. It resumes the execution of Go code until it needs to wait for
// an event.
TEXT wasm_export_resume(SB),NOSPLIT,$0
I32Const $0
Call runtime·handleEvent(SB)
Drop
Call wasm_pc_f_loop(SB)
Return
TEXT wasm_pc_f_loop(SB),NOSPLIT,$0
// Call the function for the current PC_F. Repeat until PAUSE != 0 indicates pause or exit.
// The WebAssembly stack may unwind, e.g. when switching goroutines.
// The Go stack on the linear memory is then used to jump to the correct functions
// with this loop, without having to restore the full WebAssembly stack.
// It is expected to have a pending call before entering the loop, so check PAUSE first.
Get PAUSE
I32Eqz
If
loop:
Loop
// Get PC_B & PC_F from -8(SP)
Get SP
I32Const $8
I32Sub
I32Load16U $0 // PC_B
Get SP
I32Const $8
I32Sub
I32Load16U $2 // PC_F
CallIndirect $0
Drop
Get PAUSE
I32Eqz
BrIf loop
End
End
I32Const $0
Set PAUSE
Return
// wasm_export_getsp gets called from JavaScript to retrieve the SP.
TEXT wasm_export_getsp(SB),NOSPLIT,$0
Get SP
Return
TEXT runtime·pause(SB), NOSPLIT, $0-8
MOVD newsp+0(FP), SP
I32Const $1
Set PAUSE
RETUNWIND
TEXT runtime·exit(SB), NOSPLIT, $0-4
I32Const $0
Call runtime·wasmExit(SB)
Drop
I32Const $1
Set PAUSE
RETUNWIND
TEXT wasm_export_lib(SB),NOSPLIT,$0
UNDEF