|
Revision tags: dev, v36.0.9, v44.0.1, v43.0.2, v36.0.8, v24.0.8, v44.0.0, v43.0.1, v42.0.2, v36.0.7, v24.0.7, v43.0.0, v42.0.1, v41.0.4, v42.0.0, v40.0.4, v36.0.6, v24.0.6, v41.0.3, v41.0.2, v41.0.1, v36.0.5, v40.0.3, v41.0.0, v36.0.4, v39.0.2, v40.0.2, v40.0.1, v40.0.0, v39.0.1, v39.0.0, v38.0.4, v37.0.3, v36.0.3, v24.0.5, v38.0.3, v38.0.2, v38.0.1, v37.0.2, v37.0.1, v37.0.0, v36.0.2 |
| #
fa1d6867 |
| 21-Aug-2025 |
Chris Fallin <[email protected]> |
Wasmtime/Cranelift: carry "FP to SP offset" in exception data, and use it in stackwalk. (#11500)
* Wasmtime/Cranelift: carry "FP to SP offset" in exception data, and use it in stackwalk.
Currently
Wasmtime/Cranelift: carry "FP to SP offset" in exception data, and use it in stackwalk. (#11500)
* Wasmtime/Cranelift: carry "FP to SP offset" in exception data, and use it in stackwalk.
Currently Wasmtime unwinds stack frames to look for exception handlers by walking frames one-by-one, following the FP chain as usual, and assuming that *these frames are contiguous*: that is, that the SP in any given frame (bottom of that frame) is immediately above the FP of the next lower frame, plus the FP/return address pair (e.g. 16 bytes). This allows us to get the SP for any given frame in addition to FP. We need SP for two reasons:
- To look up dynamic context, to match Wasm tag instances for handlers against the thrown tag; - To actually set SP when we resume, if we do resume to a handler in this frame.
This logic *almost but not quite* worked: I had forgotten that in our tail-call ABI, we need to clean up incoming stack args in the callee (because only the final callee in a parade of tail-calling functions that reuse the same stack frame location knows how many args it has, not the original caller). This implies that there is an "incoming args area" *above* the FP/return address pair. Thus, frames are not necessarily contiguous by the above definition.
In #11489 we see a case where a function of signature `(func)` tail-calls one of `(func (param i32 i32 i32 i32 i32))`, which on x86-64 (with four arg registers left for Wasm) is sufficient to create incoming stack args, which then trips up the unwinder, reading a bogus vmctx and segfaulting.
The most reasonable solution seems to be to embed the SP-to-FP offset in the exception metadata itself, so from only the FP (which is totally robust -- we rely on the FP chain for multiple kinds of stack-walking) we can get the SP, allowing us to read dynamic context and to reset SP during resume.
This PR does just that. Technically, in our ABI, the SP-to-FP offset is constant for an entire function, but it was simpler in the exception metadata to encode this per callsite instead (there is no other notion of "per-function" data, only "per-callsite", so it would be a separate binary search).
Fixes #11489.
prtest:full
* Review feedback.
show more ...
|