xref: /freebsd/contrib/llvm-project/compiler-rt/lib/nsan/nsan.h (revision 5036d9652a5701d00e9e40ea942c278e9f77d33d)
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 u8 *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 u8 *daddr, const u8 *saddr, uptr size);
49 
50 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char *
51 __nsan_default_options();
52 }
53 
54 namespace __nsan {
55 
56 extern bool nsan_initialized;
57 extern bool nsan_init_is_running;
58 
59 void InitializeInterceptors();
60 void InitializeMallocInterceptors();
61 
62 // See notes in nsan_platform.
63 // printf-free (see comment in nsan_interceptors.cc).
64 inline u8 *GetShadowAddrFor(u8 *Ptr) {
65   uptr AppOffset = ((uptr)Ptr) & ShadowMask();
66   return (u8 *)(AppOffset * kShadowScale + ShadowAddr());
67 }
68 
69 // printf-free (see comment in nsan_interceptors.cc).
70 inline const u8 *GetShadowAddrFor(const u8 *Ptr) {
71   return GetShadowAddrFor(const_cast<u8 *>(Ptr));
72 }
73 
74 // printf-free (see comment in nsan_interceptors.cc).
75 inline u8 *GetShadowTypeAddrFor(u8 *Ptr) {
76   uptr AppOffset = ((uptr)Ptr) & ShadowMask();
77   return (u8 *)(AppOffset + TypesAddr());
78 }
79 
80 // printf-free (see comment in nsan_interceptors.cc).
81 inline const u8 *GetShadowTypeAddrFor(const u8 *Ptr) {
82   return GetShadowTypeAddrFor(const_cast<u8 *>(Ptr));
83 }
84 
85 // Information about value types and their shadow counterparts.
86 template <typename FT> struct FTInfo {};
87 template <> struct FTInfo<float> {
88   using orig_type = float;
89   using orig_bits_type = __sanitizer::u32;
90   using mantissa_bits_type = __sanitizer::u32;
91   using shadow_type = double;
92   static const char *kCppTypeName;
93   static constexpr unsigned kMantissaBits = 23;
94   static constexpr int kExponentBits = 8;
95   static constexpr int kExponentBias = 127;
96   static constexpr int kValueType = kFloatValueType;
97   static constexpr char kTypePattern[sizeof(float)] = {
98       static_cast<unsigned char>(kValueType | (0 << kValueSizeSizeBits)),
99       static_cast<unsigned char>(kValueType | (1 << kValueSizeSizeBits)),
100       static_cast<unsigned char>(kValueType | (2 << kValueSizeSizeBits)),
101       static_cast<unsigned char>(kValueType | (3 << kValueSizeSizeBits)),
102   };
103   static constexpr const float kEpsilon = FLT_EPSILON;
104 };
105 template <> struct FTInfo<double> {
106   using orig_type = double;
107   using orig_bits_type = __sanitizer::u64;
108   using mantissa_bits_type = __sanitizer::u64;
109   using shadow_type = __float128;
110   static const char *kCppTypeName;
111   static constexpr unsigned kMantissaBits = 52;
112   static constexpr int kExponentBits = 11;
113   static constexpr int kExponentBias = 1023;
114   static constexpr int kValueType = kDoubleValueType;
115   static constexpr char kTypePattern[sizeof(double)] = {
116       static_cast<unsigned char>(kValueType | (0 << kValueSizeSizeBits)),
117       static_cast<unsigned char>(kValueType | (1 << kValueSizeSizeBits)),
118       static_cast<unsigned char>(kValueType | (2 << kValueSizeSizeBits)),
119       static_cast<unsigned char>(kValueType | (3 << kValueSizeSizeBits)),
120       static_cast<unsigned char>(kValueType | (4 << kValueSizeSizeBits)),
121       static_cast<unsigned char>(kValueType | (5 << kValueSizeSizeBits)),
122       static_cast<unsigned char>(kValueType | (6 << kValueSizeSizeBits)),
123       static_cast<unsigned char>(kValueType | (7 << kValueSizeSizeBits)),
124   };
125   static constexpr const float kEpsilon = DBL_EPSILON;
126 };
127 template <> struct FTInfo<long double> {
128   using orig_type = long double;
129   using mantissa_bits_type = __sanitizer::u64;
130   using shadow_type = __float128;
131   static const char *kCppTypeName;
132   static constexpr unsigned kMantissaBits = 63;
133   static constexpr int kExponentBits = 15;
134   static constexpr int kExponentBias = (1 << (kExponentBits - 1)) - 1;
135   static constexpr int kValueType = kFp80ValueType;
136   static constexpr char kTypePattern[sizeof(long double)] = {
137       static_cast<unsigned char>(kValueType | (0 << kValueSizeSizeBits)),
138       static_cast<unsigned char>(kValueType | (1 << kValueSizeSizeBits)),
139       static_cast<unsigned char>(kValueType | (2 << kValueSizeSizeBits)),
140       static_cast<unsigned char>(kValueType | (3 << kValueSizeSizeBits)),
141       static_cast<unsigned char>(kValueType | (4 << kValueSizeSizeBits)),
142       static_cast<unsigned char>(kValueType | (5 << kValueSizeSizeBits)),
143       static_cast<unsigned char>(kValueType | (6 << kValueSizeSizeBits)),
144       static_cast<unsigned char>(kValueType | (7 << kValueSizeSizeBits)),
145       static_cast<unsigned char>(kValueType | (8 << kValueSizeSizeBits)),
146       static_cast<unsigned char>(kValueType | (9 << kValueSizeSizeBits)),
147       static_cast<unsigned char>(kValueType | (10 << kValueSizeSizeBits)),
148       static_cast<unsigned char>(kValueType | (11 << kValueSizeSizeBits)),
149       static_cast<unsigned char>(kValueType | (12 << kValueSizeSizeBits)),
150       static_cast<unsigned char>(kValueType | (13 << kValueSizeSizeBits)),
151       static_cast<unsigned char>(kValueType | (14 << kValueSizeSizeBits)),
152       static_cast<unsigned char>(kValueType | (15 << kValueSizeSizeBits)),
153   };
154   static constexpr const float kEpsilon = LDBL_EPSILON;
155 };
156 
157 template <> struct FTInfo<__float128> {
158   using orig_type = __float128;
159   using orig_bits_type = __uint128_t;
160   using mantissa_bits_type = __uint128_t;
161   static const char *kCppTypeName;
162   static constexpr unsigned kMantissaBits = 112;
163   static constexpr int kExponentBits = 15;
164   static constexpr int kExponentBias = (1 << (kExponentBits - 1)) - 1;
165 };
166 
167 constexpr double kMaxULPDiff = INFINITY;
168 
169 // Helper for getULPDiff that works on bit representations.
170 template <typename BT> double GetULPDiffBits(BT v1_bits, BT v2_bits) {
171   // If the integer representations of two same-sign floats are subtracted then
172   // the absolute value of the result is equal to one plus the number of
173   // representable floats between them.
174   return v1_bits >= v2_bits ? v1_bits - v2_bits : v2_bits - v1_bits;
175 }
176 
177 // Returns the the number of floating point values between v1 and v2, capped to
178 // u64max. Return 0 for (-0.0,0.0).
179 template <typename FT> double GetULPDiff(FT v1, FT v2) {
180   if (v1 == v2) {
181     return 0; // Typically, -0.0 and 0.0
182   }
183   using BT = typename FTInfo<FT>::orig_bits_type;
184   static_assert(sizeof(FT) == sizeof(BT), "not implemented");
185   static_assert(sizeof(BT) <= 64, "not implemented");
186   BT v1_bits;
187   __builtin_memcpy(&v1_bits, &v1, sizeof(BT));
188   BT v2_bits;
189   __builtin_memcpy(&v2_bits, &v2, sizeof(BT));
190   // Check whether the signs differ. IEEE-754 float types always store the sign
191   // in the most significant bit. NaNs and infinities are handled by the calling
192   // code.
193   constexpr BT kSignMask = BT{1} << (CHAR_BIT * sizeof(BT) - 1);
194   if ((v1_bits ^ v2_bits) & kSignMask) {
195     // Signs differ. We can get the ULPs as `getULPDiff(negative_number, -0.0)
196     // + getULPDiff(0.0, positive_number)`.
197     if (v1_bits & kSignMask) {
198       return GetULPDiffBits<BT>(v1_bits, kSignMask) +
199              GetULPDiffBits<BT>(0, v2_bits);
200     } else {
201       return GetULPDiffBits<BT>(v2_bits, kSignMask) +
202              GetULPDiffBits<BT>(0, v1_bits);
203     }
204   }
205   return GetULPDiffBits(v1_bits, v2_bits);
206 }
207 
208 // FIXME: This needs mor work: Because there is no 80-bit integer type, we have
209 // to go through __uint128_t. Therefore the assumptions about the sign bit do
210 // not hold.
211 template <> inline double GetULPDiff(long double v1, long double v2) {
212   using BT = __uint128_t;
213   BT v1_bits = 0;
214   __builtin_memcpy(&v1_bits, &v1, sizeof(long double));
215   BT v2_bits = 0;
216   __builtin_memcpy(&v2_bits, &v2, sizeof(long double));
217   if ((v1_bits ^ v2_bits) & (BT{1} << (CHAR_BIT * sizeof(BT) - 1)))
218     return v1 == v2 ? __sanitizer::u64{0} : kMaxULPDiff; // Signs differ.
219   // If the integer representations of two same-sign floats are subtracted then
220   // the absolute value of the result is equal to one plus the number of
221   // representable floats between them.
222   BT diff = v1_bits >= v2_bits ? v1_bits - v2_bits : v2_bits - v1_bits;
223   return diff >= kMaxULPDiff ? kMaxULPDiff : diff;
224 }
225 
226 } // end namespace __nsan
227 
228 #endif // NSAN_H
229