| //===-- scudo_utils.h -------------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// Header for scudo_utils.cpp. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SCUDO_UTILS_H_ |
| #define SCUDO_UTILS_H_ |
| |
| #include "sanitizer_common/sanitizer_common.h" |
| |
| #include <string.h> |
| |
| namespace __scudo { |
| |
| template <class Dest, class Source> |
| inline Dest bit_cast(const Source& source) { |
| static_assert(sizeof(Dest) == sizeof(Source), "Sizes are not equal!"); |
| Dest dest; |
| memcpy(&dest, &source, sizeof(dest)); |
| return dest; |
| } |
| |
| void NORETURN dieWithMessage(const char *Format, ...); |
| |
| enum CPUFeature { |
| CRC32CPUFeature = 0, |
| MaxCPUFeature, |
| }; |
| bool testCPUFeature(CPUFeature Feature); |
| |
| INLINE u64 rotl(const u64 X, int K) { |
| return (X << K) | (X >> (64 - K)); |
| } |
| |
| // XoRoShiRo128+ PRNG (http://xoroshiro.di.unimi.it/). |
| struct XoRoShiRo128Plus { |
| public: |
| void init() { |
| if (UNLIKELY(!GetRandom(reinterpret_cast<void *>(State), sizeof(State), |
| /*blocking=*/false))) { |
| // On some platforms, early processes like `init` do not have an |
| // initialized random pool (getrandom blocks and /dev/urandom doesn't |
| // exist yet), but we still have to provide them with some degree of |
| // entropy. Not having a secure seed is not as problematic for them, as |
| // they are less likely to be the target of heap based vulnerabilities |
| // exploitation attempts. |
| State[0] = NanoTime(); |
| State[1] = 0; |
| } |
| fillCache(); |
| } |
| u8 getU8() { |
| if (UNLIKELY(isCacheEmpty())) |
| fillCache(); |
| const u8 Result = static_cast<u8>(CachedBytes & 0xff); |
| CachedBytes >>= 8; |
| CachedBytesAvailable--; |
| return Result; |
| } |
| u64 getU64() { return next(); } |
| |
| private: |
| u8 CachedBytesAvailable; |
| u64 CachedBytes; |
| u64 State[2]; |
| u64 next() { |
| const u64 S0 = State[0]; |
| u64 S1 = State[1]; |
| const u64 Result = S0 + S1; |
| S1 ^= S0; |
| State[0] = rotl(S0, 55) ^ S1 ^ (S1 << 14); |
| State[1] = rotl(S1, 36); |
| return Result; |
| } |
| bool isCacheEmpty() { |
| return CachedBytesAvailable == 0; |
| } |
| void fillCache() { |
| CachedBytes = next(); |
| CachedBytesAvailable = sizeof(CachedBytes); |
| } |
| }; |
| |
| typedef XoRoShiRo128Plus ScudoPrng; |
| |
| } // namespace __scudo |
| |
| #endif // SCUDO_UTILS_H_ |