common.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. namespace scudo {
  17. template <class Dest, class Source> inline Dest bit_cast(const Source &S) {
  18. static_assert(sizeof(Dest) == sizeof(Source), "");
  19. Dest D;
  20. memcpy(&D, &S, sizeof(D));
  21. return D;
  22. }
  23. inline constexpr uptr roundUpTo(uptr X, uptr Boundary) {
  24. return (X + Boundary - 1) & ~(Boundary - 1);
  25. }
  26. inline constexpr uptr roundDownTo(uptr X, uptr Boundary) {
  27. return X & ~(Boundary - 1);
  28. }
  29. inline constexpr bool isAligned(uptr X, uptr Alignment) {
  30. return (X & (Alignment - 1)) == 0;
  31. }
  32. template <class T> constexpr T Min(T A, T B) { return A < B ? A : B; }
  33. template <class T> constexpr T Max(T A, T B) { return A > B ? A : B; }
  34. template <class T> void Swap(T &A, T &B) {
  35. T Tmp = A;
  36. A = B;
  37. B = Tmp;
  38. }
  39. inline bool isPowerOfTwo(uptr X) { return (X & (X - 1)) == 0; }
  40. inline uptr getMostSignificantSetBitIndex(uptr X) {
  41. DCHECK_NE(X, 0U);
  42. return SCUDO_WORDSIZE - 1U - static_cast<uptr>(__builtin_clzl(X));
  43. }
  44. inline uptr roundUpToPowerOfTwo(uptr Size) {
  45. DCHECK(Size);
  46. if (isPowerOfTwo(Size))
  47. return Size;
  48. const uptr Up = getMostSignificantSetBitIndex(Size);
  49. DCHECK_LT(Size, (1UL << (Up + 1)));
  50. DCHECK_GT(Size, (1UL << Up));
  51. return 1UL << (Up + 1);
  52. }
  53. inline uptr getLeastSignificantSetBitIndex(uptr X) {
  54. DCHECK_NE(X, 0U);
  55. return static_cast<uptr>(__builtin_ctzl(X));
  56. }
  57. inline uptr getLog2(uptr X) {
  58. DCHECK(isPowerOfTwo(X));
  59. return getLeastSignificantSetBitIndex(X);
  60. }
  61. inline u32 getRandomU32(u32 *State) {
  62. // ANSI C linear congruential PRNG (16-bit output).
  63. // return (*State = *State * 1103515245 + 12345) >> 16;
  64. // XorShift (32-bit output).
  65. *State ^= *State << 13;
  66. *State ^= *State >> 17;
  67. *State ^= *State << 5;
  68. return *State;
  69. }
  70. inline u32 getRandomModN(u32 *State, u32 N) {
  71. return getRandomU32(State) % N; // [0, N)
  72. }
  73. template <typename T> inline void shuffle(T *A, u32 N, u32 *RandState) {
  74. if (N <= 1)
  75. return;
  76. u32 State = *RandState;
  77. for (u32 I = N - 1; I > 0; I--)
  78. Swap(A[I], A[getRandomModN(&State, I + 1)]);
  79. *RandState = State;
  80. }
  81. // Hardware specific inlinable functions.
  82. inline void yieldProcessor(UNUSED u8 Count) {
  83. #if defined(__i386__) || defined(__x86_64__)
  84. __asm__ __volatile__("" ::: "memory");
  85. for (u8 I = 0; I < Count; I++)
  86. __asm__ __volatile__("pause");
  87. #elif defined(__aarch64__) || defined(__arm__)
  88. __asm__ __volatile__("" ::: "memory");
  89. for (u8 I = 0; I < Count; I++)
  90. __asm__ __volatile__("yield");
  91. #endif
  92. __asm__ __volatile__("" ::: "memory");
  93. }
  94. // Platform specific functions.
  95. extern uptr PageSizeCached;
  96. uptr getPageSizeSlow();
  97. inline uptr getPageSizeCached() {
  98. // Bionic uses a hardcoded value.
  99. if (SCUDO_ANDROID)
  100. return 4096U;
  101. if (LIKELY(PageSizeCached))
  102. return PageSizeCached;
  103. return getPageSizeSlow();
  104. }
  105. // Returns 0 if the number of CPUs could not be determined.
  106. u32 getNumberOfCPUs();
  107. const char *getEnv(const char *Name);
  108. uptr GetRSS();
  109. u64 getMonotonicTime();
  110. u32 getThreadID();
  111. // Our randomness gathering function is limited to 256 bytes to ensure we get
  112. // as many bytes as requested, and avoid interruptions (on Linux).
  113. constexpr uptr MaxRandomLength = 256U;
  114. bool getRandom(void *Buffer, uptr Length, bool Blocking = false);
  115. // Platform memory mapping functions.
  116. #define MAP_ALLOWNOMEM (1U << 0)
  117. #define MAP_NOACCESS (1U << 1)
  118. #define MAP_RESIZABLE (1U << 2)
  119. #define MAP_MEMTAG (1U << 3)
  120. #define MAP_PRECOMMIT (1U << 4)
  121. // Our platform memory mapping use is restricted to 3 scenarios:
  122. // - reserve memory at a random address (MAP_NOACCESS);
  123. // - commit memory in a previously reserved space;
  124. // - commit memory at a random address.
  125. // As such, only a subset of parameters combinations is valid, which is checked
  126. // by the function implementation. The Data parameter allows to pass opaque
  127. // platform specific data to the function.
  128. // Returns nullptr on error or dies if MAP_ALLOWNOMEM is not specified.
  129. void *map(void *Addr, uptr Size, const char *Name, uptr Flags = 0,
  130. MapPlatformData *Data = nullptr);
  131. // Indicates that we are getting rid of the whole mapping, which might have
  132. // further consequences on Data, depending on the platform.
  133. #define UNMAP_ALL (1U << 0)
  134. void unmap(void *Addr, uptr Size, uptr Flags = 0,
  135. MapPlatformData *Data = nullptr);
  136. void setMemoryPermission(uptr Addr, uptr Size, uptr Flags,
  137. MapPlatformData *Data = nullptr);
  138. void releasePagesToOS(uptr BaseAddress, uptr Offset, uptr Size,
  139. MapPlatformData *Data = nullptr);
  140. // Internal map & unmap fatal error. This must not call map(). SizeIfOOM shall
  141. // hold the requested size on an out-of-memory error, 0 otherwise.
  142. void NORETURN dieOnMapUnmapError(uptr SizeIfOOM = 0);
  143. // Logging related functions.
  144. void setAbortMessage(const char *Message);
  145. struct BlockInfo {
  146. uptr BlockBegin;
  147. uptr BlockSize;
  148. uptr RegionBegin;
  149. uptr RegionEnd;
  150. };
  151. enum class Option : u8 {
  152. ReleaseInterval, // Release to OS interval in milliseconds.
  153. MemtagTuning, // Whether to tune tagging for UAF or overflow.
  154. ThreadDisableMemInit, // Whether to disable automatic heap initialization and,
  155. // where possible, memory tagging, on this thread.
  156. MaxCacheEntriesCount, // Maximum number of blocks that can be cached.
  157. MaxCacheEntrySize, // Maximum size of a block that can be cached.
  158. MaxTSDsCount, // Number of usable TSDs for the shared registry.
  159. };
  160. constexpr unsigned char PatternFillByte = 0xAB;
  161. enum FillContentsMode {
  162. NoFill = 0,
  163. ZeroFill = 1,
  164. PatternOrZeroFill = 2 // Pattern fill unless the memory is known to be
  165. // zero-initialized already.
  166. };
  167. } // namespace scudo
  168. #endif // SCUDO_COMMON_H_