common.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef SCUDO_COMMON_H_
  9. #define SCUDO_COMMON_H_
  10. #include "internal_defs.h"
  11. #include "fuchsia.h"
  12. #include "linux.h"
  13. #include "trusty.h"
  14. #include <stddef.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17. namespace scudo {
  18. template <class Dest, class Source> inline Dest bit_cast(const Source &S) {
  19. static_assert(sizeof(Dest) == sizeof(Source), "");
  20. Dest D;
  21. memcpy(&D, &S, sizeof(D));
  22. return D;
  23. }
  24. inline constexpr bool isPowerOfTwo(uptr X) { return (X & (X - 1)) == 0; }
  25. inline constexpr uptr roundUp(uptr X, uptr Boundary) {
  26. DCHECK(isPowerOfTwo(Boundary));
  27. return (X + Boundary - 1) & ~(Boundary - 1);
  28. }
  29. inline constexpr uptr roundUpSlow(uptr X, uptr Boundary) {
  30. return ((X + Boundary - 1) / Boundary) * Boundary;
  31. }
  32. inline constexpr uptr roundDown(uptr X, uptr Boundary) {
  33. DCHECK(isPowerOfTwo(Boundary));
  34. return X & ~(Boundary - 1);
  35. }
  36. inline constexpr uptr roundDownSlow(uptr X, uptr Boundary) {
  37. return (X / Boundary) * Boundary;
  38. }
  39. inline constexpr bool isAligned(uptr X, uptr Alignment) {
  40. DCHECK(isPowerOfTwo(Alignment));
  41. return (X & (Alignment - 1)) == 0;
  42. }
  43. inline constexpr bool isAlignedSlow(uptr X, uptr Alignment) {
  44. return X % Alignment == 0;
  45. }
  46. template <class T> constexpr T Min(T A, T B) { return A < B ? A : B; }
  47. template <class T> constexpr T Max(T A, T B) { return A > B ? A : B; }
  48. template <class T> void Swap(T &A, T &B) {
  49. T Tmp = A;
  50. A = B;
  51. B = Tmp;
  52. }
  53. inline uptr getMostSignificantSetBitIndex(uptr X) {
  54. DCHECK_NE(X, 0U);
  55. return SCUDO_WORDSIZE - 1U - static_cast<uptr>(__builtin_clzl(X));
  56. }
  57. inline uptr roundUpPowerOfTwo(uptr Size) {
  58. DCHECK(Size);
  59. if (isPowerOfTwo(Size))
  60. return Size;
  61. const uptr Up = getMostSignificantSetBitIndex(Size);
  62. DCHECK_LT(Size, (1UL << (Up + 1)));
  63. DCHECK_GT(Size, (1UL << Up));
  64. return 1UL << (Up + 1);
  65. }
  66. inline uptr getLeastSignificantSetBitIndex(uptr X) {
  67. DCHECK_NE(X, 0U);
  68. return static_cast<uptr>(__builtin_ctzl(X));
  69. }
  70. inline uptr getLog2(uptr X) {
  71. DCHECK(isPowerOfTwo(X));
  72. return getLeastSignificantSetBitIndex(X);
  73. }
  74. inline u32 getRandomU32(u32 *State) {
  75. // ANSI C linear congruential PRNG (16-bit output).
  76. // return (*State = *State * 1103515245 + 12345) >> 16;
  77. // XorShift (32-bit output).
  78. *State ^= *State << 13;
  79. *State ^= *State >> 17;
  80. *State ^= *State << 5;
  81. return *State;
  82. }
  83. inline u32 getRandomModN(u32 *State, u32 N) {
  84. return getRandomU32(State) % N; // [0, N)
  85. }
  86. template <typename T> inline void shuffle(T *A, u32 N, u32 *RandState) {
  87. if (N <= 1)
  88. return;
  89. u32 State = *RandState;
  90. for (u32 I = N - 1; I > 0; I--)
  91. Swap(A[I], A[getRandomModN(&State, I + 1)]);
  92. *RandState = State;
  93. }
  94. inline void computePercentage(uptr Numerator, uptr Denominator, uptr *Integral,
  95. uptr *Fractional) {
  96. constexpr uptr Digits = 100;
  97. if (Denominator == 0) {
  98. *Integral = 100;
  99. *Fractional = 0;
  100. return;
  101. }
  102. *Integral = Numerator * Digits / Denominator;
  103. *Fractional =
  104. (((Numerator * Digits) % Denominator) * Digits + Denominator / 2) /
  105. Denominator;
  106. }
  107. // Platform specific functions.
  108. extern uptr PageSizeCached;
  109. uptr getPageSizeSlow();
  110. inline uptr getPageSizeCached() {
  111. #if SCUDO_ANDROID && defined(PAGE_SIZE)
  112. // Most Android builds have a build-time constant page size.
  113. return PAGE_SIZE;
  114. #endif
  115. if (LIKELY(PageSizeCached))
  116. return PageSizeCached;
  117. return getPageSizeSlow();
  118. }
  119. // Returns 0 if the number of CPUs could not be determined.
  120. u32 getNumberOfCPUs();
  121. const char *getEnv(const char *Name);
  122. u64 getMonotonicTime();
  123. // Gets the time faster but with less accuracy. Can call getMonotonicTime
  124. // if no fast version is available.
  125. u64 getMonotonicTimeFast();
  126. u32 getThreadID();
  127. // Our randomness gathering function is limited to 256 bytes to ensure we get
  128. // as many bytes as requested, and avoid interruptions (on Linux).
  129. constexpr uptr MaxRandomLength = 256U;
  130. bool getRandom(void *Buffer, uptr Length, bool Blocking = false);
  131. // Platform memory mapping functions.
  132. #define MAP_ALLOWNOMEM (1U << 0)
  133. #define MAP_NOACCESS (1U << 1)
  134. #define MAP_RESIZABLE (1U << 2)
  135. #define MAP_MEMTAG (1U << 3)
  136. #define MAP_PRECOMMIT (1U << 4)
  137. // Our platform memory mapping use is restricted to 3 scenarios:
  138. // - reserve memory at a random address (MAP_NOACCESS);
  139. // - commit memory in a previously reserved space;
  140. // - commit memory at a random address.
  141. // As such, only a subset of parameters combinations is valid, which is checked
  142. // by the function implementation. The Data parameter allows to pass opaque
  143. // platform specific data to the function.
  144. // Returns nullptr on error or dies if MAP_ALLOWNOMEM is not specified.
  145. void *map(void *Addr, uptr Size, const char *Name, uptr Flags = 0,
  146. MapPlatformData *Data = nullptr);
  147. // Indicates that we are getting rid of the whole mapping, which might have
  148. // further consequences on Data, depending on the platform.
  149. #define UNMAP_ALL (1U << 0)
  150. void unmap(void *Addr, uptr Size, uptr Flags = 0,
  151. MapPlatformData *Data = nullptr);
  152. void setMemoryPermission(uptr Addr, uptr Size, uptr Flags,
  153. MapPlatformData *Data = nullptr);
  154. void releasePagesToOS(uptr BaseAddress, uptr Offset, uptr Size,
  155. MapPlatformData *Data = nullptr);
  156. // Logging related functions.
  157. void setAbortMessage(const char *Message);
  158. struct BlockInfo {
  159. uptr BlockBegin;
  160. uptr BlockSize;
  161. uptr RegionBegin;
  162. uptr RegionEnd;
  163. };
  164. enum class Option : u8 {
  165. ReleaseInterval, // Release to OS interval in milliseconds.
  166. MemtagTuning, // Whether to tune tagging for UAF or overflow.
  167. ThreadDisableMemInit, // Whether to disable automatic heap initialization and,
  168. // where possible, memory tagging, on this thread.
  169. MaxCacheEntriesCount, // Maximum number of blocks that can be cached.
  170. MaxCacheEntrySize, // Maximum size of a block that can be cached.
  171. MaxTSDsCount, // Number of usable TSDs for the shared registry.
  172. };
  173. enum class ReleaseToOS : u8 {
  174. Normal, // Follow the normal rules for releasing pages to the OS
  175. Force, // Force release pages to the OS, but avoid cases that take too long.
  176. ForceAll, // Force release every page possible regardless of how long it will
  177. // take.
  178. };
  179. constexpr unsigned char PatternFillByte = 0xAB;
  180. enum FillContentsMode {
  181. NoFill = 0,
  182. ZeroFill = 1,
  183. PatternOrZeroFill = 2 // Pattern fill unless the memory is known to be
  184. // zero-initialized already.
  185. };
  186. } // namespace scudo
  187. #endif // SCUDO_COMMON_H_