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).
GetShadowAddrFor(u8 * Ptr)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).
GetShadowAddrFor(const u8 * Ptr)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).
GetShadowTypeAddrFor(u8 * Ptr)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).
GetShadowTypeAddrFor(const u8 * Ptr)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