trap-handler.h 4.57 KB
Newer Older
1 2 3 4
// Copyright 2016 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.

5 6
#ifndef V8_TRAP_HANDLER_TRAP_HANDLER_H_
#define V8_TRAP_HANDLER_TRAP_HANDLER_H_
7

eholk's avatar
eholk committed
8 9 10
#include <stdint.h>
#include <stdlib.h>

11 12
#include <atomic>

eholk's avatar
eholk committed
13
#include "src/base/build_config.h"
14 15
#include "src/common/globals.h"
#include "src/flags/flags.h"
eholk's avatar
eholk committed
16

17 18 19 20
namespace v8 {
namespace internal {
namespace trap_handler {

eholk's avatar
eholk committed
21
// TODO(eholk): Support trap handlers on other platforms.
Eric Holk's avatar
Eric Holk committed
22
#if V8_TARGET_ARCH_X64 && V8_OS_LINUX && !V8_OS_ANDROID
23
#define V8_TRAP_HANDLER_SUPPORTED true
24 25
#elif V8_TARGET_ARCH_X64 && V8_OS_WIN
#define V8_TRAP_HANDLER_SUPPORTED true
26 27
#elif V8_TARGET_ARCH_X64 && V8_OS_MACOSX
#define V8_TRAP_HANDLER_SUPPORTED true
28 29
#elif V8_TARGET_ARCH_X64 && V8_OS_FREEBSD
#define V8_TRAP_HANDLER_SUPPORTED true
eholk's avatar
eholk committed
30
#else
31
#define V8_TRAP_HANDLER_SUPPORTED false
eholk's avatar
eholk committed
32 33
#endif

34 35
struct ProtectedInstructionData {
  // The offset of this instruction from the start of its code object.
36 37
  // Wasm code never grows larger than 2GB, so uint32_t is sufficient.
  uint32_t instr_offset;
38 39 40 41

  // The offset of the landing pad from the start of its code object.
  //
  // TODO(eholk): Using a single landing pad and store parameters here.
42
  uint32_t landing_offset;
43 44
};

45 46
const int kInvalidIndex = -1;

47
/// Adds the handler data to the place where the trap handler will find it.
eholk's avatar
eholk committed
48 49
///
/// This returns a number that can be used to identify the handler data to
50
/// ReleaseHandlerData, or -1 on failure.
51 52 53
int V8_EXPORT_PRIVATE RegisterHandlerData(
    Address base, size_t size, size_t num_protected_instructions,
    const ProtectedInstructionData* protected_instructions);
eholk's avatar
eholk committed
54 55

/// Removes the data from the master list and frees any memory, if necessary.
56 57
/// TODO(mtrofin): We can switch to using size_t for index and not need
/// kInvalidIndex.
58
void V8_EXPORT_PRIVATE ReleaseHandlerData(int index);
eholk's avatar
eholk committed
59 60 61 62 63 64 65 66 67 68

#if V8_OS_WIN
#define THREAD_LOCAL __declspec(thread)
#elif V8_OS_ANDROID
// TODO(eholk): fix this before enabling for trap handlers for Android.
#define THREAD_LOCAL
#else
#define THREAD_LOCAL __thread
#endif

69 70
// Initially false, set to true if when trap handlers are enabled. Never goes
// back to false then.
71
extern bool g_is_trap_handler_enabled;
72 73 74 75 76 77 78 79

// Initially true, set to false when either {IsTrapHandlerEnabled} or
// {EnableTrapHandler} is called to prevent calling {EnableTrapHandler}
// repeatedly, or after {IsTrapHandlerEnabled}. Needs to be atomic because
// {IsTrapHandlerEnabled} can be called from any thread. Updated using relaxed
// semantics, since it's not used for synchronization.
extern std::atomic<bool> g_can_enable_trap_handler;

80 81
// Enables trap handling for WebAssembly bounds checks.
//
82
// use_v8_handler indicates that V8 should install its own handler
83
// rather than relying on the embedder to do it.
84
V8_EXPORT_PRIVATE bool EnableTrapHandler(bool use_v8_handler);
85

86
inline bool IsTrapHandlerEnabled() {
87
  DCHECK_IMPLIES(g_is_trap_handler_enabled, V8_TRAP_HANDLER_SUPPORTED);
88 89 90 91 92 93 94
  // Disallow enabling the trap handler after retrieving the current value.
  // Re-enabling them late can produce issues because code or objects might have
  // been generated under the assumption that trap handlers are disabled.
  // Note: We test before setting to avoid contention by an unconditional write.
  if (g_can_enable_trap_handler.load(std::memory_order_relaxed)) {
    g_can_enable_trap_handler.store(false, std::memory_order_relaxed);
  }
95
  return g_is_trap_handler_enabled;
eholk's avatar
eholk committed
96 97
}

98
extern THREAD_LOCAL int g_thread_in_wasm_code;
eholk's avatar
eholk committed
99

100 101 102
// Return the address of the thread-local {g_thread_in_wasm_code} variable. This
// pointer can be accessed and modified as long as the thread calling this
// function exists. Only use if from the same thread do avoid race conditions.
103
V8_NOINLINE V8_EXPORT_PRIVATE int* GetThreadInWasmThreadLocalAddress();
104

105 106 107 108
// On Windows, asan installs its own exception handler which maps shadow
// memory. Since our exception handler may be executed before the asan exception
// handler, we have to make sure that asan shadow memory is not accessed here.
DISABLE_ASAN inline bool IsThreadInWasm() { return g_thread_in_wasm_code; }
eholk's avatar
eholk committed
109 110

inline void SetThreadInWasm() {
111
  if (IsTrapHandlerEnabled()) {
eholk's avatar
eholk committed
112 113 114 115
    DCHECK(!IsThreadInWasm());
    g_thread_in_wasm_code = true;
  }
}
116

eholk's avatar
eholk committed
117
inline void ClearThreadInWasm() {
118
  if (IsTrapHandlerEnabled()) {
eholk's avatar
eholk committed
119 120 121 122 123
    DCHECK(IsThreadInWasm());
    g_thread_in_wasm_code = false;
  }
}

124
bool RegisterDefaultTrapHandler();
125
V8_EXPORT_PRIVATE void RemoveTrapHandler();
eholk's avatar
eholk committed
126

127 128
size_t GetRecoveredTrapCount();

129 130 131 132
}  // namespace trap_handler
}  // namespace internal
}  // namespace v8

133
#endif  // V8_TRAP_HANDLER_TRAP_HANDLER_H_