xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/nsan/nsan.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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