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 <signal.h> 9 #include <stdint.h> 10 #include <stdlib.h> 11 12 #include "src/base/build_config.h" 13 #include "src/flags.h" 14 #include "src/globals.h" 15 16 #if V8_OS_LINUX 17 #include <ucontext.h> 18 #endif 19 20 namespace v8 { 21 namespace internal { 22 namespace trap_handler { 23 24 // TODO(eholk): Support trap handlers on other platforms. 25 #if V8_TARGET_ARCH_X64 && V8_OS_LINUX && !V8_OS_ANDROID 26 #define V8_TRAP_HANDLER_SUPPORTED 1 27 #else 28 #define V8_TRAP_HANDLER_SUPPORTED 0 29 #endif 30 31 struct ProtectedInstructionData { 32 // The offset of this instruction from the start of its code object. 33 // Wasm code never grows larger than 2GB, so uint32_t is sufficient. 34 uint32_t instr_offset; 35 36 // The offset of the landing pad from the start of its code object. 37 // 38 // TODO(eholk): Using a single landing pad and store parameters here. 39 uint32_t landing_offset; 40 }; 41 42 const int kInvalidIndex = -1; 43 44 /// Adds the handler data to the place where the signal handler will find it. 45 /// 46 /// This returns a number that can be used to identify the handler data to 47 /// ReleaseHandlerData, or -1 on failure. 48 int RegisterHandlerData(Address base, size_t size, 49 size_t num_protected_instructions, 50 const ProtectedInstructionData* protected_instructions); 51 52 /// Removes the data from the master list and frees any memory, if necessary. 53 /// TODO(mtrofin): We can switch to using size_t for index and not need 54 /// kInvalidIndex. 55 void ReleaseHandlerData(int index); 56 57 #if V8_OS_WIN 58 #define THREAD_LOCAL __declspec(thread) 59 #elif V8_OS_ANDROID 60 // TODO(eholk): fix this before enabling for trap handlers for Android. 61 #define THREAD_LOCAL 62 #else 63 #define THREAD_LOCAL __thread 64 #endif 65 66 extern bool g_is_trap_handler_enabled; 67 // Enables trap handling for WebAssembly bounds checks. 68 // 69 // use_v8_signal_handler indicates that V8 should install its own signal handler 70 // rather than relying on the embedder to do it. 71 bool EnableTrapHandler(bool use_v8_signal_handler); 72 IsTrapHandlerEnabled()73inline bool IsTrapHandlerEnabled() { 74 DCHECK_IMPLIES(g_is_trap_handler_enabled, V8_TRAP_HANDLER_SUPPORTED); 75 return g_is_trap_handler_enabled; 76 } 77 78 extern THREAD_LOCAL int g_thread_in_wasm_code; 79 80 // Return the address of the thread-local {g_thread_in_wasm_code} variable. This 81 // pointer can be accessed and modified as long as the thread calling this 82 // function exists. Only use if from the same thread do avoid race conditions. GetThreadInWasmThreadLocalAddress()83inline int* GetThreadInWasmThreadLocalAddress() { 84 return &g_thread_in_wasm_code; 85 } 86 IsThreadInWasm()87inline bool IsThreadInWasm() { return g_thread_in_wasm_code; } 88 SetThreadInWasm()89inline void SetThreadInWasm() { 90 if (IsTrapHandlerEnabled()) { 91 DCHECK(!IsThreadInWasm()); 92 g_thread_in_wasm_code = true; 93 } 94 } 95 ClearThreadInWasm()96inline void ClearThreadInWasm() { 97 if (IsTrapHandlerEnabled()) { 98 DCHECK(IsThreadInWasm()); 99 g_thread_in_wasm_code = false; 100 } 101 } 102 103 class ThreadInWasmScope { 104 public: ThreadInWasmScope()105 ThreadInWasmScope() { SetThreadInWasm(); } ~ThreadInWasmScope()106 ~ThreadInWasmScope() { ClearThreadInWasm(); } 107 }; 108 109 bool RegisterDefaultTrapHandler(); 110 V8_EXPORT_PRIVATE void RestoreOriginalSignalHandler(); 111 112 #if V8_OS_LINUX 113 bool TryHandleSignal(int signum, siginfo_t* info, ucontext_t* context); 114 #endif // V8_OS_LINUX 115 116 size_t GetRecoveredTrapCount(); 117 118 } // namespace trap_handler 119 } // namespace internal 120 } // namespace v8 121 122 #endif // V8_TRAP_HANDLER_TRAP_HANDLER_H_ 123