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