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