[wasm] Fix stack args in CWasmEntry stub

The particular combination of (1) having callee-saved registers in
the stub per the C++ calling convention, (2) passing arguments to
the callee on the stack, and (3) that callee throwing an exception,
caused the saved registers to be restored to bogus values.
To fix this, the stack unwinder needs to compute the stub's frame
size correctly (i.e. without stack parameters).

Bug: chromium:1007608
Change-Id: Iadd99f10764f49f9e3c620c05723e09172c73cf7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1847352
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64160}
This commit is contained in:
Jakob Kummerow 2019-10-08 12:46:38 +02:00 committed by Commit Bot
parent ce3f018722
commit f1e5488a7f
2 changed files with 32 additions and 1 deletions

View File

@ -1683,8 +1683,13 @@ Object Isolate::UnwindAndFindHandler() {
int return_offset = static_cast<int>(frame->pc() - instruction_start);
int handler_offset = table.LookupReturn(return_offset);
DCHECK_NE(-1, handler_offset);
// Compute the stack pointer from the frame pointer. This ensures that
// argument slots on the stack are dropped as returning would.
Address return_sp = frame->fp() +
StandardFrameConstants::kFixedFrameSizeAboveFp -
code.stack_slots() * kSystemPointerSize;
return FoundHandler(Context(), instruction_start, handler_offset,
code.constant_pool(), frame->sp(), frame->fp());
code.constant_pool(), return_sp, frame->fp());
}
case StackFrame::WASM_COMPILED: {

View File

@ -0,0 +1,26 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Bug is in the C-to-Wasm entry, used e.g. by the Wasm interpreter.
// Flags: --wasm-interpret-all
load("test/mjsunit/wasm/wasm-module-builder.js");
let argc = 7;
let builder = new WasmModuleBuilder();
let types = new Array(argc).fill(kWasmI32);
let sig = makeSig(types, []);
let body = [];
for (let i = 0; i < argc; ++i) {
body.push(kExprGetLocal, i);
}
body.push(kExprCallFunction, 0);
builder.addImport('', 'f', sig);
builder.addFunction("main", sig).addBody(body).exportAs('main');
let instance = builder.instantiate({
'': {
'f': function() { throw "don't crash"; }
}
});
assertThrows(instance.exports.main);