1 //===-- nsan.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 // This file is a part of NumericalStabilitySanitizer. 10 // 11 // Private NSan header. 12 //===----------------------------------------------------------------------===// 13 14 #ifndef NSAN_H 15 #define NSAN_H 16 17 #include "sanitizer_common/sanitizer_internal_defs.h" 18 19 using __sanitizer::sptr; 20 using __sanitizer::u16; 21 using __sanitizer::u8; 22 using __sanitizer::uptr; 23 24 #include "nsan_platform.h" 25 26 #include <assert.h> 27 #include <float.h> 28 #include <limits.h> 29 #include <math.h> 30 #include <stdio.h> 31 32 // Private nsan interface. Used e.g. by interceptors. 33 extern "C" { 34 35 void __nsan_init(); 36 37 // This marks the shadow type of the given block of application memory as 38 // unknown. 39 // printf-free (see comment in nsan_interceptors.cc). 40 void __nsan_set_value_unknown(const void *addr, uptr size); 41 42 // Copies annotations in the shadow memory for a block of application memory to 43 // a new address. This function is used together with memory-copying functions 44 // in application memory, e.g. the instrumentation inserts 45 // `__nsan_copy_values(dest, src, size)` after builtin calls to 46 // `memcpy(dest, src, size)`. Intercepted memcpy calls also call this function. 47 // printf-free (see comment in nsan_interceptors.cc). 48 void __nsan_copy_values(const void *daddr, const void *saddr, uptr size); 49 50 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char * 51 __nsan_default_options(); 52 } 53 54 // Unwind the stack for fatal error, as the parameter `stack` is 55 // empty without origins. 56 #define GET_FATAL_STACK_TRACE_IF_EMPTY(STACK) \ 57 if (nsan_initialized && (STACK)->size == 0) { \ 58 (STACK)->Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), nullptr, \ 59 common_flags()->fast_unwind_on_fatal); \ 60 } 61 62 namespace __nsan { 63 64 extern bool nsan_initialized; 65 extern bool nsan_init_is_running; 66 67 void InitializeInterceptors(); 68 void InitializeMallocInterceptors(); 69 70 // See notes in nsan_platform. 71 inline u8 *GetShadowAddrFor(void *ptr) { 72 uptr AppOffset = ((uptr)ptr) & ShadowMask(); 73 return (u8 *)(AppOffset * kShadowScale + ShadowAddr()); 74 } 75 76 inline u8 *GetShadowAddrFor(const void *ptr) { 77 return GetShadowAddrFor(const_cast<void *>(ptr)); 78 } 79 80 inline u8 *GetShadowTypeAddrFor(void *ptr) { 81 uptr app_offset = ((uptr)ptr) & ShadowMask(); 82 return (u8 *)(app_offset + TypesAddr()); 83 } 84 85 inline u8 *GetShadowTypeAddrFor(const void *ptr) { 86 return GetShadowTypeAddrFor(const_cast<void *>(ptr)); 87 } 88 89 // Information about value types and their shadow counterparts. 90 template <typename FT> struct FTInfo {}; 91 template <> struct FTInfo<float> { 92 using orig_type = float; 93 using orig_bits_type = u32; 94 using mantissa_bits_type = u32; 95 using shadow_type = double; 96 static const char *kCppTypeName; 97 static constexpr unsigned kMantissaBits = 23; 98 static constexpr int kExponentBits = 8; 99 static constexpr int kExponentBias = 127; 100 static constexpr int kValueType = kFloatValueType; 101 static constexpr char kTypePattern[sizeof(float)] = { 102 static_cast<unsigned char>(kValueType | (0 << kValueSizeSizeBits)), 103 static_cast<unsigned char>(kValueType | (1 << kValueSizeSizeBits)), 104 static_cast<unsigned char>(kValueType | (2 << kValueSizeSizeBits)), 105 static_cast<unsigned char>(kValueType | (3 << kValueSizeSizeBits)), 106 }; 107 static constexpr const float kEpsilon = FLT_EPSILON; 108 }; 109 template <> struct FTInfo<double> { 110 using orig_type = double; 111 using orig_bits_type = u64; 112 using mantissa_bits_type = u64; 113 using shadow_type = __float128; 114 static const char *kCppTypeName; 115 static constexpr unsigned kMantissaBits = 52; 116 static constexpr int kExponentBits = 11; 117 static constexpr int kExponentBias = 1023; 118 static constexpr int kValueType = kDoubleValueType; 119 static constexpr char kTypePattern[sizeof(double)] = { 120 static_cast<unsigned char>(kValueType | (0 << kValueSizeSizeBits)), 121 static_cast<unsigned char>(kValueType | (1 << kValueSizeSizeBits)), 122 static_cast<unsigned char>(kValueType | (2 << kValueSizeSizeBits)), 123 static_cast<unsigned char>(kValueType | (3 << kValueSizeSizeBits)), 124 static_cast<unsigned char>(kValueType | (4 << kValueSizeSizeBits)), 125 static_cast<unsigned char>(kValueType | (5 << kValueSizeSizeBits)), 126 static_cast<unsigned char>(kValueType | (6 << kValueSizeSizeBits)), 127 static_cast<unsigned char>(kValueType | (7 << kValueSizeSizeBits)), 128 }; 129 static constexpr const float kEpsilon = DBL_EPSILON; 130 }; 131 template <> struct FTInfo<long double> { 132 using orig_type = long double; 133 using mantissa_bits_type = u64; 134 using shadow_type = __float128; 135 static const char *kCppTypeName; 136 static constexpr unsigned kMantissaBits = 63; 137 static constexpr int kExponentBits = 15; 138 static constexpr int kExponentBias = (1 << (kExponentBits - 1)) - 1; 139 static constexpr int kValueType = kFp80ValueType; 140 static constexpr char kTypePattern[sizeof(long double)] = { 141 static_cast<unsigned char>(kValueType | (0 << kValueSizeSizeBits)), 142 static_cast<unsigned char>(kValueType | (1 << kValueSizeSizeBits)), 143 static_cast<unsigned char>(kValueType | (2 << kValueSizeSizeBits)), 144 static_cast<unsigned char>(kValueType | (3 << kValueSizeSizeBits)), 145 static_cast<unsigned char>(kValueType | (4 << kValueSizeSizeBits)), 146 static_cast<unsigned char>(kValueType | (5 << kValueSizeSizeBits)), 147 static_cast<unsigned char>(kValueType | (6 << kValueSizeSizeBits)), 148 static_cast<unsigned char>(kValueType | (7 << kValueSizeSizeBits)), 149 static_cast<unsigned char>(kValueType | (8 << kValueSizeSizeBits)), 150 static_cast<unsigned char>(kValueType | (9 << kValueSizeSizeBits)), 151 static_cast<unsigned char>(kValueType | (10 << kValueSizeSizeBits)), 152 static_cast<unsigned char>(kValueType | (11 << kValueSizeSizeBits)), 153 static_cast<unsigned char>(kValueType | (12 << kValueSizeSizeBits)), 154 static_cast<unsigned char>(kValueType | (13 << kValueSizeSizeBits)), 155 static_cast<unsigned char>(kValueType | (14 << kValueSizeSizeBits)), 156 static_cast<unsigned char>(kValueType | (15 << kValueSizeSizeBits)), 157 }; 158 static constexpr const float kEpsilon = LDBL_EPSILON; 159 }; 160 161 template <> struct FTInfo<__float128> { 162 using orig_type = __float128; 163 using orig_bits_type = __uint128_t; 164 using mantissa_bits_type = __uint128_t; 165 static const char *kCppTypeName; 166 static constexpr unsigned kMantissaBits = 112; 167 static constexpr int kExponentBits = 15; 168 static constexpr int kExponentBias = (1 << (kExponentBits - 1)) - 1; 169 }; 170 171 constexpr double kMaxULPDiff = INFINITY; 172 173 // Helper for getULPDiff that works on bit representations. 174 template <typename BT> double GetULPDiffBits(BT v1_bits, BT v2_bits) { 175 // If the integer representations of two same-sign floats are subtracted then 176 // the absolute value of the result is equal to one plus the number of 177 // representable floats between them. 178 return v1_bits >= v2_bits ? v1_bits - v2_bits : v2_bits - v1_bits; 179 } 180 181 // Returns the the number of floating point values between v1 and v2, capped to 182 // u64max. Return 0 for (-0.0,0.0). 183 template <typename FT> double GetULPDiff(FT v1, FT v2) { 184 if (v1 == v2) { 185 return 0; // Typically, -0.0 and 0.0 186 } 187 using BT = typename FTInfo<FT>::orig_bits_type; 188 static_assert(sizeof(FT) == sizeof(BT), "not implemented"); 189 static_assert(sizeof(BT) <= 64, "not implemented"); 190 BT v1_bits; 191 __builtin_memcpy(&v1_bits, &v1, sizeof(BT)); 192 BT v2_bits; 193 __builtin_memcpy(&v2_bits, &v2, sizeof(BT)); 194 // Check whether the signs differ. IEEE-754 float types always store the sign 195 // in the most significant bit. NaNs and infinities are handled by the calling 196 // code. 197 constexpr BT kSignMask = BT{1} << (CHAR_BIT * sizeof(BT) - 1); 198 if ((v1_bits ^ v2_bits) & kSignMask) { 199 // Signs differ. We can get the ULPs as `getULPDiff(negative_number, -0.0) 200 // + getULPDiff(0.0, positive_number)`. 201 if (v1_bits & kSignMask) { 202 return GetULPDiffBits<BT>(v1_bits, kSignMask) + 203 GetULPDiffBits<BT>(0, v2_bits); 204 } else { 205 return GetULPDiffBits<BT>(v2_bits, kSignMask) + 206 GetULPDiffBits<BT>(0, v1_bits); 207 } 208 } 209 return GetULPDiffBits(v1_bits, v2_bits); 210 } 211 212 // FIXME: This needs mor work: Because there is no 80-bit integer type, we have 213 // to go through __uint128_t. Therefore the assumptions about the sign bit do 214 // not hold. 215 template <> inline double GetULPDiff(long double v1, long double v2) { 216 using BT = __uint128_t; 217 BT v1_bits = 0; 218 __builtin_memcpy(&v1_bits, &v1, sizeof(long double)); 219 BT v2_bits = 0; 220 __builtin_memcpy(&v2_bits, &v2, sizeof(long double)); 221 if ((v1_bits ^ v2_bits) & (BT{1} << (CHAR_BIT * sizeof(BT) - 1))) 222 return v1 == v2 ? __sanitizer::u64{0} : kMaxULPDiff; // Signs differ. 223 // If the integer representations of two same-sign floats are subtracted then 224 // the absolute value of the result is equal to one plus the number of 225 // representable floats between them. 226 BT diff = v1_bits >= v2_bits ? v1_bits - v2_bits : v2_bits - v1_bits; 227 return diff >= kMaxULPDiff ? kMaxULPDiff : diff; 228 } 229 230 } // end namespace __nsan 231 232 #endif // NSAN_H 233