xref: /aosp_15_r20/external/scudo/standalone/common.h (revision 76559068c068bd27e82aff38fac3bfc865233bca)
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