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