1// Copyright 2016 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef V8_TRAP_HANDLER_TRAP_HANDLER_H_ 6#define V8_TRAP_HANDLER_TRAP_HANDLER_H_ 7 8#include <stdint.h> 9#include <stdlib.h> 10 11#include <atomic> 12 13#include "include/v8config.h" 14#include "src/base/immediate-crash.h" 15 16namespace v8 { 17namespace internal { 18namespace trap_handler { 19 20// X64 on Linux, Windows, MacOS, FreeBSD. 21#if V8_HOST_ARCH_X64 && V8_TARGET_ARCH_X64 && \ 22 ((V8_OS_LINUX && !V8_OS_ANDROID) || V8_OS_WIN || V8_OS_DARWIN || \ 23 V8_OS_FREEBSD) 24#define V8_TRAP_HANDLER_SUPPORTED true 25// Arm64 (non-simulator) on Mac. 26#elif V8_TARGET_ARCH_ARM64 && V8_HOST_ARCH_ARM64 && V8_OS_DARWIN 27#define V8_TRAP_HANDLER_SUPPORTED true 28// Arm64 simulator on x64 on Linux, Mac, or Windows. 29#elif V8_TARGET_ARCH_ARM64 && V8_HOST_ARCH_X64 && \ 30 (V8_OS_LINUX || V8_OS_DARWIN) 31#define V8_TRAP_HANDLER_VIA_SIMULATOR 32#define V8_TRAP_HANDLER_SUPPORTED true 33// Everything else is unsupported. 34#else 35#define V8_TRAP_HANDLER_SUPPORTED false 36#endif 37 38// Setup for shared library export. 39#if defined(BUILDING_V8_SHARED) && defined(V8_OS_WIN) 40#define TH_EXPORT_PRIVATE __declspec(dllexport) 41#elif defined(BUILDING_V8_SHARED) 42#define TH_EXPORT_PRIVATE __attribute__((visibility("default"))) 43#elif defined(USING_V8_SHARED) && defined(V8_OS_WIN) 44#define TH_EXPORT_PRIVATE __declspec(dllimport) 45#else 46#define TH_EXPORT_PRIVATE 47#endif 48 49#define TH_CHECK(condition) \ 50 if (!(condition)) IMMEDIATE_CRASH(); 51#ifdef DEBUG 52#define TH_DCHECK(condition) TH_CHECK(condition) 53#else 54#define TH_DCHECK(condition) void(0) 55#endif 56 57#if defined(__has_feature) 58#if __has_feature(address_sanitizer) 59#define TH_DISABLE_ASAN __attribute__((no_sanitize_address)) 60#else 61#define TH_DISABLE_ASAN 62#endif 63#else 64#define TH_DISABLE_ASAN 65#endif 66 67struct ProtectedInstructionData { 68 // The offset of this instruction from the start of its code object. 69 // Wasm code never grows larger than 2GB, so uint32_t is sufficient. 70 uint32_t instr_offset; 71 72 // The offset of the landing pad from the start of its code object. 73 // 74 // TODO(eholk): Using a single landing pad and store parameters here. 75 uint32_t landing_offset; 76}; 77 78const int kInvalidIndex = -1; 79 80/// Adds the handler data to the place where the trap handler will find it. 81/// 82/// This returns a number that can be used to identify the handler data to 83/// ReleaseHandlerData, or -1 on failure. 84int TH_EXPORT_PRIVATE RegisterHandlerData( 85 uintptr_t base, size_t size, size_t num_protected_instructions, 86 const ProtectedInstructionData* protected_instructions); 87 88/// Removes the data from the master list and frees any memory, if necessary. 89/// TODO(mtrofin): We can switch to using size_t for index and not need 90/// kInvalidIndex. 91void TH_EXPORT_PRIVATE ReleaseHandlerData(int index); 92 93// Initially false, set to true if when trap handlers are enabled. Never goes 94// back to false then. 95extern bool g_is_trap_handler_enabled; 96 97// Initially true, set to false when either {IsTrapHandlerEnabled} or 98// {EnableTrapHandler} is called to prevent calling {EnableTrapHandler} 99// repeatedly, or after {IsTrapHandlerEnabled}. Needs to be atomic because 100// {IsTrapHandlerEnabled} can be called from any thread. Updated using relaxed 101// semantics, since it's not used for synchronization. 102extern std::atomic<bool> g_can_enable_trap_handler; 103 104// Enables trap handling for WebAssembly bounds checks. 105// 106// use_v8_handler indicates that V8 should install its own handler 107// rather than relying on the embedder to do it. 108TH_EXPORT_PRIVATE bool EnableTrapHandler(bool use_v8_handler); 109 110inline bool IsTrapHandlerEnabled() { 111 TH_DCHECK(!g_is_trap_handler_enabled || V8_TRAP_HANDLER_SUPPORTED); 112 // Disallow enabling the trap handler after retrieving the current value. 113 // Re-enabling them late can produce issues because code or objects might have 114 // been generated under the assumption that trap handlers are disabled. 115 // Note: We test before setting to avoid contention by an unconditional write. 116 if (g_can_enable_trap_handler.load(std::memory_order_relaxed)) { 117 g_can_enable_trap_handler.store(false, std::memory_order_relaxed); 118 } 119 return g_is_trap_handler_enabled; 120} 121 122#if defined(V8_OS_AIX) 123// `thread_local` does not link on AIX: 124// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100641 125extern __thread int g_thread_in_wasm_code; 126#else 127extern thread_local int g_thread_in_wasm_code; 128#endif 129 130// Return the address of the thread-local {g_thread_in_wasm_code} variable. This 131// pointer can be accessed and modified as long as the thread calling this 132// function exists. Only use if from the same thread do avoid race conditions. 133V8_NOINLINE TH_EXPORT_PRIVATE int* GetThreadInWasmThreadLocalAddress(); 134 135// On Windows, asan installs its own exception handler which maps shadow 136// memory. Since our exception handler may be executed before the asan exception 137// handler, we have to make sure that asan shadow memory is not accessed here. 138TH_DISABLE_ASAN inline bool IsThreadInWasm() { return g_thread_in_wasm_code; } 139 140inline void SetThreadInWasm() { 141 if (IsTrapHandlerEnabled()) { 142 TH_DCHECK(!IsThreadInWasm()); 143 g_thread_in_wasm_code = true; 144 } 145} 146 147inline void ClearThreadInWasm() { 148 if (IsTrapHandlerEnabled()) { 149 TH_DCHECK(IsThreadInWasm()); 150 g_thread_in_wasm_code = false; 151 } 152} 153 154bool RegisterDefaultTrapHandler(); 155TH_EXPORT_PRIVATE void RemoveTrapHandler(); 156 157TH_EXPORT_PRIVATE size_t GetRecoveredTrapCount(); 158 159} // namespace trap_handler 160} // namespace internal 161} // namespace v8 162 163#endif // V8_TRAP_HANDLER_TRAP_HANDLER_H_ 164