v8/test/unittests/wasm/trap-handler-x64-unittest.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

487 lines
17 KiB
C++
Raw Normal View History

// Copyright 2018 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.
#include "include/v8config.h"
#if V8_OS_LINUX || V8_OS_FREEBSD
#include <signal.h>
#include <ucontext.h>
#elif V8_OS_MACOSX
#include <signal.h>
#include <sys/ucontext.h>
#elif V8_OS_WIN
#include <windows.h>
#endif
#include "testing/gtest/include/gtest/gtest.h"
#if V8_OS_POSIX
#include "include/v8-wasm-trap-handler-posix.h"
#elif V8_OS_WIN
#include "include/v8-wasm-trap-handler-win.h"
#endif
#include "src/base/page-allocator.h"
#include "src/codegen/assembler-inl.h"
#include "src/codegen/macro-assembler-inl.h"
#include "src/execution/simulator.h"
Reland x6 [arraybuffer] Rearchitect backing store ownership This reverts commit 9da3483136b5e71e830ed9a9c34802ad8d605e58 Original change's description: > "Reland x4 [arraybuffer] Rearchitect backing store ownership" > > This is a reland of bc33f5aeba9ceb13f8bfc401c5ba2521c2207ffb > > Contributed by titzer@chromium.org > > Original change's description: > > [arraybuffer] Rearchitect backing store ownership > > > > This CL completely rearchitects the ownership of array buffer backing stores, > > consolidating ownership into a {BackingStore} C++ object that is tracked > > throughout V8 using unique_ptr and shared_ptr where appropriate. > > > > Overall, lifetime management is simpler and more explicit. The numerous > > ways that array buffers were initialized have been streamlined to one > > Attach() method on JSArrayBuffer. The array buffer tracker in the > > GC implementation now manages std::shared_ptr<BackingStore> pointers, > > and the construction and destruction of the BackingStore object itself > > handles the underlying page or embedder-allocated memory. > > > > The embedder API remains unchanged for now. We use the > > v8::ArrayBuffer::Contents struct to hide an additional shared_ptr to > > keep the backing store alive properly, even in the case of aliases > > from live heap objects. Thus the embedder has a lower chance of making > > a mistake. Long-term, we should move the embedder to a model where they > > manage backing stores using shared_ptr to an opaque backing store object. > > TBR=yangguo@chromium.org > > BUG=v8:9380,v8:9221,chromium:986318 > > Change-Id: If671a4a9ca0476e8f084efae46e0d2bf99ed99ef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1731005 > Commit-Queue: Ulan Degenbaev <ulan@chromium.org> > Reviewed-by: Clemens Hammacher <clemensh@chromium.org> > Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> > Cr-Commit-Position: refs/heads/master@{#63041} TBR=yangguo@chromium.org Change-Id: I3cc4bb80081c662b1751234bc16a821c20e744be Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1792166 Commit-Queue: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#63617}
2019-09-09 10:19:34 +00:00
#include "src/objects/backing-store.h"
#include "src/trap-handler/trap-handler.h"
#include "src/utils/allocation.h"
#include "src/utils/vector.h"
#include "src/wasm/wasm-engine.h"
#include "test/common/assembler-tester.h"
#include "test/unittests/test-utils.h"
namespace v8 {
namespace internal {
namespace wasm {
namespace {
constexpr Register scratch = r10;
bool g_test_handler_executed = false;
#if V8_OS_LINUX || V8_OS_MACOSX || V8_OS_FREEBSD
struct sigaction g_old_segv_action;
struct sigaction g_old_fpe_action;
struct sigaction g_old_bus_action; // We get SIGBUS on Mac sometimes.
#elif V8_OS_WIN
void* g_registered_handler = nullptr;
#endif
// The recovery address allows us to recover from an intentional crash.
Address g_recovery_address;
// Flag to indicate if the test handler should call the trap handler as a first
// chance handler.
bool g_use_as_first_chance_handler = false;
} // namespace
#define __ masm.
enum TrapHandlerStyle : int {
// The test uses the default trap handler of V8.
kDefault = 0,
// The test installs the trap handler callback in its own test handler.
kCallback = 1
};
std::string PrintTrapHandlerTestParam(
::testing::TestParamInfo<TrapHandlerStyle> info) {
switch (info.param) {
case kDefault:
return "DefaultTrapHandler";
case kCallback:
return "Callback";
}
UNREACHABLE();
}
class TrapHandlerTest : public TestWithIsolate,
public ::testing::WithParamInterface<TrapHandlerStyle> {
protected:
void SetUp() override {
Revert "[wasm] Disallow late enabling of trap handlers" This reverts commit bcb0a7c5c5e13bb895391c63ec30d048f6f58dd1. Reason for revert: TSAN failure (https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20TSAN/33868) Original change's description: > [wasm] Disallow late enabling of trap handlers > > It's dangerous if trap handlers are enabled after we already used the > information whether they are enabled or not. > This CL checks for such misbehaviour by remembering whether > {IsTrapHandlerEnabled} was already called, and disallowing > {EnableTrapHandler} afterwards. Also, calling {EnableTrapHandler} > multiple times is disallowed now. > > The trap handler tests are changed to only enable trap handlers once, > and to do that before allocating wasm memory or generating code. > > R=​ahaas@chromium.org > > Bug: v8:11017 > Change-Id: Ib2256bb8435efd914c12769cedd4a0051052aeef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2494935 > Reviewed-by: Andreas Haas <ahaas@chromium.org> > Commit-Queue: Clemens Backes <clemensb@chromium.org> > Cr-Commit-Position: refs/heads/master@{#70750} TBR=ahaas@chromium.org,clemensb@chromium.org Change-Id: I1d93dcb399e2a0b5b0543aa60d34087317c01cb3 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: v8:11017 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2497176 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#70751}
2020-10-26 10:21:23 +00:00
CHECK(trap_handler::EnableTrapHandler(false));
Reland x6 [arraybuffer] Rearchitect backing store ownership This reverts commit 9da3483136b5e71e830ed9a9c34802ad8d605e58 Original change's description: > "Reland x4 [arraybuffer] Rearchitect backing store ownership" > > This is a reland of bc33f5aeba9ceb13f8bfc401c5ba2521c2207ffb > > Contributed by titzer@chromium.org > > Original change's description: > > [arraybuffer] Rearchitect backing store ownership > > > > This CL completely rearchitects the ownership of array buffer backing stores, > > consolidating ownership into a {BackingStore} C++ object that is tracked > > throughout V8 using unique_ptr and shared_ptr where appropriate. > > > > Overall, lifetime management is simpler and more explicit. The numerous > > ways that array buffers were initialized have been streamlined to one > > Attach() method on JSArrayBuffer. The array buffer tracker in the > > GC implementation now manages std::shared_ptr<BackingStore> pointers, > > and the construction and destruction of the BackingStore object itself > > handles the underlying page or embedder-allocated memory. > > > > The embedder API remains unchanged for now. We use the > > v8::ArrayBuffer::Contents struct to hide an additional shared_ptr to > > keep the backing store alive properly, even in the case of aliases > > from live heap objects. Thus the embedder has a lower chance of making > > a mistake. Long-term, we should move the embedder to a model where they > > manage backing stores using shared_ptr to an opaque backing store object. > > TBR=yangguo@chromium.org > > BUG=v8:9380,v8:9221,chromium:986318 > > Change-Id: If671a4a9ca0476e8f084efae46e0d2bf99ed99ef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1731005 > Commit-Queue: Ulan Degenbaev <ulan@chromium.org> > Reviewed-by: Clemens Hammacher <clemensh@chromium.org> > Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> > Cr-Commit-Position: refs/heads/master@{#63041} TBR=yangguo@chromium.org Change-Id: I3cc4bb80081c662b1751234bc16a821c20e744be Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1792166 Commit-Queue: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#63617}
2019-09-09 10:19:34 +00:00
backing_store_ = BackingStore::AllocateWasmMemory(i_isolate(), 1, 1,
SharedFlag::kNotShared);
CHECK(backing_store_);
CHECK(backing_store_->has_guard_regions());
// The allocated backing store ends with a guard page.
crash_address_ = reinterpret_cast<Address>(backing_store_->buffer_start()) +
backing_store_->byte_length() + 32;
// Allocate a buffer for the generated code.
buffer_ = AllocateAssemblerBuffer(AssemblerBase::kDefaultBufferSize,
GetRandomMmapAddr());
InitRecoveryCode();
#if V8_OS_LINUX || V8_OS_MACOSX || V8_OS_FREEBSD
// Set up a signal handler to recover from the expected crash.
struct sigaction action;
action.sa_sigaction = SignalHandler;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_SIGINFO;
// SIGSEGV happens for wasm oob memory accesses on Linux.
CHECK_EQ(0, sigaction(SIGSEGV, &action, &g_old_segv_action));
// SIGBUS happens for wasm oob memory accesses on macOS.
CHECK_EQ(0, sigaction(SIGBUS, &action, &g_old_bus_action));
// SIGFPE to simulate crashes which are not handled by the trap handler.
CHECK_EQ(0, sigaction(SIGFPE, &action, &g_old_fpe_action));
#elif V8_OS_WIN
g_registered_handler =
AddVectoredExceptionHandler(/*first=*/0, TestHandler);
#endif
}
void TearDown() override {
// We should always have left wasm code.
CHECK(!GetThreadInWasmFlag());
buffer_.reset();
recovery_buffer_.reset();
Reland x6 [arraybuffer] Rearchitect backing store ownership This reverts commit 9da3483136b5e71e830ed9a9c34802ad8d605e58 Original change's description: > "Reland x4 [arraybuffer] Rearchitect backing store ownership" > > This is a reland of bc33f5aeba9ceb13f8bfc401c5ba2521c2207ffb > > Contributed by titzer@chromium.org > > Original change's description: > > [arraybuffer] Rearchitect backing store ownership > > > > This CL completely rearchitects the ownership of array buffer backing stores, > > consolidating ownership into a {BackingStore} C++ object that is tracked > > throughout V8 using unique_ptr and shared_ptr where appropriate. > > > > Overall, lifetime management is simpler and more explicit. The numerous > > ways that array buffers were initialized have been streamlined to one > > Attach() method on JSArrayBuffer. The array buffer tracker in the > > GC implementation now manages std::shared_ptr<BackingStore> pointers, > > and the construction and destruction of the BackingStore object itself > > handles the underlying page or embedder-allocated memory. > > > > The embedder API remains unchanged for now. We use the > > v8::ArrayBuffer::Contents struct to hide an additional shared_ptr to > > keep the backing store alive properly, even in the case of aliases > > from live heap objects. Thus the embedder has a lower chance of making > > a mistake. Long-term, we should move the embedder to a model where they > > manage backing stores using shared_ptr to an opaque backing store object. > > TBR=yangguo@chromium.org > > BUG=v8:9380,v8:9221,chromium:986318 > > Change-Id: If671a4a9ca0476e8f084efae46e0d2bf99ed99ef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1731005 > Commit-Queue: Ulan Degenbaev <ulan@chromium.org> > Reviewed-by: Clemens Hammacher <clemensh@chromium.org> > Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> > Cr-Commit-Position: refs/heads/master@{#63041} TBR=yangguo@chromium.org Change-Id: I3cc4bb80081c662b1751234bc16a821c20e744be Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1792166 Commit-Queue: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#63617}
2019-09-09 10:19:34 +00:00
backing_store_.reset();
// Clean up the trap handler
trap_handler::RemoveTrapHandler();
if (!g_test_handler_executed) {
#if V8_OS_LINUX || V8_OS_MACOSX || V8_OS_FREEBSD
// The test handler cleans up the signal handler setup in the test. If the
// test handler was not called, we have to do the cleanup ourselves.
CHECK_EQ(0, sigaction(SIGSEGV, &g_old_segv_action, nullptr));
CHECK_EQ(0, sigaction(SIGFPE, &g_old_fpe_action, nullptr));
CHECK_EQ(0, sigaction(SIGBUS, &g_old_bus_action, nullptr));
#elif V8_OS_WIN
RemoveVectoredExceptionHandler(g_registered_handler);
g_registered_handler = nullptr;
#endif
}
}
void InitRecoveryCode() {
// Create a code snippet where we can jump to to recover from a signal or
// exception. The code snippet only consists of a return statement.
recovery_buffer_ = AllocateAssemblerBuffer(
AssemblerBase::kDefaultBufferSize, GetRandomMmapAddr());
MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
recovery_buffer_->CreateView());
int recovery_offset = __ pc_offset();
__ Pop(scratch);
__ Ret();
CodeDesc desc;
masm.GetCode(nullptr, &desc);
recovery_buffer_->MakeExecutable();
g_recovery_address =
reinterpret_cast<Address>(desc.buffer + recovery_offset);
}
#if V8_OS_LINUX || V8_OS_MACOSX || V8_OS_FREEBSD
static void SignalHandler(int signal, siginfo_t* info, void* context) {
if (g_use_as_first_chance_handler) {
if (v8::TryHandleWebAssemblyTrapPosix(signal, info, context)) {
return;
}
}
// Reset the signal handler, to avoid that this signal handler is called
// repeatedly.
sigaction(SIGSEGV, &g_old_segv_action, nullptr);
sigaction(SIGFPE, &g_old_fpe_action, nullptr);
sigaction(SIGBUS, &g_old_bus_action, nullptr);
g_test_handler_executed = true;
// Set the $rip to the recovery code.
ucontext_t* uc = reinterpret_cast<ucontext_t*>(context);
#if V8_OS_LINUX
uc->uc_mcontext.gregs[REG_RIP] = g_recovery_address;
#elif V8_OS_MACOSX
uc->uc_mcontext->__ss.__rip = g_recovery_address;
#elif V8_OS_FREEBSD
uc->uc_mcontext.mc_rip = g_recovery_address;
#else
#error Unsupported platform
#endif
}
#endif
#if V8_OS_WIN
static LONG WINAPI TestHandler(EXCEPTION_POINTERS* exception) {
if (g_use_as_first_chance_handler) {
if (v8::TryHandleWebAssemblyTrapWindows(exception)) {
return EXCEPTION_CONTINUE_EXECUTION;
}
}
RemoveVectoredExceptionHandler(g_registered_handler);
g_registered_handler = nullptr;
g_test_handler_executed = true;
exception->ContextRecord->Rip = g_recovery_address;
return EXCEPTION_CONTINUE_EXECUTION;
}
#endif
Revert "[wasm] Disallow late enabling of trap handlers" This reverts commit bcb0a7c5c5e13bb895391c63ec30d048f6f58dd1. Reason for revert: TSAN failure (https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20TSAN/33868) Original change's description: > [wasm] Disallow late enabling of trap handlers > > It's dangerous if trap handlers are enabled after we already used the > information whether they are enabled or not. > This CL checks for such misbehaviour by remembering whether > {IsTrapHandlerEnabled} was already called, and disallowing > {EnableTrapHandler} afterwards. Also, calling {EnableTrapHandler} > multiple times is disallowed now. > > The trap handler tests are changed to only enable trap handlers once, > and to do that before allocating wasm memory or generating code. > > R=​ahaas@chromium.org > > Bug: v8:11017 > Change-Id: Ib2256bb8435efd914c12769cedd4a0051052aeef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2494935 > Reviewed-by: Andreas Haas <ahaas@chromium.org> > Commit-Queue: Clemens Backes <clemensb@chromium.org> > Cr-Commit-Position: refs/heads/master@{#70750} TBR=ahaas@chromium.org,clemensb@chromium.org Change-Id: I1d93dcb399e2a0b5b0543aa60d34087317c01cb3 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: v8:11017 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2497176 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#70751}
2020-10-26 10:21:23 +00:00
public:
void SetupTrapHandler(TrapHandlerStyle style) {
bool use_default_handler = style == kDefault;
g_use_as_first_chance_handler = !use_default_handler;
CHECK(v8::V8::EnableWebAssemblyTrapHandler(use_default_handler));
}
void GenerateSetThreadInWasmFlagCode(MacroAssembler* masm) {
masm->Move(scratch,
i_isolate()->thread_local_top()->thread_in_wasm_flag_address_,
RelocInfo::NONE);
masm->movl(MemOperand(scratch, 0), Immediate(1));
}
void GenerateResetThreadInWasmFlagCode(MacroAssembler* masm) {
masm->Move(scratch,
i_isolate()->thread_local_top()->thread_in_wasm_flag_address_,
RelocInfo::NONE);
masm->movl(MemOperand(scratch, 0), Immediate(0));
}
bool GetThreadInWasmFlag() {
return *reinterpret_cast<int*>(
trap_handler::GetThreadInWasmThreadLocalAddress());
}
// Execute the code in buffer.
void ExecuteBuffer() {
buffer_->MakeExecutable();
GeneratedCode<void>::FromAddress(
i_isolate(), reinterpret_cast<Address>(buffer_->start()))
.Call();
CHECK(!g_test_handler_executed);
}
// Execute the code in buffer. We expect a crash which we recover from in the
// test handler.
void ExecuteExpectCrash(TestingAssemblerBuffer* buffer,
bool check_wasm_flag = true) {
CHECK(!g_test_handler_executed);
buffer->MakeExecutable();
GeneratedCode<void>::FromAddress(i_isolate(),
reinterpret_cast<Address>(buffer->start()))
.Call();
CHECK(g_test_handler_executed);
g_test_handler_executed = false;
if (check_wasm_flag) CHECK(!GetThreadInWasmFlag());
}
bool test_handler_executed() { return g_test_handler_executed; }
Reland x6 [arraybuffer] Rearchitect backing store ownership This reverts commit 9da3483136b5e71e830ed9a9c34802ad8d605e58 Original change's description: > "Reland x4 [arraybuffer] Rearchitect backing store ownership" > > This is a reland of bc33f5aeba9ceb13f8bfc401c5ba2521c2207ffb > > Contributed by titzer@chromium.org > > Original change's description: > > [arraybuffer] Rearchitect backing store ownership > > > > This CL completely rearchitects the ownership of array buffer backing stores, > > consolidating ownership into a {BackingStore} C++ object that is tracked > > throughout V8 using unique_ptr and shared_ptr where appropriate. > > > > Overall, lifetime management is simpler and more explicit. The numerous > > ways that array buffers were initialized have been streamlined to one > > Attach() method on JSArrayBuffer. The array buffer tracker in the > > GC implementation now manages std::shared_ptr<BackingStore> pointers, > > and the construction and destruction of the BackingStore object itself > > handles the underlying page or embedder-allocated memory. > > > > The embedder API remains unchanged for now. We use the > > v8::ArrayBuffer::Contents struct to hide an additional shared_ptr to > > keep the backing store alive properly, even in the case of aliases > > from live heap objects. Thus the embedder has a lower chance of making > > a mistake. Long-term, we should move the embedder to a model where they > > manage backing stores using shared_ptr to an opaque backing store object. > > TBR=yangguo@chromium.org > > BUG=v8:9380,v8:9221,chromium:986318 > > Change-Id: If671a4a9ca0476e8f084efae46e0d2bf99ed99ef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1731005 > Commit-Queue: Ulan Degenbaev <ulan@chromium.org> > Reviewed-by: Clemens Hammacher <clemensh@chromium.org> > Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> > Cr-Commit-Position: refs/heads/master@{#63041} TBR=yangguo@chromium.org Change-Id: I3cc4bb80081c662b1751234bc16a821c20e744be Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1792166 Commit-Queue: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#63617}
2019-09-09 10:19:34 +00:00
// The backing store used for testing the trap handler.
std::unique_ptr<BackingStore> backing_store_;
// Address within the guard region of the wasm memory. Accessing this memory
// address causes a signal or exception.
Address crash_address_;
// Buffer for generated code.
std::unique_ptr<TestingAssemblerBuffer> buffer_;
// Buffer for the code for the landing pad of the test handler.
std::unique_ptr<TestingAssemblerBuffer> recovery_buffer_;
};
// TODO(almuthanna): These tests were skipped because they cause a crash when
// they are ran on Fuchsia. This issue should be solved later on
// Ticket: https://crbug.com/1028617
#if !defined(V8_TARGET_OS_FUCHSIA)
TEST_P(TrapHandlerTest, TestTrapHandlerRecovery) {
// Test that the wasm trap handler can recover a memory access violation in
// wasm code (we fake the wasm code and the access violation).
MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
buffer_->CreateView());
__ Push(scratch);
GenerateSetThreadInWasmFlagCode(&masm);
__ Move(scratch, crash_address_, RelocInfo::NONE);
int crash_offset = __ pc_offset();
__ testl(MemOperand(scratch, 0), Immediate(1));
int recovery_offset = __ pc_offset();
GenerateResetThreadInWasmFlagCode(&masm);
__ Pop(scratch);
__ Ret();
CodeDesc desc;
masm.GetCode(nullptr, &desc);
Revert "[wasm] Disallow late enabling of trap handlers" This reverts commit bcb0a7c5c5e13bb895391c63ec30d048f6f58dd1. Reason for revert: TSAN failure (https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20TSAN/33868) Original change's description: > [wasm] Disallow late enabling of trap handlers > > It's dangerous if trap handlers are enabled after we already used the > information whether they are enabled or not. > This CL checks for such misbehaviour by remembering whether > {IsTrapHandlerEnabled} was already called, and disallowing > {EnableTrapHandler} afterwards. Also, calling {EnableTrapHandler} > multiple times is disallowed now. > > The trap handler tests are changed to only enable trap handlers once, > and to do that before allocating wasm memory or generating code. > > R=​ahaas@chromium.org > > Bug: v8:11017 > Change-Id: Ib2256bb8435efd914c12769cedd4a0051052aeef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2494935 > Reviewed-by: Andreas Haas <ahaas@chromium.org> > Commit-Queue: Clemens Backes <clemensb@chromium.org> > Cr-Commit-Position: refs/heads/master@{#70750} TBR=ahaas@chromium.org,clemensb@chromium.org Change-Id: I1d93dcb399e2a0b5b0543aa60d34087317c01cb3 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: v8:11017 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2497176 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#70751}
2020-10-26 10:21:23 +00:00
SetupTrapHandler(GetParam());
trap_handler::ProtectedInstructionData protected_instruction{crash_offset,
recovery_offset};
trap_handler::RegisterHandlerData(reinterpret_cast<Address>(desc.buffer),
desc.instr_size, 1, &protected_instruction);
ExecuteBuffer();
}
TEST_P(TrapHandlerTest, TestReleaseHandlerData) {
// Test that after we release handler data in the trap handler, it cannot
// recover from the specific memory access violation anymore.
MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
buffer_->CreateView());
__ Push(scratch);
GenerateSetThreadInWasmFlagCode(&masm);
__ Move(scratch, crash_address_, RelocInfo::NONE);
int crash_offset = __ pc_offset();
__ testl(MemOperand(scratch, 0), Immediate(1));
int recovery_offset = __ pc_offset();
GenerateResetThreadInWasmFlagCode(&masm);
__ Pop(scratch);
__ Ret();
CodeDesc desc;
masm.GetCode(nullptr, &desc);
trap_handler::ProtectedInstructionData protected_instruction{crash_offset,
recovery_offset};
int handler_id = trap_handler::RegisterHandlerData(
reinterpret_cast<Address>(desc.buffer), desc.instr_size, 1,
&protected_instruction);
Revert "[wasm] Disallow late enabling of trap handlers" This reverts commit bcb0a7c5c5e13bb895391c63ec30d048f6f58dd1. Reason for revert: TSAN failure (https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20TSAN/33868) Original change's description: > [wasm] Disallow late enabling of trap handlers > > It's dangerous if trap handlers are enabled after we already used the > information whether they are enabled or not. > This CL checks for such misbehaviour by remembering whether > {IsTrapHandlerEnabled} was already called, and disallowing > {EnableTrapHandler} afterwards. Also, calling {EnableTrapHandler} > multiple times is disallowed now. > > The trap handler tests are changed to only enable trap handlers once, > and to do that before allocating wasm memory or generating code. > > R=​ahaas@chromium.org > > Bug: v8:11017 > Change-Id: Ib2256bb8435efd914c12769cedd4a0051052aeef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2494935 > Reviewed-by: Andreas Haas <ahaas@chromium.org> > Commit-Queue: Clemens Backes <clemensb@chromium.org> > Cr-Commit-Position: refs/heads/master@{#70750} TBR=ahaas@chromium.org,clemensb@chromium.org Change-Id: I1d93dcb399e2a0b5b0543aa60d34087317c01cb3 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: v8:11017 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2497176 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#70751}
2020-10-26 10:21:23 +00:00
SetupTrapHandler(GetParam());
ExecuteBuffer();
// Deregister from the trap handler. The trap handler should not do the
// recovery now.
trap_handler::ReleaseHandlerData(handler_id);
ExecuteExpectCrash(buffer_.get());
}
TEST_P(TrapHandlerTest, TestNoThreadInWasmFlag) {
// That that if the thread_in_wasm flag is not set, the trap handler does not
// get active.
MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
buffer_->CreateView());
__ Push(scratch);
__ Move(scratch, crash_address_, RelocInfo::NONE);
int crash_offset = __ pc_offset();
__ testl(MemOperand(scratch, 0), Immediate(1));
int recovery_offset = __ pc_offset();
__ Pop(scratch);
__ Ret();
CodeDesc desc;
masm.GetCode(nullptr, &desc);
trap_handler::ProtectedInstructionData protected_instruction{crash_offset,
recovery_offset};
trap_handler::RegisterHandlerData(reinterpret_cast<Address>(desc.buffer),
desc.instr_size, 1, &protected_instruction);
Revert "[wasm] Disallow late enabling of trap handlers" This reverts commit bcb0a7c5c5e13bb895391c63ec30d048f6f58dd1. Reason for revert: TSAN failure (https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20TSAN/33868) Original change's description: > [wasm] Disallow late enabling of trap handlers > > It's dangerous if trap handlers are enabled after we already used the > information whether they are enabled or not. > This CL checks for such misbehaviour by remembering whether > {IsTrapHandlerEnabled} was already called, and disallowing > {EnableTrapHandler} afterwards. Also, calling {EnableTrapHandler} > multiple times is disallowed now. > > The trap handler tests are changed to only enable trap handlers once, > and to do that before allocating wasm memory or generating code. > > R=​ahaas@chromium.org > > Bug: v8:11017 > Change-Id: Ib2256bb8435efd914c12769cedd4a0051052aeef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2494935 > Reviewed-by: Andreas Haas <ahaas@chromium.org> > Commit-Queue: Clemens Backes <clemensb@chromium.org> > Cr-Commit-Position: refs/heads/master@{#70750} TBR=ahaas@chromium.org,clemensb@chromium.org Change-Id: I1d93dcb399e2a0b5b0543aa60d34087317c01cb3 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: v8:11017 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2497176 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#70751}
2020-10-26 10:21:23 +00:00
SetupTrapHandler(GetParam());
ExecuteExpectCrash(buffer_.get());
}
TEST_P(TrapHandlerTest, TestCrashInWasmNoProtectedInstruction) {
// Test that if the crash in wasm happened at an instruction which is not
// protected, then the trap handler does not handle it.
MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
buffer_->CreateView());
__ Push(scratch);
GenerateSetThreadInWasmFlagCode(&masm);
int no_crash_offset = __ pc_offset();
__ Move(scratch, crash_address_, RelocInfo::NONE);
__ testl(MemOperand(scratch, 0), Immediate(1));
// Offset where the crash is not happening.
int recovery_offset = __ pc_offset();
GenerateResetThreadInWasmFlagCode(&masm);
__ Pop(scratch);
__ Ret();
CodeDesc desc;
masm.GetCode(nullptr, &desc);
trap_handler::ProtectedInstructionData protected_instruction{no_crash_offset,
recovery_offset};
trap_handler::RegisterHandlerData(reinterpret_cast<Address>(desc.buffer),
desc.instr_size, 1, &protected_instruction);
Revert "[wasm] Disallow late enabling of trap handlers" This reverts commit bcb0a7c5c5e13bb895391c63ec30d048f6f58dd1. Reason for revert: TSAN failure (https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20TSAN/33868) Original change's description: > [wasm] Disallow late enabling of trap handlers > > It's dangerous if trap handlers are enabled after we already used the > information whether they are enabled or not. > This CL checks for such misbehaviour by remembering whether > {IsTrapHandlerEnabled} was already called, and disallowing > {EnableTrapHandler} afterwards. Also, calling {EnableTrapHandler} > multiple times is disallowed now. > > The trap handler tests are changed to only enable trap handlers once, > and to do that before allocating wasm memory or generating code. > > R=​ahaas@chromium.org > > Bug: v8:11017 > Change-Id: Ib2256bb8435efd914c12769cedd4a0051052aeef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2494935 > Reviewed-by: Andreas Haas <ahaas@chromium.org> > Commit-Queue: Clemens Backes <clemensb@chromium.org> > Cr-Commit-Position: refs/heads/master@{#70750} TBR=ahaas@chromium.org,clemensb@chromium.org Change-Id: I1d93dcb399e2a0b5b0543aa60d34087317c01cb3 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: v8:11017 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2497176 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#70751}
2020-10-26 10:21:23 +00:00
SetupTrapHandler(GetParam());
ExecuteExpectCrash(buffer_.get());
}
TEST_P(TrapHandlerTest, TestCrashInWasmWrongCrashType) {
// Test that if the crash reason is not a memory access violation, then the
// wasm trap handler does not handle it.
MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
buffer_->CreateView());
__ Push(scratch);
GenerateSetThreadInWasmFlagCode(&masm);
__ xorq(scratch, scratch);
int crash_offset = __ pc_offset();
__ divq(scratch);
// Offset where the crash is not happening.
int recovery_offset = __ pc_offset();
GenerateResetThreadInWasmFlagCode(&masm);
__ Pop(scratch);
__ Ret();
CodeDesc desc;
masm.GetCode(nullptr, &desc);
trap_handler::ProtectedInstructionData protected_instruction{crash_offset,
recovery_offset};
trap_handler::RegisterHandlerData(reinterpret_cast<Address>(desc.buffer),
desc.instr_size, 1, &protected_instruction);
Revert "[wasm] Disallow late enabling of trap handlers" This reverts commit bcb0a7c5c5e13bb895391c63ec30d048f6f58dd1. Reason for revert: TSAN failure (https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20TSAN/33868) Original change's description: > [wasm] Disallow late enabling of trap handlers > > It's dangerous if trap handlers are enabled after we already used the > information whether they are enabled or not. > This CL checks for such misbehaviour by remembering whether > {IsTrapHandlerEnabled} was already called, and disallowing > {EnableTrapHandler} afterwards. Also, calling {EnableTrapHandler} > multiple times is disallowed now. > > The trap handler tests are changed to only enable trap handlers once, > and to do that before allocating wasm memory or generating code. > > R=​ahaas@chromium.org > > Bug: v8:11017 > Change-Id: Ib2256bb8435efd914c12769cedd4a0051052aeef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2494935 > Reviewed-by: Andreas Haas <ahaas@chromium.org> > Commit-Queue: Clemens Backes <clemensb@chromium.org> > Cr-Commit-Position: refs/heads/master@{#70750} TBR=ahaas@chromium.org,clemensb@chromium.org Change-Id: I1d93dcb399e2a0b5b0543aa60d34087317c01cb3 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: v8:11017 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2497176 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#70751}
2020-10-26 10:21:23 +00:00
SetupTrapHandler(GetParam());
#if V8_OS_POSIX
// On Posix, the V8 default trap handler does not register for SIGFPE,
// therefore the thread-in-wasm flag is never reset in this test. We
// therefore do not check the value of this flag.
bool check_wasm_flag = GetParam() != kDefault;
#elif V8_OS_WIN
// On Windows, the trap handler returns immediately if not an exception of
// interest.
bool check_wasm_flag = false;
#else
bool check_wasm_flag = true;
#endif
ExecuteExpectCrash(buffer_.get(), check_wasm_flag);
if (!check_wasm_flag) {
// Reset the thread-in-wasm flag because it was probably not reset in the
// trap handler.
*trap_handler::GetThreadInWasmThreadLocalAddress() = 0;
}
}
#endif
class CodeRunner : public v8::base::Thread {
public:
CodeRunner(TrapHandlerTest* test, TestingAssemblerBuffer* buffer)
: Thread(Options("CodeRunner")), test_(test), buffer_(buffer) {}
void Run() override { test_->ExecuteExpectCrash(buffer_); }
private:
TrapHandlerTest* test_;
TestingAssemblerBuffer* buffer_;
};
// TODO(almuthanna): This test was skipped because it causes a crash when it is
// ran on Fuchsia. This issue should be solved later on
// Ticket: https://crbug.com/1028617
#if !defined(V8_TARGET_OS_FUCHSIA)
TEST_P(TrapHandlerTest, TestCrashInOtherThread) {
// Test setup:
// The current thread enters wasm land (sets the thread_in_wasm flag)
// A second thread crashes at a protected instruction without having the flag
// set.
MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
buffer_->CreateView());
__ Push(scratch);
__ Move(scratch, crash_address_, RelocInfo::NONE);
int crash_offset = __ pc_offset();
__ testl(MemOperand(scratch, 0), Immediate(1));
int recovery_offset = __ pc_offset();
__ Pop(scratch);
__ Ret();
CodeDesc desc;
masm.GetCode(nullptr, &desc);
trap_handler::ProtectedInstructionData protected_instruction{crash_offset,
recovery_offset};
trap_handler::RegisterHandlerData(reinterpret_cast<Address>(desc.buffer),
desc.instr_size, 1, &protected_instruction);
Revert "[wasm] Disallow late enabling of trap handlers" This reverts commit bcb0a7c5c5e13bb895391c63ec30d048f6f58dd1. Reason for revert: TSAN failure (https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20TSAN/33868) Original change's description: > [wasm] Disallow late enabling of trap handlers > > It's dangerous if trap handlers are enabled after we already used the > information whether they are enabled or not. > This CL checks for such misbehaviour by remembering whether > {IsTrapHandlerEnabled} was already called, and disallowing > {EnableTrapHandler} afterwards. Also, calling {EnableTrapHandler} > multiple times is disallowed now. > > The trap handler tests are changed to only enable trap handlers once, > and to do that before allocating wasm memory or generating code. > > R=​ahaas@chromium.org > > Bug: v8:11017 > Change-Id: Ib2256bb8435efd914c12769cedd4a0051052aeef > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2494935 > Reviewed-by: Andreas Haas <ahaas@chromium.org> > Commit-Queue: Clemens Backes <clemensb@chromium.org> > Cr-Commit-Position: refs/heads/master@{#70750} TBR=ahaas@chromium.org,clemensb@chromium.org Change-Id: I1d93dcb399e2a0b5b0543aa60d34087317c01cb3 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: v8:11017 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2497176 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#70751}
2020-10-26 10:21:23 +00:00
SetupTrapHandler(GetParam());
CodeRunner runner(this, buffer_.get());
CHECK(!GetThreadInWasmFlag());
// Set the thread-in-wasm flag manually in this thread.
*trap_handler::GetThreadInWasmThreadLocalAddress() = 1;
CHECK(runner.Start());
runner.Join();
CHECK(GetThreadInWasmFlag());
// Reset the thread-in-wasm flag.
*trap_handler::GetThreadInWasmThreadLocalAddress() = 0;
}
#endif
INSTANTIATE_TEST_SUITE_P(Traps, TrapHandlerTest,
::testing::Values(kDefault, kCallback),
PrintTrapHandlerTestParam);
#undef __
} // namespace wasm
} // namespace internal
} // namespace v8