xref: /freebsd/contrib/llvm-project/compiler-rt/lib/nsan/nsan.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- nsan.cc -----------------------------------------------------------===//
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 // NumericalStabilitySanitizer runtime.
10 //
11 // This implements:
12 //  - The public nsan interface (include/sanitizer/nsan_interface.h).
13 //  - The private nsan interface (./nsan.h).
14 //  - The internal instrumentation interface. These are function emitted by the
15 //    instrumentation pass:
16 //        * __nsan_get_shadow_ptr_for_{float,double,longdouble}_load
17 //          These return the shadow memory pointer for loading the shadow value,
18 //          after checking that the types are consistent. If the types are not
19 //          consistent, returns nullptr.
20 //        * __nsan_get_shadow_ptr_for_{float,double,longdouble}_store
21 //          Sets the shadow types appropriately and returns the shadow memory
22 //          pointer for storing the shadow value.
23 //        * __nsan_internal_check_{float,double,long double}_{f,d,l} checks the
24 //          accuracy of a value against its shadow and emits a warning depending
25 //          on the runtime configuration. The middle part indicates the type of
26 //          the application value, the suffix (f,d,l) indicates the type of the
27 //          shadow, and depends on the instrumentation configuration.
28 //        * __nsan_fcmp_fail_* emits a warning for an fcmp instruction whose
29 //          corresponding shadow fcmp result differs.
30 //
31 //===----------------------------------------------------------------------===//
32 
33 #include <assert.h>
34 #include <math.h>
35 #include <stdint.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 
39 #include "sanitizer_common/sanitizer_atomic.h"
40 #include "sanitizer_common/sanitizer_common.h"
41 #include "sanitizer_common/sanitizer_libc.h"
42 #include "sanitizer_common/sanitizer_report_decorator.h"
43 #include "sanitizer_common/sanitizer_stacktrace.h"
44 #include "sanitizer_common/sanitizer_symbolizer.h"
45 
46 #include "nsan/nsan.h"
47 #include "nsan/nsan_flags.h"
48 #include "nsan/nsan_stats.h"
49 #include "nsan/nsan_suppressions.h"
50 
51 using namespace __sanitizer;
52 using namespace __nsan;
53 
54 constexpr int kMaxVectorWidth = 8;
55 
56 // When copying application memory, we also copy its shadow and shadow type.
57 // FIXME: We could provide fixed-size versions that would nicely
58 // vectorize for known sizes.
59 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_copy_values(const u8 * daddr,const u8 * saddr,uptr size)60 __nsan_copy_values(const u8 *daddr, const u8 *saddr, uptr size) {
61   internal_memmove((void *)GetShadowTypeAddrFor(daddr),
62                    GetShadowTypeAddrFor(saddr), size);
63   internal_memmove((void *)GetShadowAddrFor(daddr), GetShadowAddrFor(saddr),
64                    size * kShadowScale);
65 }
66 
67 // FIXME: We could provide fixed-size versions that would nicely
68 // vectorize for known sizes.
69 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_set_value_unknown(const u8 * addr,uptr size)70 __nsan_set_value_unknown(const u8 *addr, uptr size) {
71   internal_memset((void *)GetShadowTypeAddrFor(addr), 0, size);
72 }
73 
74 
75 const char *FTInfo<float>::kCppTypeName = "float";
76 const char *FTInfo<double>::kCppTypeName = "double";
77 const char *FTInfo<long double>::kCppTypeName = "long double";
78 const char *FTInfo<__float128>::kCppTypeName = "__float128";
79 
80 const char FTInfo<float>::kTypePattern[sizeof(float)];
81 const char FTInfo<double>::kTypePattern[sizeof(double)];
82 const char FTInfo<long double>::kTypePattern[sizeof(long double)];
83 
84 // Helper for __nsan_dump_shadow_mem: Reads the value at address `ptr`,
85 // identified by its type id.
86 template <typename ShadowFT>
ReadShadowInternal(const u8 * ptr)87 static __float128 ReadShadowInternal(const u8 *ptr) {
88   ShadowFT Shadow;
89   __builtin_memcpy(&Shadow, ptr, sizeof(Shadow));
90   return Shadow;
91 }
92 
ReadShadow(const u8 * ptr,const char ShadowTypeId)93 static __float128 ReadShadow(const u8 *ptr, const char ShadowTypeId) {
94   switch (ShadowTypeId) {
95   case 'd':
96     return ReadShadowInternal<double>(ptr);
97   case 'l':
98     return ReadShadowInternal<long double>(ptr);
99   case 'q':
100     return ReadShadowInternal<__float128>(ptr);
101   default:
102     return 0.0;
103   }
104 }
105 
106 namespace {
107 class Decorator : public __sanitizer::SanitizerCommonDecorator {
108 public:
Decorator()109   Decorator() : SanitizerCommonDecorator() {}
Warning()110   const char *Warning() { return Red(); }
Name()111   const char *Name() { return Green(); }
End()112   const char *End() { return Default(); }
113 };
114 
115 // Workaround for the fact that Printf() does not support floats.
116 struct PrintBuffer {
117   char Buffer[64];
118 };
119 template <typename FT> struct FTPrinter {};
120 
121 template <> struct FTPrinter<double> {
dec__anon36c45c920111::FTPrinter122   static PrintBuffer dec(double value) {
123     PrintBuffer result;
124     snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20f", value);
125     return result;
126   }
hex__anon36c45c920111::FTPrinter127   static PrintBuffer hex(double value) {
128     PrintBuffer result;
129     snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20a", value);
130     return result;
131   }
132 };
133 
134 template <> struct FTPrinter<float> : FTPrinter<double> {};
135 
136 template <> struct FTPrinter<long double> {
dec__anon36c45c920111::FTPrinter137   static PrintBuffer dec(long double value) {
138     PrintBuffer result;
139     snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20Lf", value);
140     return result;
141   }
hex__anon36c45c920111::FTPrinter142   static PrintBuffer hex(long double value) {
143     PrintBuffer result;
144     snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20La", value);
145     return result;
146   }
147 };
148 
149 // FIXME: print with full precision.
150 template <> struct FTPrinter<__float128> : FTPrinter<long double> {};
151 
152 // This is a template so that there are no implicit conversions.
153 template <typename FT> inline FT ftAbs(FT v);
154 
ftAbs(long double v)155 template <> inline long double ftAbs(long double v) { return fabsl(v); }
ftAbs(double v)156 template <> inline double ftAbs(double v) { return fabs(v); }
157 
158 // We don't care about nans.
159 // std::abs(__float128) code is suboptimal and generates a function call to
160 // __getf2().
ftAbs(FT v)161 template <typename FT> inline FT ftAbs(FT v) { return v >= FT{0} ? v : -v; }
162 
163 template <typename FT1, typename FT2, bool Enable> struct LargestFTImpl {
164   using type = FT2;
165 };
166 
167 template <typename FT1, typename FT2> struct LargestFTImpl<FT1, FT2, true> {
168   using type = FT1;
169 };
170 
171 template <typename FT1, typename FT2>
172 using LargestFT =
173     typename LargestFTImpl<FT1, FT2, (sizeof(FT1) > sizeof(FT2))>::type;
174 
max(T a,T b)175 template <typename T> T max(T a, T b) { return a < b ? b : a; }
176 
177 } // end anonymous namespace
178 
UnwindImpl(uptr pc,uptr bp,void * context,bool request_fast,u32 max_depth)179 void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
180                                                  void *context,
181                                                  bool request_fast,
182                                                  u32 max_depth) {
183   using namespace __nsan;
184   return Unwind(max_depth, pc, bp, context, 0, 0, false);
185 }
186 
__nsan_print_accumulated_stats()187 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_print_accumulated_stats() {
188   if (nsan_stats)
189     nsan_stats->Print();
190 }
191 
NsanAtexit()192 static void NsanAtexit() {
193   Printf("Numerical Sanitizer exit stats:\n");
194   __nsan_print_accumulated_stats();
195   nsan_stats = nullptr;
196 }
197 
198 // The next three functions return a pointer for storing a shadow value for `n`
199 // values, after setting the shadow types. We return the pointer instead of
200 // storing ourselves because it avoids having to rely on the calling convention
201 // around long double being the same for nsan and the target application.
202 // We have to have 3 versions because we need to know which type we are storing
203 // since we are setting the type shadow memory.
getShadowPtrForStore(u8 * store_addr,uptr n)204 template <typename FT> static u8 *getShadowPtrForStore(u8 *store_addr, uptr n) {
205   unsigned char *shadow_type = GetShadowTypeAddrFor(store_addr);
206   for (uptr i = 0; i < n; ++i) {
207     __builtin_memcpy(shadow_type + i * sizeof(FT), FTInfo<FT>::kTypePattern,
208                      sizeof(FTInfo<FT>::kTypePattern));
209   }
210   return GetShadowAddrFor(store_addr);
211 }
212 
213 extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 *
__nsan_get_shadow_ptr_for_float_store(u8 * store_addr,uptr n)214 __nsan_get_shadow_ptr_for_float_store(u8 *store_addr, uptr n) {
215   return getShadowPtrForStore<float>(store_addr, n);
216 }
217 
218 extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 *
__nsan_get_shadow_ptr_for_double_store(u8 * store_addr,uptr n)219 __nsan_get_shadow_ptr_for_double_store(u8 *store_addr, uptr n) {
220   return getShadowPtrForStore<double>(store_addr, n);
221 }
222 
223 extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 *
__nsan_get_shadow_ptr_for_longdouble_store(u8 * store_addr,uptr n)224 __nsan_get_shadow_ptr_for_longdouble_store(u8 *store_addr, uptr n) {
225   return getShadowPtrForStore<long double>(store_addr, n);
226 }
227 
IsValidShadowType(const u8 * shadow_type)228 template <typename FT> static bool IsValidShadowType(const u8 *shadow_type) {
229   return __builtin_memcmp(shadow_type, FTInfo<FT>::kTypePattern, sizeof(FT)) ==
230          0;
231 }
232 
IsZero(const T * ptr)233 template <int kSize, typename T> static bool IsZero(const T *ptr) {
234   constexpr const char kZeros[kSize] = {}; // Zero initialized.
235   return __builtin_memcmp(ptr, kZeros, kSize) == 0;
236 }
237 
IsUnknownShadowType(const u8 * shadow_type)238 template <typename FT> static bool IsUnknownShadowType(const u8 *shadow_type) {
239   return IsZero<sizeof(FTInfo<FT>::kTypePattern)>(shadow_type);
240 }
241 
242 // The three folowing functions check that the address stores a complete
243 // shadow value of the given type and return a pointer for loading.
244 // They return nullptr if the type of the value is unknown or incomplete.
245 template <typename FT>
getShadowPtrForLoad(const u8 * load_addr,uptr n)246 static const u8 *getShadowPtrForLoad(const u8 *load_addr, uptr n) {
247   const u8 *const shadow_type = GetShadowTypeAddrFor(load_addr);
248   for (uptr i = 0; i < n; ++i) {
249     if (!IsValidShadowType<FT>(shadow_type + i * sizeof(FT))) {
250       // If loadtracking stats are enabled, log loads with invalid types
251       // (tampered with through type punning).
252       if (flags().enable_loadtracking_stats) {
253         if (IsUnknownShadowType<FT>(shadow_type + i * sizeof(FT))) {
254           // Warn only if the value is non-zero. Zero is special because
255           // applications typically initialize large buffers to zero in an
256           // untyped way.
257           if (!IsZero<sizeof(FT)>(load_addr)) {
258             GET_CALLER_PC_BP;
259             nsan_stats->AddUnknownLoadTrackingEvent(pc, bp);
260           }
261         } else {
262           GET_CALLER_PC_BP;
263           nsan_stats->AddInvalidLoadTrackingEvent(pc, bp);
264         }
265       }
266       return nullptr;
267     }
268   }
269   return GetShadowAddrFor(load_addr);
270 }
271 
272 extern "C" SANITIZER_INTERFACE_ATTRIBUTE const u8 *
__nsan_get_shadow_ptr_for_float_load(const u8 * load_addr,uptr n)273 __nsan_get_shadow_ptr_for_float_load(const u8 *load_addr, uptr n) {
274   return getShadowPtrForLoad<float>(load_addr, n);
275 }
276 
277 extern "C" SANITIZER_INTERFACE_ATTRIBUTE const u8 *
__nsan_get_shadow_ptr_for_double_load(const u8 * load_addr,uptr n)278 __nsan_get_shadow_ptr_for_double_load(const u8 *load_addr, uptr n) {
279   return getShadowPtrForLoad<double>(load_addr, n);
280 }
281 
282 extern "C" SANITIZER_INTERFACE_ATTRIBUTE const u8 *
__nsan_get_shadow_ptr_for_longdouble_load(const u8 * load_addr,uptr n)283 __nsan_get_shadow_ptr_for_longdouble_load(const u8 *load_addr, uptr n) {
284   return getShadowPtrForLoad<long double>(load_addr, n);
285 }
286 
287 // Returns the raw shadow pointer. The returned pointer should be considered
288 // opaque.
289 extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 *
__nsan_internal_get_raw_shadow_ptr(const u8 * addr)290 __nsan_internal_get_raw_shadow_ptr(const u8 *addr) {
291   return GetShadowAddrFor(const_cast<u8 *>(addr));
292 }
293 
294 // Returns the raw shadow type pointer. The returned pointer should be
295 // considered opaque.
296 extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 *
__nsan_internal_get_raw_shadow_type_ptr(const u8 * addr)297 __nsan_internal_get_raw_shadow_type_ptr(const u8 *addr) {
298   return reinterpret_cast<u8 *>(GetShadowTypeAddrFor(const_cast<u8 *>(addr)));
299 }
300 
getValueType(u8 c)301 static ValueType getValueType(u8 c) { return static_cast<ValueType>(c & 0x3); }
302 
getValuePos(u8 c)303 static int getValuePos(u8 c) { return c >> kValueSizeSizeBits; }
304 
305 // Checks the consistency of the value types at the given type pointer.
306 // If the value is inconsistent, returns ValueType::kUnknown. Else, return the
307 // consistent type.
308 template <typename FT>
checkValueConsistency(const u8 * shadow_type)309 static bool checkValueConsistency(const u8 *shadow_type) {
310   const int pos = getValuePos(*shadow_type);
311   // Check that all bytes from the start of the value are ordered.
312   for (uptr i = 0; i < sizeof(FT); ++i) {
313     const u8 T = *(shadow_type - pos + i);
314     if (!(getValueType(T) == FTInfo<FT>::kValueType && getValuePos(T) == i))
315       return false;
316   }
317   return true;
318 }
319 
320 // The instrumentation automatically appends `shadow_value_type_ids`, see
321 // maybeAddSuffixForNsanInterface.
322 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_dump_shadow_mem(const u8 * addr,size_t size_bytes,size_t bytes_per_line,size_t shadow_value_type_ids)323 __nsan_dump_shadow_mem(const u8 *addr, size_t size_bytes, size_t bytes_per_line,
324                        size_t shadow_value_type_ids) {
325   const u8 *const shadow_type = GetShadowTypeAddrFor(addr);
326   const u8 *const shadow = GetShadowAddrFor(addr);
327 
328   constexpr int kMaxNumDecodedValues = 16;
329   __float128 decoded_values[kMaxNumDecodedValues];
330   int num_decoded_values = 0;
331   if (bytes_per_line > 4 * kMaxNumDecodedValues)
332     bytes_per_line = 4 * kMaxNumDecodedValues;
333 
334   // We keep track of the current type and position as we go.
335   ValueType LastValueTy = kUnknownValueType;
336   int LastPos = -1;
337   size_t Offset = 0;
338   for (size_t R = 0; R < (size_bytes + bytes_per_line - 1) / bytes_per_line;
339        ++R) {
340     printf("%p:    ", (void *)(addr + R * bytes_per_line));
341     for (size_t C = 0; C < bytes_per_line && Offset < size_bytes; ++C) {
342       const ValueType ValueTy = getValueType(shadow_type[Offset]);
343       const int pos = getValuePos(shadow_type[Offset]);
344       if (ValueTy == LastValueTy && pos == LastPos + 1) {
345         ++LastPos;
346       } else {
347         LastValueTy = ValueTy;
348         LastPos = pos == 0 ? 0 : -1;
349       }
350 
351       switch (ValueTy) {
352       case kUnknownValueType:
353         printf("__ ");
354         break;
355       case kFloatValueType:
356         printf("f%x ", pos);
357         if (LastPos == sizeof(float) - 1) {
358           decoded_values[num_decoded_values] =
359               ReadShadow(shadow + kShadowScale * (Offset + 1 - sizeof(float)),
360                          static_cast<char>(shadow_value_type_ids & 0xff));
361           ++num_decoded_values;
362         }
363         break;
364       case kDoubleValueType:
365         printf("d%x ", pos);
366         if (LastPos == sizeof(double) - 1) {
367           decoded_values[num_decoded_values] = ReadShadow(
368               shadow + kShadowScale * (Offset + 1 - sizeof(double)),
369               static_cast<char>((shadow_value_type_ids >> 8) & 0xff));
370           ++num_decoded_values;
371         }
372         break;
373       case kFp80ValueType:
374         printf("l%x ", pos);
375         if (LastPos == sizeof(long double) - 1) {
376           decoded_values[num_decoded_values] = ReadShadow(
377               shadow + kShadowScale * (Offset + 1 - sizeof(long double)),
378               static_cast<char>((shadow_value_type_ids >> 16) & 0xff));
379           ++num_decoded_values;
380         }
381         break;
382       }
383       ++Offset;
384     }
385     for (int i = 0; i < num_decoded_values; ++i) {
386       printf("  (%s)", FTPrinter<__float128>::dec(decoded_values[i]).Buffer);
387     }
388     num_decoded_values = 0;
389     printf("\n");
390   }
391 }
392 
393 alignas(16) SANITIZER_INTERFACE_ATTRIBUTE
394     thread_local uptr __nsan_shadow_ret_tag = 0;
395 
396 alignas(16) SANITIZER_INTERFACE_ATTRIBUTE
397     thread_local char __nsan_shadow_ret_ptr[kMaxVectorWidth *
398                                             sizeof(__float128)];
399 
400 alignas(16) SANITIZER_INTERFACE_ATTRIBUTE
401     thread_local uptr __nsan_shadow_args_tag = 0;
402 
403 // Maximum number of args. This should be enough for anyone (tm). An alternate
404 // scheme is to have the generated code create an alloca and make
405 // __nsan_shadow_args_ptr point ot the alloca.
406 constexpr const int kMaxNumArgs = 128;
407 alignas(16) SANITIZER_INTERFACE_ATTRIBUTE
408     thread_local char __nsan_shadow_args_ptr[kMaxVectorWidth * kMaxNumArgs *
409                                              sizeof(__float128)];
410 
411 enum ContinuationType { // Keep in sync with instrumentation pass.
412   kContinueWithShadow = 0,
413   kResumeFromValue = 1,
414 };
415 
416 // Checks the consistency between application and shadow value. Returns true
417 // when the instrumented code should resume computations from the original value
418 // rather than the shadow value. This prevents one error to propagate to all
419 // subsequent operations. This behaviour is tunable with flags.
420 template <typename FT, typename ShadowFT>
checkFT(const FT value,ShadowFT Shadow,CheckTypeT CheckType,uptr CheckArg)421 int32_t checkFT(const FT value, ShadowFT Shadow, CheckTypeT CheckType,
422                 uptr CheckArg) {
423   // We do all comparisons in the InternalFT domain, which is the largest FT
424   // type.
425   using InternalFT = LargestFT<FT, ShadowFT>;
426   const InternalFT check_value = value;
427   const InternalFT check_shadow = Shadow;
428 
429   // See this article for an interesting discussion of how to compare floats:
430   // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
431   static constexpr const FT Eps = FTInfo<FT>::kEpsilon;
432 
433   const InternalFT abs_err = ftAbs(check_value - check_shadow);
434 
435   if (flags().enable_check_stats) {
436     GET_CALLER_PC_BP;
437     // We are re-computing `largest` here because this is a cold branch, and we
438     // want to avoid having to move the computation of `largest` before the
439     // absolute value check when this branch is not taken.
440     const InternalFT largest = max(ftAbs(check_value), ftAbs(check_shadow));
441     nsan_stats->AddCheck(CheckType, pc, bp, abs_err / largest);
442   }
443 
444   // Note: writing the comparison that way ensures that when `abs_err` is Nan
445   // (value and shadow are inf or -inf), we pass the test.
446   if (!(abs_err >= flags().cached_absolute_error_threshold))
447     return kContinueWithShadow;
448 
449   const InternalFT largest = max(ftAbs(check_value), ftAbs(check_shadow));
450   if (abs_err * (1ull << flags().log2_max_relative_error) <= largest)
451     return kContinueWithShadow; // No problem here.
452 
453   if (!flags().disable_warnings) {
454     GET_CALLER_PC_BP;
455     BufferedStackTrace stack;
456     stack.Unwind(pc, bp, nullptr, false);
457     if (GetSuppressionForStack(&stack, CheckKind::Consistency)) {
458       // FIXME: optionally print.
459       return flags().resume_after_suppression ? kResumeFromValue
460                                               : kContinueWithShadow;
461     }
462 
463     Decorator D;
464     Printf("%s", D.Warning());
465     // Printf does not support float formatting.
466     char RelErrBuf[64] = "inf";
467     if (largest > Eps) {
468       snprintf(RelErrBuf, sizeof(RelErrBuf) - 1, "%.20Lf%% (2^%.0Lf epsilons)",
469                static_cast<long double>(100.0 * abs_err / largest),
470                log2l(static_cast<long double>(abs_err / largest / Eps)));
471     }
472     char ulp_err_buf[128] = "";
473     const double shadow_ulp_diff = GetULPDiff(check_value, check_shadow);
474     if (shadow_ulp_diff != kMaxULPDiff) {
475       // This is the ULP diff in the internal domain. The user actually cares
476       // about that in the original domain.
477       const double ulp_diff =
478           shadow_ulp_diff / (u64{1} << (FTInfo<InternalFT>::kMantissaBits -
479                                         FTInfo<FT>::kMantissaBits));
480       snprintf(ulp_err_buf, sizeof(ulp_err_buf) - 1,
481                "(%.0f ULPs == %.1f digits == %.1f bits)", ulp_diff,
482                log10(ulp_diff), log2(ulp_diff));
483     }
484     Printf("WARNING: NumericalStabilitySanitizer: inconsistent shadow results");
485     switch (CheckType) {
486     case CheckTypeT::kUnknown:
487     case CheckTypeT::kFcmp:
488     case CheckTypeT::kMaxCheckType:
489       break;
490     case CheckTypeT::kRet:
491       Printf(" while checking return value");
492       break;
493     case CheckTypeT::kArg:
494       Printf(" while checking call argument #%d", static_cast<int>(CheckArg));
495       break;
496     case CheckTypeT::kLoad:
497       Printf(
498           " while checking load from address 0x%lx. This is due to incorrect "
499           "shadow memory tracking, typically due to uninstrumented code "
500           "writing to memory.",
501           CheckArg);
502       break;
503     case CheckTypeT::kStore:
504       Printf(" while checking store to address 0x%lx", CheckArg);
505       break;
506     case CheckTypeT::kInsert:
507       Printf(" while checking vector insert");
508       break;
509     case CheckTypeT::kUser:
510       Printf(" in user-initiated check");
511       break;
512     }
513     using ValuePrinter = FTPrinter<FT>;
514     using ShadowPrinter = FTPrinter<ShadowFT>;
515     Printf("%s", D.Default());
516 
517     Printf("\n"
518            "%-12s precision  (native): dec: %s  hex: %s\n"
519            "%-12s precision  (shadow): dec: %s  hex: %s\n"
520            "shadow truncated to %-12s: dec: %s  hex: %s\n"
521            "Relative error: %s\n"
522            "Absolute error: %s\n"
523            "%s\n",
524            FTInfo<FT>::kCppTypeName, ValuePrinter::dec(value).Buffer,
525            ValuePrinter::hex(value).Buffer, FTInfo<ShadowFT>::kCppTypeName,
526            ShadowPrinter::dec(Shadow).Buffer, ShadowPrinter::hex(Shadow).Buffer,
527            FTInfo<FT>::kCppTypeName, ValuePrinter::dec(Shadow).Buffer,
528            ValuePrinter::hex(Shadow).Buffer, RelErrBuf,
529            ValuePrinter::hex(abs_err).Buffer, ulp_err_buf);
530     stack.Print();
531   }
532 
533   if (flags().enable_warning_stats) {
534     GET_CALLER_PC_BP;
535     nsan_stats->AddWarning(CheckType, pc, bp, abs_err / largest);
536   }
537 
538   if (flags().halt_on_error) {
539     if (common_flags()->abort_on_error)
540       Printf("ABORTING\n");
541     else
542       Printf("Exiting\n");
543     Die();
544   }
545   return flags().resume_after_warning ? kResumeFromValue : kContinueWithShadow;
546 }
547 
__nsan_internal_check_float_d(float value,double shadow,int32_t check_type,uptr check_arg)548 extern "C" SANITIZER_INTERFACE_ATTRIBUTE int32_t __nsan_internal_check_float_d(
549     float value, double shadow, int32_t check_type, uptr check_arg) {
550   return checkFT(value, shadow, static_cast<CheckTypeT>(check_type), check_arg);
551 }
552 
__nsan_internal_check_double_l(double value,long double shadow,int32_t check_type,uptr check_arg)553 extern "C" SANITIZER_INTERFACE_ATTRIBUTE int32_t __nsan_internal_check_double_l(
554     double value, long double shadow, int32_t check_type, uptr check_arg) {
555   return checkFT(value, shadow, static_cast<CheckTypeT>(check_type), check_arg);
556 }
557 
__nsan_internal_check_double_q(double value,__float128 shadow,int32_t check_type,uptr check_arg)558 extern "C" SANITIZER_INTERFACE_ATTRIBUTE int32_t __nsan_internal_check_double_q(
559     double value, __float128 shadow, int32_t check_type, uptr check_arg) {
560   return checkFT(value, shadow, static_cast<CheckTypeT>(check_type), check_arg);
561 }
562 
563 extern "C" SANITIZER_INTERFACE_ATTRIBUTE int32_t
__nsan_internal_check_longdouble_q(long double value,__float128 shadow,int32_t check_type,uptr check_arg)564 __nsan_internal_check_longdouble_q(long double value, __float128 shadow,
565                                    int32_t check_type, uptr check_arg) {
566   return checkFT(value, shadow, static_cast<CheckTypeT>(check_type), check_arg);
567 }
568 
GetTruthValueName(bool v)569 static const char *GetTruthValueName(bool v) { return v ? "true" : "false"; }
570 
571 // This uses the same values as CmpInst::Predicate.
GetPredicateName(int v)572 static const char *GetPredicateName(int v) {
573   switch (v) {
574   case 0:
575     return "(false)";
576   case 1:
577     return "==";
578   case 2:
579     return ">";
580   case 3:
581     return ">=";
582   case 4:
583     return "<";
584   case 5:
585     return "<=";
586   case 6:
587     return "!=";
588   case 7:
589     return "(ordered)";
590   case 8:
591     return "(unordered)";
592   case 9:
593     return "==";
594   case 10:
595     return ">";
596   case 11:
597     return ">=";
598   case 12:
599     return "<";
600   case 13:
601     return "<=";
602   case 14:
603     return "!=";
604   case 15:
605     return "(true)";
606   }
607   return "??";
608 }
609 
610 template <typename FT, typename ShadowFT>
fCmpFailFT(const FT Lhs,const FT Rhs,ShadowFT LhsShadow,ShadowFT RhsShadow,int Predicate,bool result,bool ShadowResult)611 void fCmpFailFT(const FT Lhs, const FT Rhs, ShadowFT LhsShadow,
612                 ShadowFT RhsShadow, int Predicate, bool result,
613                 bool ShadowResult) {
614   if (result == ShadowResult) {
615     // When a vector comparison fails, we fail each element of the comparison
616     // to simplify instrumented code. Skip elements where the shadow comparison
617     // gave the same result as the original one.
618     return;
619   }
620 
621   GET_CALLER_PC_BP;
622   BufferedStackTrace stack;
623   stack.Unwind(pc, bp, nullptr, false);
624 
625   if (GetSuppressionForStack(&stack, CheckKind::Fcmp)) {
626     // FIXME: optionally print.
627     return;
628   }
629 
630   if (flags().enable_warning_stats)
631     nsan_stats->AddWarning(CheckTypeT::kFcmp, pc, bp, 0.0);
632 
633   if (flags().disable_warnings)
634     return;
635 
636   // FIXME: ideally we would print the shadow value as FP128. Right now because
637   // we truncate to long double we can sometimes see stuff like:
638   // shadow <value> == <value> (false)
639   using ValuePrinter = FTPrinter<FT>;
640   using ShadowPrinter = FTPrinter<ShadowFT>;
641   Decorator D;
642   const char *const PredicateName = GetPredicateName(Predicate);
643   Printf("%s", D.Warning());
644   Printf("WARNING: NumericalStabilitySanitizer: floating-point comparison "
645          "results depend on precision\n");
646   Printf("%s", D.Default());
647   Printf("%-12s precision dec (native): %s %s %s (%s)\n"
648          "%-12s precision dec (shadow): %s %s %s (%s)\n"
649          "%-12s precision hex (native): %s %s %s (%s)\n"
650          "%-12s precision hex (shadow): %s %s %s (%s)\n"
651          "%s",
652          // Native, decimal.
653          FTInfo<FT>::kCppTypeName, ValuePrinter::dec(Lhs).Buffer, PredicateName,
654          ValuePrinter::dec(Rhs).Buffer, GetTruthValueName(result),
655          // Shadow, decimal
656          FTInfo<ShadowFT>::kCppTypeName, ShadowPrinter::dec(LhsShadow).Buffer,
657          PredicateName, ShadowPrinter::dec(RhsShadow).Buffer,
658          GetTruthValueName(ShadowResult),
659          // Native, hex.
660          FTInfo<FT>::kCppTypeName, ValuePrinter::hex(Lhs).Buffer, PredicateName,
661          ValuePrinter::hex(Rhs).Buffer, GetTruthValueName(result),
662          // Shadow, hex
663          FTInfo<ShadowFT>::kCppTypeName, ShadowPrinter::hex(LhsShadow).Buffer,
664          PredicateName, ShadowPrinter::hex(RhsShadow).Buffer,
665          GetTruthValueName(ShadowResult), D.End());
666   stack.Print();
667   if (flags().halt_on_error) {
668     Printf("Exiting\n");
669     Die();
670   }
671 }
672 
673 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_fcmp_fail_float_d(float lhs,float rhs,double lhs_shadow,double rhs_shadow,int predicate,bool result,bool shadow_result)674 __nsan_fcmp_fail_float_d(float lhs, float rhs, double lhs_shadow,
675                          double rhs_shadow, int predicate, bool result,
676                          bool shadow_result) {
677   fCmpFailFT(lhs, rhs, lhs_shadow, rhs_shadow, predicate, result,
678              shadow_result);
679 }
680 
681 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_fcmp_fail_double_q(double lhs,double rhs,__float128 lhs_shadow,__float128 rhs_shadow,int predicate,bool result,bool shadow_result)682 __nsan_fcmp_fail_double_q(double lhs, double rhs, __float128 lhs_shadow,
683                           __float128 rhs_shadow, int predicate, bool result,
684                           bool shadow_result) {
685   fCmpFailFT(lhs, rhs, lhs_shadow, rhs_shadow, predicate, result,
686              shadow_result);
687 }
688 
689 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_fcmp_fail_double_l(double lhs,double rhs,long double lhs_shadow,long double rhs_shadow,int predicate,bool result,bool shadow_result)690 __nsan_fcmp_fail_double_l(double lhs, double rhs, long double lhs_shadow,
691                           long double rhs_shadow, int predicate, bool result,
692                           bool shadow_result) {
693   fCmpFailFT(lhs, rhs, lhs_shadow, rhs_shadow, predicate, result,
694              shadow_result);
695 }
696 
697 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_fcmp_fail_longdouble_q(long double lhs,long double rhs,__float128 lhs_shadow,__float128 rhs_shadow,int predicate,bool result,bool shadow_result)698 __nsan_fcmp_fail_longdouble_q(long double lhs, long double rhs,
699                               __float128 lhs_shadow, __float128 rhs_shadow,
700                               int predicate, bool result, bool shadow_result) {
701   fCmpFailFT(lhs, rhs, lhs_shadow, rhs_shadow, predicate, result,
702              shadow_result);
703 }
704 
checkFTFromShadowStack(const FT value)705 template <typename FT> void checkFTFromShadowStack(const FT value) {
706   // Get the shadow 2FT value from the shadow stack. Note that
707   // __nsan_check_{float,double,long double} is a function like any other, so
708   // the instrumentation will have placed the shadow value on the shadow stack.
709   using ShadowFT = typename FTInfo<FT>::shadow_type;
710   ShadowFT Shadow;
711   __builtin_memcpy(&Shadow, __nsan_shadow_args_ptr, sizeof(ShadowFT));
712   checkFT(value, Shadow, CheckTypeT::kUser, 0);
713 }
714 
715 // FIXME: Add suffixes and let the instrumentation pass automatically add
716 // suffixes.
__nsan_check_float(float value)717 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_check_float(float value) {
718   assert(__nsan_shadow_args_tag == (uptr)&__nsan_check_float &&
719          "__nsan_check_float called from non-instrumented function");
720   checkFTFromShadowStack(value);
721 }
722 
723 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_check_double(double value)724 __nsan_check_double(double value) {
725   assert(__nsan_shadow_args_tag == (uptr)&__nsan_check_double &&
726          "__nsan_check_double called from non-instrumented function");
727   checkFTFromShadowStack(value);
728 }
729 
730 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_check_longdouble(long double value)731 __nsan_check_longdouble(long double value) {
732   assert(__nsan_shadow_args_tag == (uptr)&__nsan_check_longdouble &&
733          "__nsan_check_longdouble called from non-instrumented function");
734   checkFTFromShadowStack(value);
735 }
736 
dumpFTFromShadowStack(const FT value)737 template <typename FT> static void dumpFTFromShadowStack(const FT value) {
738   // Get the shadow 2FT value from the shadow stack. Note that
739   // __nsan_dump_{float,double,long double} is a function like any other, so
740   // the instrumentation will have placed the shadow value on the shadow stack.
741   using ShadowFT = typename FTInfo<FT>::shadow_type;
742   ShadowFT shadow;
743   __builtin_memcpy(&shadow, __nsan_shadow_args_ptr, sizeof(ShadowFT));
744   using ValuePrinter = FTPrinter<FT>;
745   using ShadowPrinter = FTPrinter<typename FTInfo<FT>::shadow_type>;
746   printf("value  dec:%s hex:%s\n"
747          "shadow dec:%s hex:%s\n",
748          ValuePrinter::dec(value).Buffer, ValuePrinter::hex(value).Buffer,
749          ShadowPrinter::dec(shadow).Buffer, ShadowPrinter::hex(shadow).Buffer);
750 }
751 
__nsan_dump_float(float value)752 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_float(float value) {
753   assert(__nsan_shadow_args_tag == (uptr)&__nsan_dump_float &&
754          "__nsan_dump_float called from non-instrumented function");
755   dumpFTFromShadowStack(value);
756 }
757 
__nsan_dump_double(double value)758 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_double(double value) {
759   assert(__nsan_shadow_args_tag == (uptr)&__nsan_dump_double &&
760          "__nsan_dump_double called from non-instrumented function");
761   dumpFTFromShadowStack(value);
762 }
763 
764 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__nsan_dump_longdouble(long double value)765 __nsan_dump_longdouble(long double value) {
766   assert(__nsan_shadow_args_tag == (uptr)&__nsan_dump_longdouble &&
767          "__nsan_dump_longdouble called from non-instrumented function");
768   dumpFTFromShadowStack(value);
769 }
770 
__nsan_dump_shadow_ret()771 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_shadow_ret() {
772   printf("ret tag: %lx\n", __nsan_shadow_ret_tag);
773   double v;
774   __builtin_memcpy(&v, __nsan_shadow_ret_ptr, sizeof(double));
775   printf("double value: %f\n", v);
776   // FIXME: float128 value.
777 }
778 
__nsan_dump_shadow_args()779 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_shadow_args() {
780   printf("args tag: %lx\n", __nsan_shadow_args_tag);
781 }
782 
783 bool __nsan::nsan_initialized;
784 bool __nsan::nsan_init_is_running;
785 
__nsan_init()786 extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_init() {
787   CHECK(!nsan_init_is_running);
788   if (nsan_initialized)
789     return;
790   nsan_init_is_running = true;
791 
792   InitializeFlags();
793   InitializeSuppressions();
794   InitializePlatformEarly();
795 
796   DisableCoreDumperIfNecessary();
797 
798   if (!MmapFixedNoReserve(TypesAddr(), UnusedAddr() - TypesAddr()))
799     Die();
800 
801   InitializeInterceptors();
802 
803   InitializeStats();
804   if (flags().print_stats_on_exit)
805     Atexit(NsanAtexit);
806 
807   nsan_init_is_running = false;
808   nsan_initialized = true;
809 }
810