xref: /llvm-project/compiler-rt/lib/nsan/nsan.h (revision 652707a6457eeb3927a1fe82e6b2cbc2a1fa22f5)
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