blob: ad0800d57149a3f17b18da07dbbe8616770195d8 [file] [edit]
// Copyright 2022 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.
#ifndef V8_COMMON_CODE_MEMORY_ACCESS_H_
#define V8_COMMON_CODE_MEMORY_ACCESS_H_
#include "src/base/build_config.h"
#include "src/base/macros.h"
namespace v8 {
namespace internal {
class CodePageCollectionMemoryModificationScope;
class CodePageMemoryModificationScope;
class CodeSpaceMemoryModificationScope;
class RwxMemoryWriteScopeForTesting;
namespace wasm {
class CodeSpaceWriteScope;
}
// This scope is a wrapper for APRR/MAP_JIT machinery on MacOS on ARM64
// ("Apple M1"/Apple Silicon) with respective semantics.
// See pthread_jit_write_protect_np() for details.
// The scope must not be used if the process does not have the
// "com.apple.security.cs.allow-jit" entitlement (see IsAllowed()).
// On other platforms the scope is a no-op and thus it's allowed to be used.
//
// The semantics is the following: the scope switches permissions between
// writable and executable for all the pages allocated with RWX permissions.
// Only current thread is affected. This achieves "real" W^X and it's fast.
// By default it is assumed that the state is executable.
//
// The scope is reentrant and thread safe.
class V8_NODISCARD RwxMemoryWriteScope final {
public:
// The comment argument is used only for ensuring that explanation about why
// the scope is needed is given at particular use case.
V8_INLINE explicit RwxMemoryWriteScope(const char* comment);
V8_INLINE ~RwxMemoryWriteScope();
// Disable copy constructor and copy-assignment operator, since this manages
// a resource and implicit copying of the scope can yield surprising errors.
RwxMemoryWriteScope(const RwxMemoryWriteScope&) = delete;
RwxMemoryWriteScope& operator=(const RwxMemoryWriteScope&) = delete;
// Returns true if the configuration of the binary allows using of MAP_JIT
// machinery.
// This method is intended to be used for checking that the state of --jitless
// flag does not contradict the allowance of the MAP_JIT feature.
V8_INLINE static bool IsAllowed();
private:
friend class CodePageCollectionMemoryModificationScope;
friend class CodePageMemoryModificationScope;
friend class CodeSpaceMemoryModificationScope;
friend class RwxMemoryWriteScopeForTesting;
friend class wasm::CodeSpaceWriteScope;
// {SetWritable} and {SetExecutable} implicitly enters/exits the scope.
// These methods are exposed only for the purpose of implementing other
// scope classes that affect executable pages permissions.
V8_INLINE static void SetWritable();
V8_INLINE static void SetExecutable();
#if V8_HAS_PTHREAD_JIT_WRITE_PROTECT
// This counter is used for supporting scope reentrance.
static thread_local int code_space_write_nesting_level_;
#endif // V8_HAS_PTHREAD_JIT_WRITE_PROTECT
};
// This class is a no-op version of the RwxMemoryWriteScope class above.
// It's used as a target type for other scope type definitions when a no-op
// semantics is required.
class V8_NODISCARD NopRwxMemoryWriteScope final {
public:
V8_INLINE explicit NopRwxMemoryWriteScope(const char* comment) {
// Define a constructor to avoid unused variable warnings.
}
};
// Same as the RwxMemoryWriteScope but without inlining the code.
// This is a workaround for component build issue (crbug/1316800), when
// a thread_local value can't be properly exported.
class V8_NODISCARD RwxMemoryWriteScopeForTesting final {
public:
#if V8_HAS_PTHREAD_JIT_WRITE_PROTECT
V8_EXPORT_PRIVATE RwxMemoryWriteScopeForTesting();
V8_EXPORT_PRIVATE ~RwxMemoryWriteScopeForTesting();
#else
V8_INLINE RwxMemoryWriteScopeForTesting() {
// Define a constructor to avoid unused variable warnings.
}
#endif // V8_HAS_PTHREAD_JIT_WRITE_PROTECT
// Disable copy constructor and copy-assignment operator, since this manages
// a resource and implicit copying of the scope can yield surprising errors.
RwxMemoryWriteScopeForTesting(const RwxMemoryWriteScopeForTesting&) = delete;
RwxMemoryWriteScopeForTesting& operator=(
const RwxMemoryWriteScopeForTesting&) = delete;
};
} // namespace internal
} // namespace v8
#endif // V8_COMMON_CODE_MEMORY_ACCESS_H_