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