[traphandler] Add arm64 simulator support on Windows
This ports the trap handler implementation for the arm64 simulator from POSIX to Windows. Apart from different registers being used for passing parameters, and different access to these register values in the signal handler, the implementation is exactly the same. The new logic is being used for sanitizer builds which automatically target arm64 via the simulator, or if manually compiling an arm64 simulator build on x64. I manually tested the latter. Also, the existing unit test is enabled for Mac (which was missing) and Windows now. R=ahaas@chromium.org, mseaborn@chromium.org Bug: v8:11955 Cq-Include-Trybots: luci.v8.try:v8_win64_asan_rel_ng Cq-Include-Trybots: luci.v8.try:v8_mac64_asan_rel_ng Change-Id: Ia62405b28808a3cc9f199e3f43a45ffc4bda491b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3163256 Commit-Queue: Clemens Backes <clemensb@chromium.org> Reviewed-by: Andreas Haas <ahaas@chromium.org> Cr-Commit-Position: refs/heads/main@{#76902}
This commit is contained in:
parent
62133215bc
commit
367f86de7e
15
BUILD.gn
15
BUILD.gn
@ -3487,7 +3487,8 @@ v8_header_set("v8_internal_headers") {
|
||||
(current_cpu == "x64" && (is_linux || is_chromeos || is_mac))) {
|
||||
sources += [ "src/trap-handler/handler-inside-posix.h" ]
|
||||
}
|
||||
if (current_cpu == "x64" && (is_linux || is_chromeos || is_mac)) {
|
||||
if (current_cpu == "x64" &&
|
||||
(is_linux || is_chromeos || is_mac || is_win)) {
|
||||
sources += [ "src/trap-handler/trap-handler-simulator.h" ]
|
||||
}
|
||||
}
|
||||
@ -4411,16 +4412,22 @@ v8_source_set("v8_base_without_compiler") {
|
||||
"src/regexp/arm64/regexp-macro-assembler-arm64.cc",
|
||||
]
|
||||
if (v8_enable_webassembly) {
|
||||
# Trap handling is enabled on arm64 Mac and in simulators on x64 on Linux
|
||||
# and Mac.
|
||||
# Trap handling is enabled on arm64 Mac and in simulators on x64 on Linux,
|
||||
# Mac, and Windows.
|
||||
if ((current_cpu == "arm64" && is_mac) ||
|
||||
(current_cpu == "x64" && (is_linux || is_chromeos || is_mac))) {
|
||||
sources += [
|
||||
"src/trap-handler/handler-inside-posix.cc",
|
||||
"src/trap-handler/handler-outside-posix.cc",
|
||||
]
|
||||
} else if (current_cpu == "x64" && is_win) {
|
||||
sources += [
|
||||
"src/trap-handler/handler-inside-win.cc",
|
||||
"src/trap-handler/handler-outside-win.cc",
|
||||
]
|
||||
}
|
||||
if (current_cpu == "x64" && (is_linux || is_chromeos || is_mac)) {
|
||||
if (current_cpu == "x64" &&
|
||||
(is_linux || is_chromeos || is_mac || is_win)) {
|
||||
sources += [ "src/trap-handler/handler-outside-simulator.cc" ]
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ class UnmaskOobSignalScope {
|
||||
|
||||
#ifdef V8_TRAP_HANDLER_VIA_SIMULATOR
|
||||
// This is the address where we continue on a failed "ProbeMemory". It's defined
|
||||
// in "handler-outside-simulators.cc".
|
||||
// in "handler-outside-simulator.cc".
|
||||
extern "C" char v8_probe_memory_continuation[];
|
||||
#endif // V8_TRAP_HANDLER_VIA_SIMULATOR
|
||||
|
||||
|
@ -30,6 +30,10 @@
|
||||
#include "src/trap-handler/trap-handler-internal.h"
|
||||
#include "src/trap-handler/trap-handler.h"
|
||||
|
||||
#ifdef V8_TRAP_HANDLER_VIA_SIMULATOR
|
||||
#include "src/trap-handler/trap-handler-simulator.h"
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace trap_handler {
|
||||
@ -49,6 +53,12 @@ struct TEB {
|
||||
PVOID thread_local_storage_pointer;
|
||||
};
|
||||
|
||||
#ifdef V8_TRAP_HANDLER_VIA_SIMULATOR
|
||||
// This is the address where we continue on a failed "ProbeMemory". It's defined
|
||||
// in "handler-outside-simulator.cc".
|
||||
extern "C" char v8_probe_memory_continuation[];
|
||||
#endif // V8_TRAP_HANDLER_VIA_SIMULATOR
|
||||
|
||||
bool TryHandleWasmTrap(EXCEPTION_POINTERS* exception) {
|
||||
// VectoredExceptionHandlers need extreme caution. Do as little as possible
|
||||
// to determine if the exception should be handled or not. Exceptions can be
|
||||
@ -71,17 +81,16 @@ bool TryHandleWasmTrap(EXCEPTION_POINTERS* exception) {
|
||||
// need to run to initialize values may not have run yet, but that is not
|
||||
// the case for any thread_locals used here).
|
||||
TEB* pteb = reinterpret_cast<TEB*>(NtCurrentTeb());
|
||||
if (!pteb->thread_local_storage_pointer) {
|
||||
return false;
|
||||
}
|
||||
if (!pteb->thread_local_storage_pointer) return false;
|
||||
|
||||
// Now safe to run more advanced logic, which may access thread_locals
|
||||
// Ensure the faulting thread was actually running Wasm code.
|
||||
if (!IsThreadInWasm()) {
|
||||
return false;
|
||||
}
|
||||
if (!IsThreadInWasm()) return false;
|
||||
|
||||
// Clear g_thread_in_wasm_code, primarily to protect against nested faults.
|
||||
// The only path that resets the flag to true is if we find a landing pad (in
|
||||
// which case this function returns true). Otherwise we leave the flag unset
|
||||
// since we do not return to wasm code.
|
||||
g_thread_in_wasm_code = false;
|
||||
|
||||
const EXCEPTION_RECORD* record = exception->ExceptionRecord;
|
||||
@ -89,17 +98,28 @@ bool TryHandleWasmTrap(EXCEPTION_POINTERS* exception) {
|
||||
uintptr_t fault_addr = reinterpret_cast<uintptr_t>(record->ExceptionAddress);
|
||||
uintptr_t landing_pad = 0;
|
||||
|
||||
if (TryFindLandingPad(fault_addr, &landing_pad)) {
|
||||
#ifdef V8_TRAP_HANDLER_VIA_SIMULATOR
|
||||
// Only handle signals triggered by the load in {ProbeMemory}.
|
||||
if (fault_addr != reinterpret_cast<uintptr_t>(&ProbeMemory)) return false;
|
||||
|
||||
// The simulated ip will be in the second parameter register (%rdx).
|
||||
uintptr_t simulated_ip = exception->ContextRecord->Rdx;
|
||||
if (!TryFindLandingPad(simulated_ip, &landing_pad)) return false;
|
||||
TH_DCHECK(landing_pad != 0);
|
||||
|
||||
exception->ContextRecord->Rax = landing_pad;
|
||||
// Continue at the memory probing continuation.
|
||||
exception->ContextRecord->Rip =
|
||||
reinterpret_cast<uintptr_t>(&v8_probe_memory_continuation);
|
||||
#else
|
||||
if (!TryFindLandingPad(fault_addr, &landing_pad)) return false;
|
||||
|
||||
// Tell the caller to return to the landing pad.
|
||||
exception->ContextRecord->Rip = landing_pad;
|
||||
#endif
|
||||
// We will return to wasm code, so restore the g_thread_in_wasm_code flag.
|
||||
g_thread_in_wasm_code = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we get here, it's not a recoverable wasm fault, so we go to the next
|
||||
// handler. Leave the g_thread_in_wasm_code flag unset since we do not return
|
||||
// to wasm code.
|
||||
return false;
|
||||
}
|
||||
|
||||
LONG HandleWasmTrap(EXCEPTION_POINTERS* exception) {
|
||||
|
@ -15,10 +15,14 @@
|
||||
asm(
|
||||
".globl " SYMBOL(ProbeMemory) " \n"
|
||||
SYMBOL(ProbeMemory) ": \n"
|
||||
// First parameter (address) passed in %rdi.
|
||||
// The second parameter (pc) is unused here. It is read by the trap handler
|
||||
// instead.
|
||||
// First parameter (address) passed in %rdi on Linux/Mac, and %rcx on Windows.
|
||||
// The second parameter (pc) is unused here. It is read by the trap handler
|
||||
// instead.
|
||||
#if V8_OS_WIN
|
||||
" movb (%rcx), %al \n"
|
||||
#else
|
||||
" movb (%rdi), %al \n"
|
||||
#endif // V8_OS_WIN
|
||||
// Return 0 on success.
|
||||
" xorl %eax, %eax \n"
|
||||
// Place an additional "ret" here instead of falling through to the one
|
||||
|
@ -25,8 +25,9 @@ namespace trap_handler {
|
||||
// Arm64 (non-simulator) on Mac.
|
||||
#elif V8_TARGET_ARCH_ARM64 && V8_HOST_ARCH_ARM64 && V8_OS_MACOSX
|
||||
#define V8_TRAP_HANDLER_SUPPORTED true
|
||||
// Arm64 simulator on x64 on Linux or Mac.
|
||||
#elif V8_TARGET_ARCH_ARM64 && V8_HOST_ARCH_X64 && (V8_OS_LINUX || V8_OS_MACOSX)
|
||||
// Arm64 simulator on x64 on Linux, Mac, or Windows.
|
||||
#elif V8_TARGET_ARCH_ARM64 && V8_HOST_ARCH_X64 && \
|
||||
(V8_OS_LINUX || V8_OS_MACOSX || V8_OS_WIN)
|
||||
#define V8_TRAP_HANDLER_VIA_SIMULATOR
|
||||
#define V8_TRAP_HANDLER_SUPPORTED true
|
||||
// Everything else is unsupported.
|
||||
|
@ -493,19 +493,22 @@ v8_source_set("unittests_sources") {
|
||||
]
|
||||
}
|
||||
|
||||
if (is_posix && v8_enable_webassembly) {
|
||||
if (v8_enable_webassembly) {
|
||||
if (is_posix) {
|
||||
sources += [ "wasm/trap-handler-posix-unittest.cc" ]
|
||||
}
|
||||
|
||||
if (is_win && v8_enable_webassembly) {
|
||||
if (is_win) {
|
||||
sources += [ "wasm/trap-handler-win-unittest.cc" ]
|
||||
}
|
||||
|
||||
# Include this test only on arm64 simulator builds on x64 on Linux.
|
||||
if (current_cpu == "x64" && v8_current_cpu == "arm64" && is_linux &&
|
||||
v8_enable_webassembly) {
|
||||
# Include this test only on arm64 simulator builds on x64 on Linux, Mac and
|
||||
# Windows.
|
||||
if (current_cpu == "x64" && v8_current_cpu == "arm64" &&
|
||||
(is_linux || is_mac || is_win)) {
|
||||
sources += [ "wasm/trap-handler-simulator-unittest.cc" ]
|
||||
}
|
||||
}
|
||||
|
||||
configs = [
|
||||
"../..:cppgc_base_config",
|
||||
|
Loading…
Reference in New Issue
Block a user