brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.3 KiB · 8adcebd Raw
263 lines · c
1//===-- common.h ------------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef SCUDO_COMMON_H_10#define SCUDO_COMMON_H_11 12#include "internal_defs.h"13 14#include "fuchsia.h"15#include "linux.h"16#include "trusty.h"17 18#include <stddef.h>19#include <string.h>20#include <unistd.h>21 22namespace scudo {23 24template <class Dest, class Source> inline Dest bit_cast(const Source &S) {25  static_assert(sizeof(Dest) == sizeof(Source), "");26  Dest D;27  memcpy(&D, &S, sizeof(D));28  return D;29}30 31inline constexpr bool isPowerOfTwo(uptr X) {32  if (X == 0)33    return false;34  return (X & (X - 1)) == 0;35}36 37inline constexpr uptr roundUp(uptr X, uptr Boundary) {38  DCHECK(isPowerOfTwo(Boundary));39  return (X + Boundary - 1) & ~(Boundary - 1);40}41inline constexpr uptr roundUpSlow(uptr X, uptr Boundary) {42  return ((X + Boundary - 1) / Boundary) * Boundary;43}44 45inline constexpr uptr roundDown(uptr X, uptr Boundary) {46  DCHECK(isPowerOfTwo(Boundary));47  return X & ~(Boundary - 1);48}49inline constexpr uptr roundDownSlow(uptr X, uptr Boundary) {50  return (X / Boundary) * Boundary;51}52 53inline constexpr bool isAligned(uptr X, uptr Alignment) {54  DCHECK(isPowerOfTwo(Alignment));55  return (X & (Alignment - 1)) == 0;56}57inline constexpr bool isAlignedSlow(uptr X, uptr Alignment) {58  return X % Alignment == 0;59}60 61template <class T> constexpr T Min(T A, T B) { return A < B ? A : B; }62 63template <class T> constexpr T Max(T A, T B) { return A > B ? A : B; }64 65template <class T> void Swap(T &A, T &B) {66  T Tmp = A;67  A = B;68  B = Tmp;69}70 71inline uptr getMostSignificantSetBitIndex(uptr X) {72  DCHECK_NE(X, 0U);73  return SCUDO_WORDSIZE - 1U - static_cast<uptr>(__builtin_clzl(X));74}75 76inline uptr roundUpPowerOfTwo(uptr Size) {77  DCHECK(Size);78  if (isPowerOfTwo(Size))79    return Size;80  const uptr Up = getMostSignificantSetBitIndex(Size);81  DCHECK_LT(Size, (1UL << (Up + 1)));82  DCHECK_GT(Size, (1UL << Up));83  return 1UL << (Up + 1);84}85 86inline uptr getLeastSignificantSetBitIndex(uptr X) {87  DCHECK_NE(X, 0U);88  return static_cast<uptr>(__builtin_ctzl(X));89}90 91inline uptr getLog2(uptr X) {92  DCHECK(isPowerOfTwo(X));93  return getLeastSignificantSetBitIndex(X);94}95 96inline u32 getRandomU32(u32 *State) {97  // ANSI C linear congruential PRNG (16-bit output).98  // return (*State = *State * 1103515245 + 12345) >> 16;99  // XorShift (32-bit output).100  *State ^= *State << 13;101  *State ^= *State >> 17;102  *State ^= *State << 5;103  return *State;104}105 106inline u32 getRandomModN(u32 *State, u32 N) {107  return getRandomU32(State) % N; // [0, N)108}109 110template <typename T> inline void shuffle(T *A, u32 N, u32 *RandState) {111  if (N <= 1)112    return;113  u32 State = *RandState;114  for (u32 I = N - 1; I > 0; I--)115    Swap(A[I], A[getRandomModN(&State, I + 1)]);116  *RandState = State;117}118 119inline void computePercentage(uptr Numerator, uptr Denominator, uptr *Integral,120                              uptr *Fractional) {121  constexpr uptr Digits = 100;122  if (Denominator == 0) {123    *Integral = 100;124    *Fractional = 0;125    return;126  }127 128  *Integral = Numerator * Digits / Denominator;129  *Fractional =130      (((Numerator * Digits) % Denominator) * Digits + Denominator / 2) /131      Denominator;132}133 134// Platform specific functions.135 136#if defined(SCUDO_PAGE_SIZE)137 138inline constexpr uptr getPageSizeCached() { return SCUDO_PAGE_SIZE; }139 140inline constexpr uptr getPageSizeSlow() { return getPageSizeCached(); }141 142inline constexpr uptr getPageSizeLogCached() {143  return static_cast<uptr>(__builtin_ctzl(SCUDO_PAGE_SIZE));144}145 146#else147 148extern uptr PageSizeCached;149extern uptr PageSizeLogCached;150 151// Must be defined in platform specific code.152uptr getPageSize();153 154// Always calls getPageSize(), but caches the results for get*Cached(), below.155uptr getPageSizeSlow();156 157inline uptr getPageSizeCached() {158  if (LIKELY(PageSizeCached))159    return PageSizeCached;160  return getPageSizeSlow();161}162 163inline uptr getPageSizeLogCached() {164  if (LIKELY(PageSizeLogCached))165    return PageSizeLogCached;166  // PageSizeLogCached and PageSizeCached are both set in getPageSizeSlow()167  getPageSizeSlow();168  DCHECK_NE(PageSizeLogCached, 0);169  return PageSizeLogCached;170}171 172#endif173 174// Returns 0 if the number of CPUs could not be determined.175u32 getNumberOfCPUs();176 177const char *getEnv(const char *Name);178 179u64 getMonotonicTime();180// Gets the time faster but with less accuracy. Can call getMonotonicTime181// if no fast version is available.182u64 getMonotonicTimeFast();183 184u32 getThreadID();185 186// Our randomness gathering function is limited to 256 bytes to ensure we get187// as many bytes as requested, and avoid interruptions (on Linux).188constexpr uptr MaxRandomLength = 256U;189bool getRandom(void *Buffer, uptr Length, bool Blocking = false);190 191// Platform memory mapping functions.192 193#define MAP_ALLOWNOMEM (1U << 0)194#define MAP_NOACCESS (1U << 1)195#define MAP_RESIZABLE (1U << 2)196#define MAP_MEMTAG (1U << 3)197#define MAP_PRECOMMIT (1U << 4)198 199// Our platform memory mapping use is restricted to 3 scenarios:200// - reserve memory at a random address (MAP_NOACCESS);201// - commit memory in a previously reserved space;202// - commit memory at a random address.203// As such, only a subset of parameters combinations is valid, which is checked204// by the function implementation. The Data parameter allows to pass opaque205// platform specific data to the function.206// Returns nullptr on error or dies if MAP_ALLOWNOMEM is not specified.207void *map(void *Addr, uptr Size, const char *Name, uptr Flags = 0,208          MapPlatformData *Data = nullptr);209 210// Indicates that we are getting rid of the whole mapping, which might have211// further consequences on Data, depending on the platform.212#define UNMAP_ALL (1U << 0)213 214void unmap(void *Addr, uptr Size, uptr Flags = 0,215           MapPlatformData *Data = nullptr);216 217void setMemoryPermission(uptr Addr, uptr Size, uptr Flags,218                         MapPlatformData *Data = nullptr);219 220void releasePagesToOS(uptr BaseAddress, uptr Offset, uptr Size,221                      MapPlatformData *Data = nullptr);222 223// Logging related functions.224 225void setAbortMessage(const char *Message);226 227struct BlockInfo {228  uptr BlockBegin;229  uptr BlockSize;230  uptr RegionBegin;231  uptr RegionEnd;232};233 234enum class Option : u8 {235  ReleaseInterval,      // Release to OS interval in milliseconds.236  MemtagTuning,         // Whether to tune tagging for UAF or overflow.237  ThreadDisableMemInit, // Whether to disable automatic heap initialization and,238                        // where possible, memory tagging, on this thread.239  MaxCacheEntriesCount, // Maximum number of blocks that can be cached.240  MaxCacheEntrySize,    // Maximum size of a block that can be cached.241  MaxTSDsCount,         // Number of usable TSDs for the shared registry.242};243 244enum class ReleaseToOS : u8 {245  Normal, // Follow the normal rules for releasing pages to the OS246  Force,  // Force release pages to the OS, but avoid cases that take too long.247  ForceAll, // Force release every page possible regardless of how long it will248            // take.249};250 251constexpr unsigned char PatternFillByte = 0xAB;252 253enum FillContentsMode {254  NoFill = 0,255  ZeroFill = 1,256  PatternOrZeroFill = 2 // Pattern fill unless the memory is known to be257                        // zero-initialized already.258};259 260} // namespace scudo261 262#endif // SCUDO_COMMON_H_263