1 //===-- scudo_utils.cpp -----------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// Platform specific utility functions. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "scudo_utils.h" 15 16 #include <errno.h> 17 #include <fcntl.h> 18 #include <stdarg.h> 19 #include <unistd.h> 20 #if defined(__x86_64__) || defined(__i386__) 21 # include <cpuid.h> 22 #endif 23 #if defined(__arm__) || defined(__aarch64__) 24 # include <sys/auxv.h> 25 #endif 26 27 // TODO(kostyak): remove __sanitizer *Printf uses in favor for our own less 28 // complicated string formatting code. The following is a 29 // temporary workaround to be able to use __sanitizer::VSNPrintf. 30 namespace __sanitizer { 31 32 extern int VSNPrintf(char *buff, int buff_length, const char *format, 33 va_list args); 34 35 } // namespace __sanitizer 36 37 namespace __scudo { 38 39 FORMAT(1, 2) 40 void NORETURN dieWithMessage(const char *Format, ...) { 41 // Our messages are tiny, 256 characters is more than enough. 42 char Message[256]; 43 va_list Args; 44 va_start(Args, Format); 45 __sanitizer::VSNPrintf(Message, sizeof(Message), Format, Args); 46 va_end(Args); 47 RawWrite(Message); 48 Die(); 49 } 50 51 #if defined(__x86_64__) || defined(__i386__) 52 // i386 and x86_64 specific code to detect CRC32 hardware support via CPUID. 53 // CRC32 requires the SSE 4.2 instruction set. 54 typedef struct { 55 u32 Eax; 56 u32 Ebx; 57 u32 Ecx; 58 u32 Edx; 59 } CPUIDRegs; 60 61 static void getCPUID(CPUIDRegs *Regs, u32 Level) 62 { 63 __get_cpuid(Level, &Regs->Eax, &Regs->Ebx, &Regs->Ecx, &Regs->Edx); 64 } 65 66 CPUIDRegs getCPUFeatures() { 67 CPUIDRegs VendorRegs = {}; 68 getCPUID(&VendorRegs, 0); 69 bool IsIntel = 70 (VendorRegs.Ebx == signature_INTEL_ebx) && 71 (VendorRegs.Edx == signature_INTEL_edx) && 72 (VendorRegs.Ecx == signature_INTEL_ecx); 73 bool IsAMD = 74 (VendorRegs.Ebx == signature_AMD_ebx) && 75 (VendorRegs.Edx == signature_AMD_edx) && 76 (VendorRegs.Ecx == signature_AMD_ecx); 77 // Default to an empty feature set if not on a supported CPU. 78 CPUIDRegs FeaturesRegs = {}; 79 if (IsIntel || IsAMD) { 80 getCPUID(&FeaturesRegs, 1); 81 } 82 return FeaturesRegs; 83 } 84 85 #ifndef bit_SSE4_2 86 # define bit_SSE4_2 bit_SSE42 // clang and gcc have different defines. 87 #endif 88 89 bool testCPUFeature(CPUFeature Feature) 90 { 91 CPUIDRegs FeaturesRegs = getCPUFeatures(); 92 93 switch (Feature) { 94 case CRC32CPUFeature: // CRC32 is provided by SSE 4.2. 95 return !!(FeaturesRegs.Ecx & bit_SSE4_2); 96 default: 97 break; 98 } 99 return false; 100 } 101 #elif defined(__arm__) || defined(__aarch64__) 102 // For ARM and AArch64, hardware CRC32 support is indicated in the 103 // AT_HWVAL auxiliary vector. 104 105 #ifndef HWCAP_CRC32 106 # define HWCAP_CRC32 (1<<7) // HWCAP_CRC32 is missing on older platforms. 107 #endif 108 109 bool testCPUFeature(CPUFeature Feature) { 110 uptr HWCap = getauxval(AT_HWCAP); 111 112 switch (Feature) { 113 case CRC32CPUFeature: 114 return !!(HWCap & HWCAP_CRC32); 115 default: 116 break; 117 } 118 return false; 119 } 120 #else 121 bool testCPUFeature(CPUFeature Feature) { 122 return false; 123 } 124 #endif // defined(__x86_64__) || defined(__i386__) 125 126 } // namespace __scudo 127