1 // Copyright 2021 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 #include "src/wasm/code-space-access.h" 6 7 #include "src/wasm/wasm-code-manager.h" 8 #include "src/wasm/wasm-engine.h" 9 10 namespace v8 { 11 namespace internal { 12 namespace wasm { 13 14 thread_local NativeModule* CodeSpaceWriteScope::current_native_module_ = 15 nullptr; 16 17 // TODO(jkummerow): Background threads could permanently stay in 18 // writable mode; only the main thread has to switch back and forth. CodeSpaceWriteScope(NativeModule* native_module)19CodeSpaceWriteScope::CodeSpaceWriteScope(NativeModule* native_module) 20 : previous_native_module_(current_native_module_) { 21 DCHECK_NOT_NULL(native_module); 22 if (previous_native_module_ == native_module) return; 23 current_native_module_ = native_module; 24 if (previous_native_module_ == nullptr || SwitchingPerNativeModule()) { 25 SetWritable(); 26 } 27 } 28 ~CodeSpaceWriteScope()29CodeSpaceWriteScope::~CodeSpaceWriteScope() { 30 if (previous_native_module_ == current_native_module_) return; 31 if (previous_native_module_ == nullptr || SwitchingPerNativeModule()) { 32 SetExecutable(); 33 } 34 current_native_module_ = previous_native_module_; 35 } 36 37 #if V8_HAS_PTHREAD_JIT_WRITE_PROTECT 38 39 // Ignoring this warning is considered better than relying on 40 // __builtin_available. 41 #pragma clang diagnostic push 42 #pragma clang diagnostic ignored "-Wunguarded-availability-new" 43 // static SetWritable()44void CodeSpaceWriteScope::SetWritable() { 45 pthread_jit_write_protect_np(0); 46 } 47 48 // static SetExecutable()49void CodeSpaceWriteScope::SetExecutable() { 50 pthread_jit_write_protect_np(1); 51 } 52 #pragma clang diagnostic pop 53 54 // static SwitchingPerNativeModule()55bool CodeSpaceWriteScope::SwitchingPerNativeModule() { return false; } 56 57 #else // !V8_HAS_PTHREAD_JIT_WRITE_PROTECT 58 59 // static SetWritable()60void CodeSpaceWriteScope::SetWritable() { 61 auto* code_manager = GetWasmCodeManager(); 62 if (code_manager->MemoryProtectionKeysEnabled()) { 63 code_manager->SetThreadWritable(true); 64 } else if (FLAG_wasm_write_protect_code_memory) { 65 current_native_module_->AddWriter(); 66 } 67 } 68 69 // static SetExecutable()70void CodeSpaceWriteScope::SetExecutable() { 71 auto* code_manager = GetWasmCodeManager(); 72 if (code_manager->MemoryProtectionKeysEnabled()) { 73 DCHECK(FLAG_wasm_memory_protection_keys); 74 code_manager->SetThreadWritable(false); 75 } else if (FLAG_wasm_write_protect_code_memory) { 76 current_native_module_->RemoveWriter(); 77 } 78 } 79 80 // static SwitchingPerNativeModule()81bool CodeSpaceWriteScope::SwitchingPerNativeModule() { 82 return !GetWasmCodeManager()->MemoryProtectionKeysEnabled() && 83 FLAG_wasm_write_protect_code_memory; 84 } 85 86 #endif // !V8_HAS_PTHREAD_JIT_WRITE_PROTECT 87 88 } // namespace wasm 89 } // namespace internal 90 } // namespace v8 91