// Copyright 2021 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_BASE_EMULATED_VIRTUAL_ADDRESS_SUBSPACE_H_ #define V8_BASE_EMULATED_VIRTUAL_ADDRESS_SUBSPACE_H_ #include "include/v8-platform.h" #include "src/base/base-export.h" #include "src/base/compiler-specific.h" #include "src/base/platform/mutex.h" #include "src/base/region-allocator.h" #include "src/base/virtual-address-space.h" namespace v8 { namespace base { /** * Emulates a virtual address subspace. * * This class is (optionally) backed by a page allocation and emulates a virtual * address space that is potentially larger than that mapping. It generally * first attempts to satisfy page allocation requests from its backing mapping, * but will also attempt to obtain new page mappings inside the unmapped space * through page allocation hints if necessary. * * Caveat: an emulated subspace violates the invariant that page allocations in * an address space will never end up inside a child space and so does not * provide the same security gurarantees. */ class V8_BASE_EXPORT EmulatedVirtualAddressSubspace final : public NON_EXPORTED_BASE(::v8::VirtualAddressSpace) { public: // Construct an emulated virtual address subspace of the specified total size, // potentially backed by a page allocation from the parent space. The newly // created instance takes ownership of the page allocation (if any) and frees // it during destruction. EmulatedVirtualAddressSubspace(v8::VirtualAddressSpace* parent_space, Address base, size_t mapped_size, size_t total_size); ~EmulatedVirtualAddressSubspace() override; void SetRandomSeed(int64_t seed) override; Address RandomPageAddress() override; Address AllocatePages(Address hint, size_t size, size_t alignment, PagePermissions permissions) override; void FreePages(Address address, size_t size) override; Address AllocateSharedPages(Address hint, size_t size, PagePermissions permissions, PlatformSharedMemoryHandle handle, uint64_t offset) override; void FreeSharedPages(Address address, size_t size) override; bool SetPagePermissions(Address address, size_t size, PagePermissions permissions) override; bool AllocateGuardRegion(Address address, size_t size) override; void FreeGuardRegion(Address address, size_t size) override; bool CanAllocateSubspaces() override; std::unique_ptr AllocateSubspace( Address hint, size_t size, size_t alignment, PagePermissions max_page_permissions) override; bool DiscardSystemPages(Address address, size_t size) override; bool DecommitPages(Address address, size_t size) override; private: size_t mapped_size() const { return mapped_size_; } size_t unmapped_size() const { return size() - mapped_size_; } Address mapped_base() const { return base(); } Address unmapped_base() const { return base() + mapped_size_; } bool Contains(Address outer_start, size_t outer_size, Address inner_start, size_t inner_size) const { return (inner_start >= outer_start) && ((inner_start + inner_size) <= (outer_start + outer_size)); } bool Contains(Address addr, size_t length) const { return Contains(base(), size(), addr, length); } bool MappedRegionContains(Address addr, size_t length) const { return Contains(mapped_base(), mapped_size(), addr, length); } bool UnmappedRegionContains(Address addr, size_t length) const { return Contains(unmapped_base(), unmapped_size(), addr, length); } // Helper function to define a limit for the size of allocations in the // unmapped region. This limit makes it possible to estimate the expected // runtime of some loops in the Allocate methods. bool IsUsableSizeForUnmappedRegion(size_t size) const { return size <= (unmapped_size() / 2); } // Size of the mapped region located at the beginning of this address space. const size_t mapped_size_; // Pointer to the parent space from which the backing pages were allocated. // Must be kept alive by the owner of this instance. v8::VirtualAddressSpace* parent_space_; // Mutex guarding the non-threadsafe RegionAllocator and // RandomNumberGenerator. Mutex mutex_; // RegionAllocator to manage the page allocation and divide it into further // regions as necessary. RegionAllocator region_allocator_; // Random number generator for generating random addresses. RandomNumberGenerator rng_; }; } // namespace base } // namespace v8 #endif // V8_BASE_EMULATED_VIRTUAL_ADDRESS_SUBSPACE_H_