1 //===-- common.h ------------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef SCUDO_COMMON_H_
10 #define SCUDO_COMMON_H_
12 #include "internal_defs.h"
24 template <class Dest
, class Source
> inline Dest
bit_cast(const Source
&S
) {
25 static_assert(sizeof(Dest
) == sizeof(Source
), "");
27 memcpy(&D
, &S
, sizeof(D
));
31 inline constexpr bool isPowerOfTwo(uptr X
) { return (X
& (X
- 1)) == 0; }
33 inline constexpr uptr
roundUp(uptr X
, uptr Boundary
) {
34 DCHECK(isPowerOfTwo(Boundary
));
35 return (X
+ Boundary
- 1) & ~(Boundary
- 1);
37 inline constexpr uptr
roundUpSlow(uptr X
, uptr Boundary
) {
38 return ((X
+ Boundary
- 1) / Boundary
) * Boundary
;
41 inline constexpr uptr
roundDown(uptr X
, uptr Boundary
) {
42 DCHECK(isPowerOfTwo(Boundary
));
43 return X
& ~(Boundary
- 1);
45 inline constexpr uptr
roundDownSlow(uptr X
, uptr Boundary
) {
46 return (X
/ Boundary
) * Boundary
;
49 inline constexpr bool isAligned(uptr X
, uptr Alignment
) {
50 DCHECK(isPowerOfTwo(Alignment
));
51 return (X
& (Alignment
- 1)) == 0;
53 inline constexpr bool isAlignedSlow(uptr X
, uptr Alignment
) {
54 return X
% Alignment
== 0;
57 template <class T
> constexpr T
Min(T A
, T B
) { return A
< B
? A
: B
; }
59 template <class T
> constexpr T
Max(T A
, T B
) { return A
> B
? A
: B
; }
61 template <class T
> void Swap(T
&A
, T
&B
) {
67 inline uptr
getMostSignificantSetBitIndex(uptr X
) {
69 return SCUDO_WORDSIZE
- 1U - static_cast<uptr
>(__builtin_clzl(X
));
72 inline uptr
roundUpPowerOfTwo(uptr Size
) {
74 if (isPowerOfTwo(Size
))
76 const uptr Up
= getMostSignificantSetBitIndex(Size
);
77 DCHECK_LT(Size
, (1UL << (Up
+ 1)));
78 DCHECK_GT(Size
, (1UL << Up
));
79 return 1UL << (Up
+ 1);
82 inline uptr
getLeastSignificantSetBitIndex(uptr X
) {
84 return static_cast<uptr
>(__builtin_ctzl(X
));
87 inline uptr
getLog2(uptr X
) {
88 DCHECK(isPowerOfTwo(X
));
89 return getLeastSignificantSetBitIndex(X
);
92 inline u32
getRandomU32(u32
*State
) {
93 // ANSI C linear congruential PRNG (16-bit output).
94 // return (*State = *State * 1103515245 + 12345) >> 16;
95 // XorShift (32-bit output).
96 *State
^= *State
<< 13;
97 *State
^= *State
>> 17;
98 *State
^= *State
<< 5;
102 inline u32
getRandomModN(u32
*State
, u32 N
) {
103 return getRandomU32(State
) % N
; // [0, N)
106 template <typename T
> inline void shuffle(T
*A
, u32 N
, u32
*RandState
) {
109 u32 State
= *RandState
;
110 for (u32 I
= N
- 1; I
> 0; I
--)
111 Swap(A
[I
], A
[getRandomModN(&State
, I
+ 1)]);
115 inline void computePercentage(uptr Numerator
, uptr Denominator
, uptr
*Integral
,
117 constexpr uptr Digits
= 100;
118 if (Denominator
== 0) {
124 *Integral
= Numerator
* Digits
/ Denominator
;
126 (((Numerator
* Digits
) % Denominator
) * Digits
+ Denominator
/ 2) /
130 // Platform specific functions.
132 extern uptr PageSizeCached
;
133 uptr
getPageSizeSlow();
134 inline uptr
getPageSizeCached() {
135 #if SCUDO_ANDROID && defined(PAGE_SIZE)
136 // Most Android builds have a build-time constant page size.
139 if (LIKELY(PageSizeCached
))
140 return PageSizeCached
;
141 return getPageSizeSlow();
144 // Returns 0 if the number of CPUs could not be determined.
145 u32
getNumberOfCPUs();
147 const char *getEnv(const char *Name
);
149 u64
getMonotonicTime();
150 // Gets the time faster but with less accuracy. Can call getMonotonicTime
151 // if no fast version is available.
152 u64
getMonotonicTimeFast();
156 // Our randomness gathering function is limited to 256 bytes to ensure we get
157 // as many bytes as requested, and avoid interruptions (on Linux).
158 constexpr uptr MaxRandomLength
= 256U;
159 bool getRandom(void *Buffer
, uptr Length
, bool Blocking
= false);
161 // Platform memory mapping functions.
163 #define MAP_ALLOWNOMEM (1U << 0)
164 #define MAP_NOACCESS (1U << 1)
165 #define MAP_RESIZABLE (1U << 2)
166 #define MAP_MEMTAG (1U << 3)
167 #define MAP_PRECOMMIT (1U << 4)
169 // Our platform memory mapping use is restricted to 3 scenarios:
170 // - reserve memory at a random address (MAP_NOACCESS);
171 // - commit memory in a previously reserved space;
172 // - commit memory at a random address.
173 // As such, only a subset of parameters combinations is valid, which is checked
174 // by the function implementation. The Data parameter allows to pass opaque
175 // platform specific data to the function.
176 // Returns nullptr on error or dies if MAP_ALLOWNOMEM is not specified.
177 void *map(void *Addr
, uptr Size
, const char *Name
, uptr Flags
= 0,
178 MapPlatformData
*Data
= nullptr);
180 // Indicates that we are getting rid of the whole mapping, which might have
181 // further consequences on Data, depending on the platform.
182 #define UNMAP_ALL (1U << 0)
184 void unmap(void *Addr
, uptr Size
, uptr Flags
= 0,
185 MapPlatformData
*Data
= nullptr);
187 void setMemoryPermission(uptr Addr
, uptr Size
, uptr Flags
,
188 MapPlatformData
*Data
= nullptr);
190 void releasePagesToOS(uptr BaseAddress
, uptr Offset
, uptr Size
,
191 MapPlatformData
*Data
= nullptr);
193 // Logging related functions.
195 void setAbortMessage(const char *Message
);
204 enum class Option
: u8
{
205 ReleaseInterval
, // Release to OS interval in milliseconds.
206 MemtagTuning
, // Whether to tune tagging for UAF or overflow.
207 ThreadDisableMemInit
, // Whether to disable automatic heap initialization and,
208 // where possible, memory tagging, on this thread.
209 MaxCacheEntriesCount
, // Maximum number of blocks that can be cached.
210 MaxCacheEntrySize
, // Maximum size of a block that can be cached.
211 MaxTSDsCount
, // Number of usable TSDs for the shared registry.
214 enum class ReleaseToOS
: u8
{
215 Normal
, // Follow the normal rules for releasing pages to the OS
216 Force
, // Force release pages to the OS, but avoid cases that take too long.
217 ForceAll
, // Force release every page possible regardless of how long it will
221 constexpr unsigned char PatternFillByte
= 0xAB;
223 enum FillContentsMode
{
226 PatternOrZeroFill
= 2 // Pattern fill unless the memory is known to be
227 // zero-initialized already.
232 #endif // SCUDO_COMMON_H_