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