1 //===-- scudo_utils.cpp -----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// Platform specific utility functions.
12 //===----------------------------------------------------------------------===//
14 #include "scudo_utils.h"
23 // TODO(kostyak): remove __sanitizer *Printf uses in favor for our own less
24 // complicated string formatting code. The following is a
25 // temporary workaround to be able to use __sanitizer::VSNPrintf.
26 namespace __sanitizer {
28 extern int VSNPrintf(char *buff, int buff_length, const char *format,
31 } // namespace __sanitizer
36 void dieWithMessage(const char *Format, ...) {
37 // Our messages are tiny, 128 characters is more than enough.
40 va_start(Args, Format);
41 __sanitizer::VSNPrintf(Message, sizeof(Message), Format, Args);
54 static void getCPUID(CPUIDInfo *info, u32 leaf, u32 subleaf)
57 : "=a" (info->Eax), "=b" (info->Ebx), "=c" (info->Ecx), "=d" (info->Edx)
58 : "a" (leaf), "c" (subleaf)
62 // Returns true is the CPU is a "GenuineIntel" or "AuthenticAMD"
63 static bool isSupportedCPU()
67 getCPUID(&Info, 0, 0);
68 if (memcmp(reinterpret_cast<char *>(&Info.Ebx), "Genu", 4) == 0 &&
69 memcmp(reinterpret_cast<char *>(&Info.Edx), "ineI", 4) == 0 &&
70 memcmp(reinterpret_cast<char *>(&Info.Ecx), "ntel", 4) == 0) {
73 if (memcmp(reinterpret_cast<char *>(&Info.Ebx), "Auth", 4) == 0 &&
74 memcmp(reinterpret_cast<char *>(&Info.Edx), "enti", 4) == 0 &&
75 memcmp(reinterpret_cast<char *>(&Info.Ecx), "cAMD", 4) == 0) {
81 bool testCPUFeature(CPUFeature feature)
83 static bool InfoInitialized = false;
84 static CPUIDInfo CPUInfo = {};
86 if (InfoInitialized == false) {
87 if (isSupportedCPU() == true)
88 getCPUID(&CPUInfo, 1, 0);
91 InfoInitialized = true;
95 return ((CPUInfo.Ecx >> 20) & 0x1) != 0;
102 // readRetry will attempt to read Count bytes from the Fd specified, and if
103 // interrupted will retry to read additional bytes to reach Count.
104 static ssize_t readRetry(int Fd, u8 *Buffer, size_t Count) {
105 ssize_t AmountRead = 0;
106 while (static_cast<size_t>(AmountRead) < Count) {
107 ssize_t Result = read(Fd, Buffer + AmountRead, Count - AmountRead);
109 AmountRead += Result;
112 else if (errno != EINTR) {
120 // Default constructor for Xorshift128Plus seeds the state with /dev/urandom
121 Xorshift128Plus::Xorshift128Plus() {
122 int Fd = open("/dev/urandom", O_RDONLY);
123 bool Success = readRetry(Fd, reinterpret_cast<u8 *>(&State_0_),
124 sizeof(State_0_)) == sizeof(State_0_);
125 Success &= readRetry(Fd, reinterpret_cast<u8 *>(&State_1_),
126 sizeof(State_1_)) == sizeof(State_1_);
129 dieWithMessage("ERROR: failed to read enough data from /dev/urandom.\n");
133 } // namespace __scudo