Path: blob/main/contrib/llvm-project/compiler-rt/lib/scudo/standalone/common.h
35292 views
//===-- common.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_COMMON_H_9#define SCUDO_COMMON_H_1011#include "internal_defs.h"1213#include "fuchsia.h"14#include "linux.h"15#include "trusty.h"1617#include <stddef.h>18#include <string.h>19#include <unistd.h>2021namespace scudo {2223template <class Dest, class Source> inline Dest bit_cast(const Source &S) {24static_assert(sizeof(Dest) == sizeof(Source), "");25Dest D;26memcpy(&D, &S, sizeof(D));27return D;28}2930inline constexpr bool isPowerOfTwo(uptr X) {31if (X == 0)32return false;33return (X & (X - 1)) == 0;34}3536inline constexpr uptr roundUp(uptr X, uptr Boundary) {37DCHECK(isPowerOfTwo(Boundary));38return (X + Boundary - 1) & ~(Boundary - 1);39}40inline constexpr uptr roundUpSlow(uptr X, uptr Boundary) {41return ((X + Boundary - 1) / Boundary) * Boundary;42}4344inline constexpr uptr roundDown(uptr X, uptr Boundary) {45DCHECK(isPowerOfTwo(Boundary));46return X & ~(Boundary - 1);47}48inline constexpr uptr roundDownSlow(uptr X, uptr Boundary) {49return (X / Boundary) * Boundary;50}5152inline constexpr bool isAligned(uptr X, uptr Alignment) {53DCHECK(isPowerOfTwo(Alignment));54return (X & (Alignment - 1)) == 0;55}56inline constexpr bool isAlignedSlow(uptr X, uptr Alignment) {57return X % Alignment == 0;58}5960template <class T> constexpr T Min(T A, T B) { return A < B ? A : B; }6162template <class T> constexpr T Max(T A, T B) { return A > B ? A : B; }6364template <class T> void Swap(T &A, T &B) {65T Tmp = A;66A = B;67B = Tmp;68}6970inline uptr getMostSignificantSetBitIndex(uptr X) {71DCHECK_NE(X, 0U);72return SCUDO_WORDSIZE - 1U - static_cast<uptr>(__builtin_clzl(X));73}7475inline uptr roundUpPowerOfTwo(uptr Size) {76DCHECK(Size);77if (isPowerOfTwo(Size))78return Size;79const uptr Up = getMostSignificantSetBitIndex(Size);80DCHECK_LT(Size, (1UL << (Up + 1)));81DCHECK_GT(Size, (1UL << Up));82return 1UL << (Up + 1);83}8485inline uptr getLeastSignificantSetBitIndex(uptr X) {86DCHECK_NE(X, 0U);87return static_cast<uptr>(__builtin_ctzl(X));88}8990inline uptr getLog2(uptr X) {91DCHECK(isPowerOfTwo(X));92return getLeastSignificantSetBitIndex(X);93}9495inline u32 getRandomU32(u32 *State) {96// ANSI C linear congruential PRNG (16-bit output).97// return (*State = *State * 1103515245 + 12345) >> 16;98// XorShift (32-bit output).99*State ^= *State << 13;100*State ^= *State >> 17;101*State ^= *State << 5;102return *State;103}104105inline u32 getRandomModN(u32 *State, u32 N) {106return getRandomU32(State) % N; // [0, N)107}108109template <typename T> inline void shuffle(T *A, u32 N, u32 *RandState) {110if (N <= 1)111return;112u32 State = *RandState;113for (u32 I = N - 1; I > 0; I--)114Swap(A[I], A[getRandomModN(&State, I + 1)]);115*RandState = State;116}117118inline void computePercentage(uptr Numerator, uptr Denominator, uptr *Integral,119uptr *Fractional) {120constexpr uptr Digits = 100;121if (Denominator == 0) {122*Integral = 100;123*Fractional = 0;124return;125}126127*Integral = Numerator * Digits / Denominator;128*Fractional =129(((Numerator * Digits) % Denominator) * Digits + Denominator / 2) /130Denominator;131}132133// Platform specific functions.134135extern uptr PageSizeCached;136uptr getPageSizeSlow();137inline uptr getPageSizeCached() {138#if SCUDO_ANDROID && defined(PAGE_SIZE)139// Most Android builds have a build-time constant page size.140return PAGE_SIZE;141#endif142if (LIKELY(PageSizeCached))143return PageSizeCached;144return getPageSizeSlow();145}146147// Returns 0 if the number of CPUs could not be determined.148u32 getNumberOfCPUs();149150const char *getEnv(const char *Name);151152u64 getMonotonicTime();153// Gets the time faster but with less accuracy. Can call getMonotonicTime154// if no fast version is available.155u64 getMonotonicTimeFast();156157u32 getThreadID();158159// Our randomness gathering function is limited to 256 bytes to ensure we get160// as many bytes as requested, and avoid interruptions (on Linux).161constexpr uptr MaxRandomLength = 256U;162bool getRandom(void *Buffer, uptr Length, bool Blocking = false);163164// Platform memory mapping functions.165166#define MAP_ALLOWNOMEM (1U << 0)167#define MAP_NOACCESS (1U << 1)168#define MAP_RESIZABLE (1U << 2)169#define MAP_MEMTAG (1U << 3)170#define MAP_PRECOMMIT (1U << 4)171172// Our platform memory mapping use is restricted to 3 scenarios:173// - reserve memory at a random address (MAP_NOACCESS);174// - commit memory in a previously reserved space;175// - commit memory at a random address.176// As such, only a subset of parameters combinations is valid, which is checked177// by the function implementation. The Data parameter allows to pass opaque178// platform specific data to the function.179// Returns nullptr on error or dies if MAP_ALLOWNOMEM is not specified.180void *map(void *Addr, uptr Size, const char *Name, uptr Flags = 0,181MapPlatformData *Data = nullptr);182183// Indicates that we are getting rid of the whole mapping, which might have184// further consequences on Data, depending on the platform.185#define UNMAP_ALL (1U << 0)186187void unmap(void *Addr, uptr Size, uptr Flags = 0,188MapPlatformData *Data = nullptr);189190void setMemoryPermission(uptr Addr, uptr Size, uptr Flags,191MapPlatformData *Data = nullptr);192193void releasePagesToOS(uptr BaseAddress, uptr Offset, uptr Size,194MapPlatformData *Data = nullptr);195196// Logging related functions.197198void setAbortMessage(const char *Message);199200struct BlockInfo {201uptr BlockBegin;202uptr BlockSize;203uptr RegionBegin;204uptr RegionEnd;205};206207enum class Option : u8 {208ReleaseInterval, // Release to OS interval in milliseconds.209MemtagTuning, // Whether to tune tagging for UAF or overflow.210ThreadDisableMemInit, // Whether to disable automatic heap initialization and,211// where possible, memory tagging, on this thread.212MaxCacheEntriesCount, // Maximum number of blocks that can be cached.213MaxCacheEntrySize, // Maximum size of a block that can be cached.214MaxTSDsCount, // Number of usable TSDs for the shared registry.215};216217enum class ReleaseToOS : u8 {218Normal, // Follow the normal rules for releasing pages to the OS219Force, // Force release pages to the OS, but avoid cases that take too long.220ForceAll, // Force release every page possible regardless of how long it will221// take.222};223224constexpr unsigned char PatternFillByte = 0xAB;225226enum FillContentsMode {227NoFill = 0,228ZeroFill = 1,229PatternOrZeroFill = 2 // Pattern fill unless the memory is known to be230// zero-initialized already.231};232233} // namespace scudo234235#endif // SCUDO_COMMON_H_236237238