Path: blob/main/contrib/llvm-project/compiler-rt/lib/scudo/standalone/mem_map_base.h
35291 views
//===-- mem_map_base.h ------------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef SCUDO_MEM_MAP_BASE_H_9#define SCUDO_MEM_MAP_BASE_H_1011#include "common.h"1213namespace scudo {1415// In Scudo, every memory operation will be fulfilled through a16// platform-specific `MemMap` instance. The essential APIs are listed in the17// `MemMapBase` below. This is implemented in CRTP, so for each implementation,18// it has to implement all of the 'Impl' named functions.19template <class Derived> class MemMapBase {20public:21constexpr MemMapBase() = default;2223// This is used to map a new set of contiguous pages. Note that the `Addr` is24// only a suggestion to the system.25bool map(uptr Addr, uptr Size, const char *Name, uptr Flags = 0) {26DCHECK(!isAllocated());27return invokeImpl(&Derived::mapImpl, Addr, Size, Name, Flags);28}2930// This is used to unmap partial/full pages from the beginning or the end.31// I.e., the result pages are expected to be still contiguous.32void unmap(uptr Addr, uptr Size) {33DCHECK(isAllocated());34DCHECK((Addr == getBase()) || (Addr + Size == getBase() + getCapacity()));35invokeImpl(&Derived::unmapImpl, Addr, Size);36}3738// This is used to remap a mapped range (either from map() or dispatched from39// ReservedMemory). For example, we have reserved several pages and then we40// want to remap them with different accessibility.41bool remap(uptr Addr, uptr Size, const char *Name, uptr Flags = 0) {42DCHECK(isAllocated());43DCHECK((Addr >= getBase()) && (Addr + Size <= getBase() + getCapacity()));44return invokeImpl(&Derived::remapImpl, Addr, Size, Name, Flags);45}4647// This is used to update the pages' access permission. For example, mark48// pages as no read/write permission.49void setMemoryPermission(uptr Addr, uptr Size, uptr Flags) {50DCHECK(isAllocated());51DCHECK((Addr >= getBase()) && (Addr + Size <= getBase() + getCapacity()));52return invokeImpl(&Derived::setMemoryPermissionImpl, Addr, Size, Flags);53}5455// Suggest releasing a set of contiguous physical pages back to the OS. Note56// that only physical pages are supposed to be released. Any release of57// virtual pages may lead to undefined behavior.58void releasePagesToOS(uptr From, uptr Size) {59DCHECK(isAllocated());60DCHECK((From >= getBase()) && (From + Size <= getBase() + getCapacity()));61invokeImpl(&Derived::releasePagesToOSImpl, From, Size);62}63// This is similar to the above one except that any subsequent access to the64// released pages will return with zero-filled pages.65void releaseAndZeroPagesToOS(uptr From, uptr Size) {66DCHECK(isAllocated());67DCHECK((From >= getBase()) && (From + Size <= getBase() + getCapacity()));68invokeImpl(&Derived::releaseAndZeroPagesToOSImpl, From, Size);69}7071uptr getBase() { return invokeImpl(&Derived::getBaseImpl); }72uptr getCapacity() { return invokeImpl(&Derived::getCapacityImpl); }7374bool isAllocated() { return getBase() != 0U; }7576protected:77template <typename R, typename... Args>78R invokeImpl(R (Derived::*MemFn)(Args...), Args... args) {79return (static_cast<Derived *>(this)->*MemFn)(args...);80}81};8283// `ReservedMemory` is a special memory handle which can be viewed as a page84// allocator. `ReservedMemory` will reserve a contiguous pages and the later85// page request can be fulfilled at the designated address. This is used when86// we want to ensure the virtual address of the MemMap will be in a known range.87// This is implemented in CRTP, so for each88// implementation, it has to implement all of the 'Impl' named functions.89template <class Derived, typename MemMapTy> class ReservedMemory {90public:91using MemMapT = MemMapTy;92constexpr ReservedMemory() = default;9394// Reserve a chunk of memory at a suggested address.95bool create(uptr Addr, uptr Size, const char *Name, uptr Flags = 0) {96DCHECK(!isCreated());97return invokeImpl(&Derived::createImpl, Addr, Size, Name, Flags);98}99100// Release the entire reserved memory.101void release() {102DCHECK(isCreated());103invokeImpl(&Derived::releaseImpl);104}105106// Dispatch a sub-range of reserved memory. Note that any fragmentation of107// the reserved pages is managed by each implementation.108MemMapT dispatch(uptr Addr, uptr Size) {109DCHECK(isCreated());110DCHECK((Addr >= getBase()) && (Addr + Size <= getBase() + getCapacity()));111return invokeImpl(&Derived::dispatchImpl, Addr, Size);112}113114uptr getBase() { return invokeImpl(&Derived::getBaseImpl); }115uptr getCapacity() { return invokeImpl(&Derived::getCapacityImpl); }116117bool isCreated() { return getBase() != 0U; }118119protected:120template <typename R, typename... Args>121R invokeImpl(R (Derived::*MemFn)(Args...), Args... args) {122return (static_cast<Derived *>(this)->*MemFn)(args...);123}124};125126} // namespace scudo127128#endif // SCUDO_MEM_MAP_BASE_H_129130131