diff options
author | Fangrui Song <i@maskray.me> | 2024-06-20 00:46:10 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-20 00:46:10 -0700 |
commit | ef83c25b0e56438d1697138915273dc71b8acf82 (patch) | |
tree | 2fe8eab214814a7e8e8d8fc2e0adfd21fba468c1 | |
parent | 11344249e1e8360e75490733660ee1439d571228 (diff) | |
download | llvm-ef83c25b0e56438d1697138915273dc71b8acf82.zip llvm-ef83c25b0e56438d1697138915273dc71b8acf82.tar.gz llvm-ef83c25b0e56438d1697138915273dc71b8acf82.tar.bz2 |
[nsan] Fix style issue
The initial check-in of compiler-rt/lib/nsan #94322 has a lot of style
issues. Fix them before the history becomes more useful.
Pull Request: https://github.com/llvm/llvm-project/pull/96142
-rw-r--r-- | compiler-rt/lib/nsan/CMakeLists.txt | 10 | ||||
-rw-r--r-- | compiler-rt/lib/nsan/nsan.cpp (renamed from compiler-rt/lib/nsan/nsan.cc) | 345 | ||||
-rw-r--r-- | compiler-rt/lib/nsan/nsan.h | 68 | ||||
-rw-r--r-- | compiler-rt/lib/nsan/nsan_flags.cpp (renamed from compiler-rt/lib/nsan/nsan_flags.cc) | 11 | ||||
-rw-r--r-- | compiler-rt/lib/nsan/nsan_interceptors.cc | 364 | ||||
-rw-r--r-- | compiler-rt/lib/nsan/nsan_interceptors.cpp | 356 | ||||
-rw-r--r-- | compiler-rt/lib/nsan/nsan_stats.cc | 158 | ||||
-rw-r--r-- | compiler-rt/lib/nsan/nsan_stats.cpp | 157 | ||||
-rw-r--r-- | compiler-rt/lib/nsan/nsan_stats.h | 43 | ||||
-rw-r--r-- | compiler-rt/lib/nsan/nsan_suppressions.cc | 77 | ||||
-rw-r--r-- | compiler-rt/lib/nsan/nsan_suppressions.cpp | 73 | ||||
-rw-r--r-- | compiler-rt/lib/nsan/tests/NSanUnitTest.cpp | 48 |
12 files changed, 841 insertions, 869 deletions
diff --git a/compiler-rt/lib/nsan/CMakeLists.txt b/compiler-rt/lib/nsan/CMakeLists.txt index ae94c96..36c7b2b 100644 --- a/compiler-rt/lib/nsan/CMakeLists.txt +++ b/compiler-rt/lib/nsan/CMakeLists.txt @@ -3,11 +3,11 @@ add_compiler_rt_component(nsan) include_directories(..) set(NSAN_SOURCES - nsan.cc - nsan_flags.cc - nsan_interceptors.cc - nsan_stats.cc - nsan_suppressions.cc + nsan.cpp + nsan_flags.cpp + nsan_interceptors.cpp + nsan_stats.cpp + nsan_suppressions.cpp ) set(NSAN_HEADERS diff --git a/compiler-rt/lib/nsan/nsan.cc b/compiler-rt/lib/nsan/nsan.cpp index d0d29dd..f7b2ce2 100644 --- a/compiler-rt/lib/nsan/nsan.cc +++ b/compiler-rt/lib/nsan/nsan.cpp @@ -51,16 +51,16 @@ using namespace __sanitizer; using namespace __nsan; -static constexpr const int kMaxVectorWidth = 8; +constexpr int kMaxVectorWidth = 8; // When copying application memory, we also copy its shadow and shadow type. // FIXME: We could provide fixed-size versions that would nicely // vectorize for known sizes. extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_copy_values(const u8 *daddr, const u8 *saddr, uptr size) { - internal_memmove((void *)getShadowTypeAddrFor(daddr), - getShadowTypeAddrFor(saddr), size); - internal_memmove((void *)getShadowAddrFor(daddr), getShadowAddrFor(saddr), + internal_memmove((void *)GetShadowTypeAddrFor(daddr), + GetShadowTypeAddrFor(saddr), size); + internal_memmove((void *)GetShadowAddrFor(daddr), GetShadowAddrFor(saddr), size * kShadowScale); } @@ -68,10 +68,9 @@ __nsan_copy_values(const u8 *daddr, const u8 *saddr, uptr size) { // vectorize for known sizes. extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_set_value_unknown(const u8 *addr, uptr size) { - internal_memset((void *)getShadowTypeAddrFor(addr), 0, size); + internal_memset((void *)GetShadowTypeAddrFor(addr), 0, size); } -namespace __nsan { const char *FTInfo<float>::kCppTypeName = "float"; const char *FTInfo<double>::kCppTypeName = "double"; @@ -82,27 +81,29 @@ const char FTInfo<float>::kTypePattern[sizeof(float)]; const char FTInfo<double>::kTypePattern[sizeof(double)]; const char FTInfo<long double>::kTypePattern[sizeof(long double)]; -// Helper for __nsan_dump_shadow_mem: Reads the value at address `Ptr`, +// Helper for __nsan_dump_shadow_mem: Reads the value at address `ptr`, // identified by its type id. -template <typename ShadowFT> __float128 readShadowInternal(const u8 *Ptr) { +template <typename ShadowFT> +static __float128 ReadShadowInternal(const u8 *ptr) { ShadowFT Shadow; - __builtin_memcpy(&Shadow, Ptr, sizeof(Shadow)); + __builtin_memcpy(&Shadow, ptr, sizeof(Shadow)); return Shadow; } -__float128 readShadow(const u8 *Ptr, const char ShadowTypeId) { +static __float128 ReadShadow(const u8 *ptr, const char ShadowTypeId) { switch (ShadowTypeId) { case 'd': - return readShadowInternal<double>(Ptr); + return ReadShadowInternal<double>(ptr); case 'l': - return readShadowInternal<long double>(Ptr); + return ReadShadowInternal<long double>(ptr); case 'q': - return readShadowInternal<__float128>(Ptr); + return ReadShadowInternal<__float128>(ptr); default: return 0.0; } } +namespace { class Decorator : public __sanitizer::SanitizerCommonDecorator { public: Decorator() : SanitizerCommonDecorator() {} @@ -111,8 +112,6 @@ public: const char *End() { return Default(); } }; -namespace { - // Workaround for the fact that Printf() does not support floats. struct PrintBuffer { char Buffer[64]; @@ -120,30 +119,30 @@ struct PrintBuffer { template <typename FT> struct FTPrinter {}; template <> struct FTPrinter<double> { - static PrintBuffer dec(double Value) { - PrintBuffer Result; - snprintf(Result.Buffer, sizeof(Result.Buffer) - 1, "%.20f", Value); - return Result; + static PrintBuffer dec(double value) { + PrintBuffer result; + snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20f", value); + return result; } - static PrintBuffer hex(double Value) { - PrintBuffer Result; - snprintf(Result.Buffer, sizeof(Result.Buffer) - 1, "%.20a", Value); - return Result; + static PrintBuffer hex(double value) { + PrintBuffer result; + snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20a", value); + return result; } }; template <> struct FTPrinter<float> : FTPrinter<double> {}; template <> struct FTPrinter<long double> { - static PrintBuffer dec(long double Value) { - PrintBuffer Result; - snprintf(Result.Buffer, sizeof(Result.Buffer) - 1, "%.20Lf", Value); - return Result; + static PrintBuffer dec(long double value) { + PrintBuffer result; + snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20Lf", value); + return result; } - static PrintBuffer hex(long double Value) { - PrintBuffer Result; - snprintf(Result.Buffer, sizeof(Result.Buffer) - 1, "%.20La", Value); - return Result; + static PrintBuffer hex(long double value) { + PrintBuffer result; + snprintf(result.Buffer, sizeof(result.Buffer) - 1, "%.20La", value); + return result; } }; @@ -151,15 +150,15 @@ template <> struct FTPrinter<long double> { template <> struct FTPrinter<__float128> : FTPrinter<long double> {}; // This is a template so that there are no implicit conversions. -template <typename FT> inline FT ftAbs(FT V); +template <typename FT> inline FT ftAbs(FT v); -template <> inline long double ftAbs(long double V) { return fabsl(V); } -template <> inline double ftAbs(double V) { return fabs(V); } +template <> inline long double ftAbs(long double v) { return fabsl(v); } +template <> inline double ftAbs(double v) { return fabs(v); } // We don't care about nans. // std::abs(__float128) code is suboptimal and generates a function call to // __getf2(). -template <typename FT> inline FT ftAbs(FT V) { return V >= FT{0} ? V : -V; } +template <typename FT> inline FT ftAbs(FT v) { return v >= FT{0} ? v : -v; } template <typename FT1, typename FT2, bool Enable> struct LargestFTImpl { using type = FT2; @@ -177,8 +176,6 @@ template <typename T> T max(T a, T b) { return a < b ? b : a; } } // end anonymous namespace -} // end namespace __nsan - void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp, void *context, bool request_fast, @@ -189,10 +186,10 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp, extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_print_accumulated_stats() { if (nsan_stats) - nsan_stats->print(); + nsan_stats->Print(); } -static void nsanAtexit() { +static void NsanAtexit() { Printf("Numerical Sanitizer exit stats:\n"); __nsan_print_accumulated_stats(); nsan_stats = nullptr; @@ -204,13 +201,13 @@ static void nsanAtexit() { // around long double being the same for nsan and the target application. // We have to have 3 versions because we need to know which type we are storing // since we are setting the type shadow memory. -template <typename FT> static u8 *getShadowPtrForStore(u8 *StoreAddr, uptr N) { - unsigned char *ShadowType = getShadowTypeAddrFor(StoreAddr); - for (uptr I = 0; I < N; ++I) { - __builtin_memcpy(ShadowType + I * sizeof(FT), FTInfo<FT>::kTypePattern, +template <typename FT> static u8 *getShadowPtrForStore(u8 *store_addr, uptr n) { + unsigned char *shadow_type = GetShadowTypeAddrFor(store_addr); + for (uptr i = 0; i < n; ++i) { + __builtin_memcpy(shadow_type + i * sizeof(FT), FTInfo<FT>::kTypePattern, sizeof(FTInfo<FT>::kTypePattern)); } - return getShadowAddrFor(StoreAddr); + return GetShadowAddrFor(store_addr); } extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 * @@ -228,48 +225,48 @@ __nsan_get_shadow_ptr_for_longdouble_store(u8 *store_addr, uptr n) { return getShadowPtrForStore<long double>(store_addr, n); } -template <typename FT> static bool isValidShadowType(const u8 *ShadowType) { - return __builtin_memcmp(ShadowType, FTInfo<FT>::kTypePattern, sizeof(FT)) == +template <typename FT> static bool IsValidShadowType(const u8 *shadow_type) { + return __builtin_memcmp(shadow_type, FTInfo<FT>::kTypePattern, sizeof(FT)) == 0; } -template <int kSize, typename T> static bool isZero(const T *Ptr) { +template <int kSize, typename T> static bool IsZero(const T *ptr) { constexpr const char kZeros[kSize] = {}; // Zero initialized. - return __builtin_memcmp(Ptr, kZeros, kSize) == 0; + return __builtin_memcmp(ptr, kZeros, kSize) == 0; } -template <typename FT> static bool isUnknownShadowType(const u8 *ShadowType) { - return isZero<sizeof(FTInfo<FT>::kTypePattern)>(ShadowType); +template <typename FT> static bool IsUnknownShadowType(const u8 *shadow_type) { + return IsZero<sizeof(FTInfo<FT>::kTypePattern)>(shadow_type); } // The three folowing functions check that the address stores a complete // shadow value of the given type and return a pointer for loading. // They return nullptr if the type of the value is unknown or incomplete. template <typename FT> -static const u8 *getShadowPtrForLoad(const u8 *LoadAddr, uptr N) { - const u8 *const ShadowType = getShadowTypeAddrFor(LoadAddr); - for (uptr I = 0; I < N; ++I) { - if (!isValidShadowType<FT>(ShadowType + I * sizeof(FT))) { +static const u8 *getShadowPtrForLoad(const u8 *load_addr, uptr n) { + const u8 *const shadow_type = GetShadowTypeAddrFor(load_addr); + for (uptr i = 0; i < n; ++i) { + if (!IsValidShadowType<FT>(shadow_type + i * sizeof(FT))) { // If loadtracking stats are enabled, log loads with invalid types // (tampered with through type punning). if (flags().enable_loadtracking_stats) { - if (isUnknownShadowType<FT>(ShadowType + I * sizeof(FT))) { + if (IsUnknownShadowType<FT>(shadow_type + i * sizeof(FT))) { // Warn only if the value is non-zero. Zero is special because // applications typically initialize large buffers to zero in an // untyped way. - if (!isZero<sizeof(FT)>(LoadAddr)) { + if (!IsZero<sizeof(FT)>(load_addr)) { GET_CALLER_PC_BP; - nsan_stats->addUnknownLoadTrackingEvent(pc, bp); + nsan_stats->AddUnknownLoadTrackingEvent(pc, bp); } } else { GET_CALLER_PC_BP; - nsan_stats->addInvalidLoadTrackingEvent(pc, bp); + nsan_stats->AddInvalidLoadTrackingEvent(pc, bp); } } return nullptr; } } - return getShadowAddrFor(LoadAddr); + return GetShadowAddrFor(load_addr); } extern "C" SANITIZER_INTERFACE_ATTRIBUTE const u8 * @@ -291,14 +288,14 @@ __nsan_get_shadow_ptr_for_longdouble_load(const u8 *load_addr, uptr n) { // opaque. extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 * __nsan_internal_get_raw_shadow_ptr(const u8 *addr) { - return getShadowAddrFor(const_cast<u8 *>(addr)); + return GetShadowAddrFor(const_cast<u8 *>(addr)); } // Returns the raw shadow type pointer. The returned pointer should be // considered opaque. extern "C" SANITIZER_INTERFACE_ATTRIBUTE u8 * __nsan_internal_get_raw_shadow_type_ptr(const u8 *addr) { - return reinterpret_cast<u8 *>(getShadowTypeAddrFor(const_cast<u8 *>(addr))); + return reinterpret_cast<u8 *>(GetShadowTypeAddrFor(const_cast<u8 *>(addr))); } static ValueType getValueType(u8 c) { return static_cast<ValueType>(c & 0x3); } @@ -308,14 +305,14 @@ static int getValuePos(u8 c) { return c >> kValueSizeSizeBits; } // Checks the consistency of the value types at the given type pointer. // If the value is inconsistent, returns ValueType::kUnknown. Else, return the // consistent type. -template <typename FT> static bool checkValueConsistency(const u8 *ShadowType) { - const int Pos = getValuePos(*ShadowType); +template <typename FT> +static bool checkValueConsistency(const u8 *shadow_type) { + const int pos = getValuePos(*shadow_type); // Check that all bytes from the start of the value are ordered. - for (uptr I = 0; I < sizeof(FT); ++I) { - const u8 T = *(ShadowType - Pos + I); - if (!(getValueType(T) == FTInfo<FT>::kValueType && getValuePos(T) == I)) { + for (uptr i = 0; i < sizeof(FT); ++i) { + const u8 T = *(shadow_type - pos + i); + if (!(getValueType(T) == FTInfo<FT>::kValueType && getValuePos(T) == i)) return false; - } } return true; } @@ -325,15 +322,14 @@ template <typename FT> static bool checkValueConsistency(const u8 *ShadowType) { 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) { - const u8 *const ShadowType = getShadowTypeAddrFor(addr); - const u8 *const Shadow = getShadowAddrFor(addr); + const u8 *const shadow_type = GetShadowTypeAddrFor(addr); + const u8 *const shadow = GetShadowAddrFor(addr); constexpr int kMaxNumDecodedValues = 16; - __float128 DecodedValues[kMaxNumDecodedValues]; - int NumDecodedValues = 0; - if (bytes_per_line > 4 * kMaxNumDecodedValues) { + __float128 decoded_values[kMaxNumDecodedValues]; + int num_decoded_values = 0; + if (bytes_per_line > 4 * kMaxNumDecodedValues) bytes_per_line = 4 * kMaxNumDecodedValues; - } // We keep track of the current type and position as we go. ValueType LastValueTy = kUnknownValueType; @@ -343,8 +339,8 @@ __nsan_dump_shadow_mem(const u8 *addr, size_t size_bytes, size_t bytes_per_line, ++R) { printf("%p: ", (void *)(addr + R * bytes_per_line)); for (size_t C = 0; C < bytes_per_line && Offset < size_bytes; ++C) { - const ValueType ValueTy = getValueType(ShadowType[Offset]); - const int pos = getValuePos(ShadowType[Offset]); + const ValueType ValueTy = getValueType(shadow_type[Offset]); + const int pos = getValuePos(shadow_type[Offset]); if (ValueTy == LastValueTy && pos == LastPos + 1) { ++LastPos; } else { @@ -359,64 +355,59 @@ __nsan_dump_shadow_mem(const u8 *addr, size_t size_bytes, size_t bytes_per_line, case kFloatValueType: printf("f%x ", pos); if (LastPos == sizeof(float) - 1) { - DecodedValues[NumDecodedValues] = - readShadow(Shadow + kShadowScale * (Offset + 1 - sizeof(float)), + decoded_values[num_decoded_values] = + ReadShadow(shadow + kShadowScale * (Offset + 1 - sizeof(float)), static_cast<char>(shadow_value_type_ids & 0xff)); - ++NumDecodedValues; + ++num_decoded_values; } break; case kDoubleValueType: printf("d%x ", pos); if (LastPos == sizeof(double) - 1) { - DecodedValues[NumDecodedValues] = readShadow( - Shadow + kShadowScale * (Offset + 1 - sizeof(double)), + decoded_values[num_decoded_values] = ReadShadow( + shadow + kShadowScale * (Offset + 1 - sizeof(double)), static_cast<char>((shadow_value_type_ids >> 8) & 0xff)); - ++NumDecodedValues; + ++num_decoded_values; } break; case kFp80ValueType: printf("l%x ", pos); if (LastPos == sizeof(long double) - 1) { - DecodedValues[NumDecodedValues] = readShadow( - Shadow + kShadowScale * (Offset + 1 - sizeof(long double)), + decoded_values[num_decoded_values] = ReadShadow( + shadow + kShadowScale * (Offset + 1 - sizeof(long double)), static_cast<char>((shadow_value_type_ids >> 16) & 0xff)); - ++NumDecodedValues; + ++num_decoded_values; } break; } ++Offset; } - for (int I = 0; I < NumDecodedValues; ++I) { - printf(" (%s)", FTPrinter<__float128>::dec(DecodedValues[I]).Buffer); + for (int i = 0; i < num_decoded_values; ++i) { + printf(" (%s)", FTPrinter<__float128>::dec(decoded_values[i]).Buffer); } - NumDecodedValues = 0; + num_decoded_values = 0; printf("\n"); } } SANITIZER_INTERFACE_ATTRIBUTE -ALIGNED(16) -THREADLOCAL -uptr __nsan_shadow_ret_tag = 0; +alignas(16) thread_local uptr __nsan_shadow_ret_tag = 0; SANITIZER_INTERFACE_ATTRIBUTE -ALIGNED(16) -THREADLOCAL -char __nsan_shadow_ret_ptr[kMaxVectorWidth * sizeof(__float128)]; +alignas(16) thread_local char __nsan_shadow_ret_ptr[kMaxVectorWidth * + sizeof(__float128)]; SANITIZER_INTERFACE_ATTRIBUTE -ALIGNED(16) -THREADLOCAL -uptr __nsan_shadow_args_tag = 0; +alignas(16) thread_local uptr __nsan_shadow_args_tag = 0; // Maximum number of args. This should be enough for anyone (tm). An alternate // scheme is to have the generated code create an alloca and make // __nsan_shadow_args_ptr point ot the alloca. constexpr const int kMaxNumArgs = 128; SANITIZER_INTERFACE_ATTRIBUTE -ALIGNED(16) -THREADLOCAL -char __nsan_shadow_args_ptr[kMaxVectorWidth * kMaxNumArgs * sizeof(__float128)]; +alignas( + 16) thread_local char __nsan_shadow_args_ptr[kMaxVectorWidth * kMaxNumArgs * + sizeof(__float128)]; enum ContinuationType { // Keep in sync with instrumentation pass. kContinueWithShadow = 0, @@ -428,36 +419,36 @@ enum ContinuationType { // Keep in sync with instrumentation pass. // rather than the shadow value. This prevents one error to propagate to all // subsequent operations. This behaviour is tunable with flags. template <typename FT, typename ShadowFT> -int32_t checkFT(const FT Value, ShadowFT Shadow, CheckTypeT CheckType, +int32_t checkFT(const FT value, ShadowFT Shadow, CheckTypeT CheckType, uptr CheckArg) { // We do all comparisons in the InternalFT domain, which is the largest FT // type. using InternalFT = LargestFT<FT, ShadowFT>; - const InternalFT CheckValue = Value; - const InternalFT CheckShadow = Shadow; + const InternalFT check_value = value; + const InternalFT check_shadow = Shadow; // See this article for an interesting discussion of how to compare floats: // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ static constexpr const FT Eps = FTInfo<FT>::kEpsilon; - const InternalFT AbsErr = ftAbs(CheckValue - CheckShadow); + const InternalFT abs_err = ftAbs(check_value - check_shadow); if (flags().enable_check_stats) { GET_CALLER_PC_BP; - // We are re-computing `Largest` here because this is a cold branch, and we - // want to avoid having to move the computation of `Largest` before the + // We are re-computing `largest` here because this is a cold branch, and we + // want to avoid having to move the computation of `largest` before the // absolute value check when this branch is not taken. - const InternalFT Largest = max(ftAbs(CheckValue), ftAbs(CheckShadow)); - nsan_stats->addCheck(CheckType, pc, bp, AbsErr / Largest); + const InternalFT largest = max(ftAbs(check_value), ftAbs(check_shadow)); + nsan_stats->AddCheck(CheckType, pc, bp, abs_err / largest); } - // Note: writing the comparison that way ensures that when `AbsErr` is Nan + // Note: writing the comparison that way ensures that when `abs_err` is Nan // (value and shadow are inf or -inf), we pass the test. - if (!(AbsErr >= flags().cached_absolute_error_threshold)) + if (!(abs_err >= flags().cached_absolute_error_threshold)) return kContinueWithShadow; - const InternalFT Largest = max(ftAbs(CheckValue), ftAbs(CheckShadow)); - if (AbsErr * (1ull << flags().log2_max_relative_error) <= Largest) + const InternalFT largest = max(ftAbs(check_value), ftAbs(check_shadow)); + if (abs_err * (1ull << flags().log2_max_relative_error) <= largest) return kContinueWithShadow; // No problem here. if (!flags().disable_warnings) { @@ -474,22 +465,22 @@ int32_t checkFT(const FT Value, ShadowFT Shadow, CheckTypeT CheckType, Printf("%s", D.Warning()); // Printf does not support float formatting. char RelErrBuf[64] = "inf"; - if (Largest > Eps) { + if (largest > Eps) { snprintf(RelErrBuf, sizeof(RelErrBuf) - 1, "%.20Lf%% (2^%.0Lf epsilons)", - static_cast<long double>(100.0 * AbsErr / Largest), - log2l(static_cast<long double>(AbsErr / Largest / Eps))); + static_cast<long double>(100.0 * abs_err / largest), + log2l(static_cast<long double>(abs_err / largest / Eps))); } - char UlpErrBuf[128] = ""; - const double ShadowUlpDiff = getULPDiff(CheckValue, CheckShadow); - if (ShadowUlpDiff != kMaxULPDiff) { + char ulp_err_buf[128] = ""; + const double shadow_ulp_diff = GetULPDiff(check_value, check_shadow); + if (shadow_ulp_diff != kMaxULPDiff) { // This is the ULP diff in the internal domain. The user actually cares // about that in the original domain. - const double UlpDiff = - ShadowUlpDiff / (u64{1} << (FTInfo<InternalFT>::kMantissaBits - - FTInfo<FT>::kMantissaBits)); - snprintf(UlpErrBuf, sizeof(UlpErrBuf) - 1, - "(%.0f ULPs == %.1f digits == %.1f bits)", UlpDiff, - log10(UlpDiff), log2(UlpDiff)); + const double ulp_diff = + shadow_ulp_diff / (u64{1} << (FTInfo<InternalFT>::kMantissaBits - + FTInfo<FT>::kMantissaBits)); + snprintf(ulp_err_buf, sizeof(ulp_err_buf) - 1, + "(%.0f ULPs == %.1f digits == %.1f bits)", ulp_diff, + log10(ulp_diff), log2(ulp_diff)); } Printf("WARNING: NumericalStabilitySanitizer: inconsistent shadow results"); switch (CheckType) { @@ -529,18 +520,18 @@ int32_t checkFT(const FT Value, ShadowFT Shadow, CheckTypeT CheckType, "Relative error: %s\n" "Absolute error: %s\n" "%s\n", - FTInfo<FT>::kCppTypeName, ValuePrinter::dec(Value).Buffer, - ValuePrinter::hex(Value).Buffer, FTInfo<ShadowFT>::kCppTypeName, + FTInfo<FT>::kCppTypeName, ValuePrinter::dec(value).Buffer, + ValuePrinter::hex(value).Buffer, FTInfo<ShadowFT>::kCppTypeName, ShadowPrinter::dec(Shadow).Buffer, ShadowPrinter::hex(Shadow).Buffer, FTInfo<FT>::kCppTypeName, ValuePrinter::dec(Shadow).Buffer, ValuePrinter::hex(Shadow).Buffer, RelErrBuf, - ValuePrinter::hex(AbsErr).Buffer, UlpErrBuf); + ValuePrinter::hex(abs_err).Buffer, ulp_err_buf); stack.Print(); } if (flags().enable_warning_stats) { GET_CALLER_PC_BP; - nsan_stats->addWarning(CheckType, pc, bp, AbsErr / Largest); + nsan_stats->AddWarning(CheckType, pc, bp, abs_err / largest); } if (flags().halt_on_error) { @@ -571,10 +562,10 @@ __nsan_internal_check_longdouble_q(long double value, __float128 shadow, return checkFT(value, shadow, static_cast<CheckTypeT>(check_type), check_arg); } -static const char *getTruthValueName(bool v) { return v ? "true" : "false"; } +static const char *GetTruthValueName(bool v) { return v ? "true" : "false"; } // This uses the same values as CmpInst::Predicate. -static const char *getPredicateName(int v) { +static const char *GetPredicateName(int v) { switch (v) { case 0: return "(false)"; @@ -614,9 +605,9 @@ static const char *getPredicateName(int v) { template <typename FT, typename ShadowFT> void fCmpFailFT(const FT Lhs, const FT Rhs, ShadowFT LhsShadow, - ShadowFT RhsShadow, int Predicate, bool Result, + ShadowFT RhsShadow, int Predicate, bool result, bool ShadowResult) { - if (Result == ShadowResult) { + if (result == ShadowResult) { // When a vector comparison fails, we fail each element of the comparison // to simplify instrumented code. Skip elements where the shadow comparison // gave the same result as the original one. @@ -624,21 +615,19 @@ void fCmpFailFT(const FT Lhs, const FT Rhs, ShadowFT LhsShadow, } GET_CALLER_PC_BP; - BufferedStackTrace Stack; - Stack.Unwind(pc, bp, nullptr, false); + BufferedStackTrace stack; + stack.Unwind(pc, bp, nullptr, false); - if (GetSuppressionForStack(&Stack, CheckKind::Fcmp)) { + if (GetSuppressionForStack(&stack, CheckKind::Fcmp)) { // FIXME: optionally print. return; } - if (flags().enable_warning_stats) { - nsan_stats->addWarning(CheckTypeT::kFcmp, pc, bp, 0.0); - } + if (flags().enable_warning_stats) + nsan_stats->AddWarning(CheckTypeT::kFcmp, pc, bp, 0.0); - if (flags().disable_warnings) { + if (flags().disable_warnings) return; - } // FIXME: ideally we would print the shadow value as FP128. Right now because // we truncate to long double we can sometimes see stuff like: @@ -646,7 +635,7 @@ void fCmpFailFT(const FT Lhs, const FT Rhs, ShadowFT LhsShadow, using ValuePrinter = FTPrinter<FT>; using ShadowPrinter = FTPrinter<ShadowFT>; Decorator D; - const char *const PredicateName = getPredicateName(Predicate); + const char *const PredicateName = GetPredicateName(Predicate); Printf("%s", D.Warning()); Printf("WARNING: NumericalStabilitySanitizer: floating-point comparison " "results depend on precision\n" @@ -657,20 +646,20 @@ void fCmpFailFT(const FT Lhs, const FT Rhs, ShadowFT LhsShadow, "%s", // Native, decimal. FTInfo<FT>::kCppTypeName, ValuePrinter::dec(Lhs).Buffer, PredicateName, - ValuePrinter::dec(Rhs).Buffer, getTruthValueName(Result), + ValuePrinter::dec(Rhs).Buffer, GetTruthValueName(result), // Shadow, decimal FTInfo<ShadowFT>::kCppTypeName, ShadowPrinter::dec(LhsShadow).Buffer, PredicateName, ShadowPrinter::dec(RhsShadow).Buffer, - getTruthValueName(ShadowResult), + GetTruthValueName(ShadowResult), // Native, hex. FTInfo<FT>::kCppTypeName, ValuePrinter::hex(Lhs).Buffer, PredicateName, - ValuePrinter::hex(Rhs).Buffer, getTruthValueName(Result), + ValuePrinter::hex(Rhs).Buffer, GetTruthValueName(result), // Shadow, hex FTInfo<ShadowFT>::kCppTypeName, ShadowPrinter::hex(LhsShadow).Buffer, PredicateName, ShadowPrinter::hex(RhsShadow).Buffer, - getTruthValueName(ShadowResult), D.End()); + GetTruthValueName(ShadowResult), D.End()); Printf("%s", D.Default()); - Stack.Print(); + stack.Print(); if (flags().halt_on_error) { Printf("Exiting\n"); Die(); @@ -709,77 +698,77 @@ __nsan_fcmp_fail_longdouble_q(long double lhs, long double rhs, shadow_result); } -template <typename FT> void checkFTFromShadowStack(const FT Value) { +template <typename FT> void checkFTFromShadowStack(const FT value) { // Get the shadow 2FT value from the shadow stack. Note that // __nsan_check_{float,double,long double} is a function like any other, so // the instrumentation will have placed the shadow value on the shadow stack. using ShadowFT = typename FTInfo<FT>::shadow_type; ShadowFT Shadow; __builtin_memcpy(&Shadow, __nsan_shadow_args_ptr, sizeof(ShadowFT)); - checkFT(Value, Shadow, CheckTypeT::kUser, 0); + checkFT(value, Shadow, CheckTypeT::kUser, 0); } // FIXME: Add suffixes and let the instrumentation pass automatically add // suffixes. -extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_check_float(float Value) { +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_check_float(float value) { assert(__nsan_shadow_args_tag == (uptr)&__nsan_check_float && "__nsan_check_float called from non-instrumented function"); - checkFTFromShadowStack(Value); + checkFTFromShadowStack(value); } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__nsan_check_double(double Value) { +__nsan_check_double(double value) { assert(__nsan_shadow_args_tag == (uptr)&__nsan_check_double && "__nsan_check_double called from non-instrumented function"); - checkFTFromShadowStack(Value); + checkFTFromShadowStack(value); } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__nsan_check_longdouble(long double Value) { +__nsan_check_longdouble(long double value) { assert(__nsan_shadow_args_tag == (uptr)&__nsan_check_longdouble && "__nsan_check_longdouble called from non-instrumented function"); - checkFTFromShadowStack(Value); + checkFTFromShadowStack(value); } -template <typename FT> static void dumpFTFromShadowStack(const FT Value) { +template <typename FT> static void dumpFTFromShadowStack(const FT value) { // Get the shadow 2FT value from the shadow stack. Note that // __nsan_dump_{float,double,long double} is a function like any other, so // the instrumentation will have placed the shadow value on the shadow stack. using ShadowFT = typename FTInfo<FT>::shadow_type; - ShadowFT Shadow; - __builtin_memcpy(&Shadow, __nsan_shadow_args_ptr, sizeof(ShadowFT)); + ShadowFT shadow; + __builtin_memcpy(&shadow, __nsan_shadow_args_ptr, sizeof(ShadowFT)); using ValuePrinter = FTPrinter<FT>; using ShadowPrinter = FTPrinter<typename FTInfo<FT>::shadow_type>; printf("value dec:%s hex:%s\n" "shadow dec:%s hex:%s\n", - ValuePrinter::dec(Value).Buffer, ValuePrinter::hex(Value).Buffer, - ShadowPrinter::dec(Shadow).Buffer, ShadowPrinter::hex(Shadow).Buffer); + ValuePrinter::dec(value).Buffer, ValuePrinter::hex(value).Buffer, + ShadowPrinter::dec(shadow).Buffer, ShadowPrinter::hex(shadow).Buffer); } -extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_float(float Value) { +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_float(float value) { assert(__nsan_shadow_args_tag == (uptr)&__nsan_dump_float && "__nsan_dump_float called from non-instrumented function"); - dumpFTFromShadowStack(Value); + dumpFTFromShadowStack(value); } -extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_double(double Value) { +extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_double(double value) { assert(__nsan_shadow_args_tag == (uptr)&__nsan_dump_double && "__nsan_dump_double called from non-instrumented function"); - dumpFTFromShadowStack(Value); + dumpFTFromShadowStack(value); } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__nsan_dump_longdouble(long double Value) { +__nsan_dump_longdouble(long double value) { assert(__nsan_shadow_args_tag == (uptr)&__nsan_dump_longdouble && "__nsan_dump_longdouble called from non-instrumented function"); - dumpFTFromShadowStack(Value); + dumpFTFromShadowStack(value); } extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_shadow_ret() { printf("ret tag: %lx\n", __nsan_shadow_ret_tag); - double V; - __builtin_memcpy(&V, __nsan_shadow_ret_ptr, sizeof(double)); - printf("double Value: %f\n", V); + double v; + __builtin_memcpy(&v, __nsan_shadow_ret_ptr, sizeof(double)); + printf("double value: %f\n", v); // FIXME: float128 value. } @@ -787,16 +776,14 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_dump_shadow_args() { printf("args tag: %lx\n", __nsan_shadow_args_tag); } -namespace __nsan { -bool NsanInitialized = false; -bool NsanInitIsRunning; -} // end namespace __nsan +bool __nsan::nsan_initialized; +bool __nsan::nsan_init_is_running; extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_init() { - CHECK(!NsanInitIsRunning); - if (NsanInitialized) + CHECK(!nsan_init_is_running); + if (nsan_initialized) return; - NsanInitIsRunning = true; + nsan_init_is_running = true; InitializeFlags(); InitializeSuppressions(); @@ -805,14 +792,14 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __nsan_init() { if (!MmapFixedNoReserve(TypesAddr(), UnusedAddr() - TypesAddr())) Die(); - initializeInterceptors(); + InitializeInterceptors(); - initializeStats(); + InitializeStats(); if (flags().print_stats_on_exit) - Atexit(nsanAtexit); + Atexit(NsanAtexit); - NsanInitIsRunning = false; - NsanInitialized = true; + nsan_init_is_running = false; + nsan_initialized = true; } #if SANITIZER_CAN_USE_PREINIT_ARRAY diff --git a/compiler-rt/lib/nsan/nsan.h b/compiler-rt/lib/nsan/nsan.h index 6ab64d3..896e537 100644 --- a/compiler-rt/lib/nsan/nsan.h +++ b/compiler-rt/lib/nsan/nsan.h @@ -51,32 +51,32 @@ __nsan_default_options(); namespace __nsan { -extern bool NsanInitialized; -extern bool NsanInitIsRunning; +extern bool nsan_initialized; +extern bool nsan_init_is_running; -void initializeInterceptors(); +void InitializeInterceptors(); // See notes in nsan_platform. // printf-free (see comment in nsan_interceptors.cc). -inline u8 *getShadowAddrFor(u8 *Ptr) { +inline u8 *GetShadowAddrFor(u8 *Ptr) { uptr AppOffset = ((uptr)Ptr) & ShadowMask(); return (u8 *)(AppOffset * kShadowScale + ShadowAddr()); } // printf-free (see comment in nsan_interceptors.cc). -inline const u8 *getShadowAddrFor(const u8 *Ptr) { - return getShadowAddrFor(const_cast<u8 *>(Ptr)); +inline const u8 *GetShadowAddrFor(const u8 *Ptr) { + return GetShadowAddrFor(const_cast<u8 *>(Ptr)); } // printf-free (see comment in nsan_interceptors.cc). -inline u8 *getShadowTypeAddrFor(u8 *Ptr) { +inline u8 *GetShadowTypeAddrFor(u8 *Ptr) { uptr AppOffset = ((uptr)Ptr) & ShadowMask(); return (u8 *)(AppOffset + TypesAddr()); } // printf-free (see comment in nsan_interceptors.cc). -inline const u8 *getShadowTypeAddrFor(const u8 *Ptr) { - return getShadowTypeAddrFor(const_cast<u8 *>(Ptr)); +inline const u8 *GetShadowTypeAddrFor(const u8 *Ptr) { + return GetShadowTypeAddrFor(const_cast<u8 *>(Ptr)); } // Information about value types and their shadow counterparts. @@ -164,60 +164,60 @@ template <> struct FTInfo<__float128> { constexpr double kMaxULPDiff = INFINITY; // Helper for getULPDiff that works on bit representations. -template <typename BT> double getULPDiffBits(BT V1Bits, BT V2Bits) { +template <typename BT> double GetULPDiffBits(BT v1_bits, BT v2_bits) { // If the integer representations of two same-sign floats are subtracted then // the absolute value of the result is equal to one plus the number of // representable floats between them. - return V1Bits >= V2Bits ? V1Bits - V2Bits : V2Bits - V1Bits; + return v1_bits >= v2_bits ? v1_bits - v2_bits : v2_bits - v1_bits; } -// Returns the the number of floating point values between V1 and V2, capped to +// Returns the the number of floating point values between v1 and v2, capped to // u64max. Return 0 for (-0.0,0.0). -template <typename FT> double getULPDiff(FT V1, FT V2) { - if (V1 == V2) { +template <typename FT> double GetULPDiff(FT v1, FT v2) { + if (v1 == v2) { return 0; // Typically, -0.0 and 0.0 } using BT = typename FTInfo<FT>::orig_bits_type; static_assert(sizeof(FT) == sizeof(BT), "not implemented"); static_assert(sizeof(BT) <= 64, "not implemented"); - BT V1Bits; - __builtin_memcpy(&V1Bits, &V1, sizeof(BT)); - BT V2Bits; - __builtin_memcpy(&V2Bits, &V2, sizeof(BT)); + BT v1_bits; + __builtin_memcpy(&v1_bits, &v1, sizeof(BT)); + BT v2_bits; + __builtin_memcpy(&v2_bits, &v2, sizeof(BT)); // Check whether the signs differ. IEEE-754 float types always store the sign // in the most significant bit. NaNs and infinities are handled by the calling // code. constexpr BT kSignMask = BT{1} << (CHAR_BIT * sizeof(BT) - 1); - if ((V1Bits ^ V2Bits) & kSignMask) { + if ((v1_bits ^ v2_bits) & kSignMask) { // Signs differ. We can get the ULPs as `getULPDiff(negative_number, -0.0) // + getULPDiff(0.0, positive_number)`. - if (V1Bits & kSignMask) { - return getULPDiffBits<BT>(V1Bits, kSignMask) + - getULPDiffBits<BT>(0, V2Bits); + if (v1_bits & kSignMask) { + return GetULPDiffBits<BT>(v1_bits, kSignMask) + + GetULPDiffBits<BT>(0, v2_bits); } else { - return getULPDiffBits<BT>(V2Bits, kSignMask) + - getULPDiffBits<BT>(0, V1Bits); + return GetULPDiffBits<BT>(v2_bits, kSignMask) + + GetULPDiffBits<BT>(0, v1_bits); } } - return getULPDiffBits(V1Bits, V2Bits); + return GetULPDiffBits(v1_bits, v2_bits); } // FIXME: This needs mor work: Because there is no 80-bit integer type, we have // to go through __uint128_t. Therefore the assumptions about the sign bit do // not hold. -template <> inline double getULPDiff(long double V1, long double V2) { +template <> inline double GetULPDiff(long double v1, long double v2) { using BT = __uint128_t; - BT V1Bits = 0; - __builtin_memcpy(&V1Bits, &V1, sizeof(long double)); - BT V2Bits = 0; - __builtin_memcpy(&V2Bits, &V2, sizeof(long double)); - if ((V1Bits ^ V2Bits) & (BT{1} << (CHAR_BIT * sizeof(BT) - 1))) - return (V1 == V2) ? __sanitizer::u64{0} : kMaxULPDiff; // Signs differ. + BT v1_bits = 0; + __builtin_memcpy(&v1_bits, &v1, sizeof(long double)); + BT v2_bits = 0; + __builtin_memcpy(&v2_bits, &v2, sizeof(long double)); + if ((v1_bits ^ v2_bits) & (BT{1} << (CHAR_BIT * sizeof(BT) - 1))) + return v1 == v2 ? __sanitizer::u64{0} : kMaxULPDiff; // Signs differ. // If the integer representations of two same-sign floats are subtracted then // the absolute value of the result is equal to one plus the number of // representable floats between them. - BT Diff = V1Bits >= V2Bits ? V1Bits - V2Bits : V2Bits - V1Bits; - return Diff >= kMaxULPDiff ? kMaxULPDiff : Diff; + BT diff = v1_bits >= v2_bits ? v1_bits - v2_bits : v2_bits - v1_bits; + return diff >= kMaxULPDiff ? kMaxULPDiff : diff; } } // end namespace __nsan diff --git a/compiler-rt/lib/nsan/nsan_flags.cc b/compiler-rt/lib/nsan/nsan_flags.cpp index 09a9dad..94e3a18 100644 --- a/compiler-rt/lib/nsan/nsan_flags.cc +++ b/compiler-rt/lib/nsan/nsan_flags.cpp @@ -15,15 +15,14 @@ #include "sanitizer_common/sanitizer_flag_parser.h" #include "sanitizer_common/sanitizer_flags.h" -namespace __nsan { +using namespace __sanitizer; +using namespace __nsan; SANITIZER_INTERFACE_WEAK_DEF(const char *, __nsan_default_options, void) { return ""; } -using namespace __sanitizer; - -Flags flags_data; +Flags __nsan::flags_data; void Flags::SetDefaults() { #define NSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; @@ -47,7 +46,7 @@ static const char *MaybeCallNsanDefaultOptions() { return (&__nsan_default_options) ? __nsan_default_options() : ""; } -void InitializeFlags() { +void __nsan::InitializeFlags() { SetCommonFlagsDefaults(); { CommonFlags cf; @@ -74,5 +73,3 @@ void InitializeFlags() { flags().PopulateCache(); } - -} // namespace __nsan diff --git a/compiler-rt/lib/nsan/nsan_interceptors.cc b/compiler-rt/lib/nsan/nsan_interceptors.cc deleted file mode 100644 index 394d788..0000000 --- a/compiler-rt/lib/nsan/nsan_interceptors.cc +++ /dev/null @@ -1,364 +0,0 @@ -//===-- nsan_interceptors.cc ----------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Interceptors for standard library functions. -// -// A note about `printf`: Make sure none of the interceptor code calls any -// part of the nsan framework that can call `printf`, since this could create -// a loop (`printf` itself uses the libc). printf-free functions are documented -// as such in nsan.h. -// -//===----------------------------------------------------------------------===// - -#include "interception/interception.h" -#include "nsan/nsan.h" -#include "sanitizer_common/sanitizer_common.h" - -#include <wchar.h> - -#if SANITIZER_LINUX -extern "C" int mallopt(int param, int value); -#endif - -using namespace __sanitizer; -using __nsan::NsanInitialized; -using __nsan::NsanInitIsRunning; - -static constexpr uptr kEarlyAllocBufSize = 16384; -static uptr AllocatedBytes; -static char EarlyAllocBuf[kEarlyAllocBufSize]; - -static bool isInEarlyAllocBuf(const void *Ptr) { - return ((uptr)Ptr >= (uptr)EarlyAllocBuf && - ((uptr)Ptr - (uptr)EarlyAllocBuf) < sizeof(EarlyAllocBuf)); -} - -static u8 *toU8Ptr(wchar_t *ptr) { return reinterpret_cast<u8 *>(ptr); } - -static const u8 *toU8Ptr(const wchar_t *ptr) { - return reinterpret_cast<const u8 *>(ptr); -} - -template <typename T> T min(T a, T b) { return a < b ? a : b; } - -// Handle allocation requests early (before all interceptors are setup). dlsym, -// for example, calls calloc. -static void *handleEarlyAlloc(uptr Size) { - void *Mem = (void *)&EarlyAllocBuf[AllocatedBytes]; - AllocatedBytes += Size; - CHECK_LT(AllocatedBytes, kEarlyAllocBufSize); - return Mem; -} - -INTERCEPTOR(void *, memset, void *Dst, int V, uptr Size) { - // NOTE: This guard is needed because nsan's initialization code might call - // memset. - if (!NsanInitialized && REAL(memset) == nullptr) - return internal_memset(Dst, V, Size); - - void *Res = REAL(memset)(Dst, V, Size); - __nsan_set_value_unknown(static_cast<u8 *>(Dst), Size); - return Res; -} - -INTERCEPTOR(wchar_t *, wmemset, wchar_t *Dst, wchar_t V, uptr Size) { - wchar_t *Res = REAL(wmemset)(Dst, V, Size); - __nsan_set_value_unknown(toU8Ptr(Dst), sizeof(wchar_t) * Size); - return Res; -} - -INTERCEPTOR(void *, memmove, void *Dst, const void *Src, uptr Size) { - // NOTE: This guard is needed because nsan's initialization code might call - // memmove. - if (!NsanInitialized && REAL(memmove) == nullptr) - return internal_memmove(Dst, Src, Size); - - void *Res = REAL(memmove)(Dst, Src, Size); - __nsan_copy_values(static_cast<u8 *>(Dst), static_cast<const u8 *>(Src), - Size); - return Res; -} - -INTERCEPTOR(wchar_t *, wmemmove, wchar_t *Dst, const wchar_t *Src, uptr Size) { - wchar_t *Res = REAL(wmemmove)(Dst, Src, Size); - __nsan_copy_values(toU8Ptr(Dst), toU8Ptr(Src), sizeof(wchar_t) * Size); - return Res; -} - -INTERCEPTOR(void *, memcpy, void *Dst, const void *Src, uptr Size) { - // NOTE: This guard is needed because nsan's initialization code might call - // memcpy. - if (!NsanInitialized && REAL(memcpy) == nullptr) { - // memmove is used here because on some platforms this will also - // intercept the memmove implementation. - return internal_memmove(Dst, Src, Size); - } - - void *Res = REAL(memcpy)(Dst, Src, Size); - __nsan_copy_values(static_cast<u8 *>(Dst), static_cast<const u8 *>(Src), - Size); - return Res; -} - -INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *Dst, const wchar_t *Src, uptr Size) { - wchar_t *Res = REAL(wmemcpy)(Dst, Src, Size); - __nsan_copy_values(toU8Ptr(Dst), toU8Ptr(Src), sizeof(wchar_t) * Size); - return Res; -} - -INTERCEPTOR(void *, malloc, uptr Size) { - // NOTE: This guard is needed because nsan's initialization code might call - // malloc. - if (NsanInitIsRunning && REAL(malloc) == nullptr) - return handleEarlyAlloc(Size); - - void *Res = REAL(malloc)(Size); - if (Res) - __nsan_set_value_unknown(static_cast<u8 *>(Res), Size); - return Res; -} - -INTERCEPTOR(void *, realloc, void *Ptr, uptr Size) { - void *Res = REAL(realloc)(Ptr, Size); - // FIXME: We might want to copy the types from the original allocation - // (although that would require that we know its size). - if (Res) - __nsan_set_value_unknown(static_cast<u8 *>(Res), Size); - return Res; -} - -INTERCEPTOR(void *, calloc, uptr Nmemb, uptr Size) { - // NOTE: This guard is needed because nsan's initialization code might call - // calloc. - if (NsanInitIsRunning && REAL(calloc) == nullptr) { - // Note: EarlyAllocBuf is initialized with zeros. - return handleEarlyAlloc(Nmemb * Size); - } - - void *Res = REAL(calloc)(Nmemb, Size); - if (Res) - __nsan_set_value_unknown(static_cast<u8 *>(Res), Nmemb * Size); - return Res; -} - -INTERCEPTOR(void, free, void *P) { - // There are only a few early allocation requests, so we simply skip the free. - if (isInEarlyAllocBuf(P)) - return; - REAL(free)(P); -} - -INTERCEPTOR(void *, valloc, uptr Size) { - void *const Res = REAL(valloc)(Size); - if (Res) - __nsan_set_value_unknown(static_cast<u8 *>(Res), Size); - return Res; -} - -INTERCEPTOR(void *, memalign, uptr Alignment, uptr Size) { - void *const Res = REAL(memalign)(Alignment, Size); - if (Res) - __nsan_set_value_unknown(static_cast<u8 *>(Res), Size); - return Res; -} - -INTERCEPTOR(void *, __libc_memalign, uptr Alignment, uptr Size) { - void *const Res = REAL(__libc_memalign)(Alignment, Size); - if (Res) - __nsan_set_value_unknown(static_cast<u8 *>(Res), Size); - return Res; -} - -INTERCEPTOR(void *, pvalloc, uptr Size) { - void *const Res = REAL(pvalloc)(Size); - if (Res) - __nsan_set_value_unknown(static_cast<u8 *>(Res), Size); - return Res; -} - -INTERCEPTOR(void *, aligned_alloc, uptr Alignment, uptr Size) { - void *const Res = REAL(aligned_alloc)(Alignment, Size); - if (Res) - __nsan_set_value_unknown(static_cast<u8 *>(Res), Size); - return Res; -} - -INTERCEPTOR(int, posix_memalign, void **Memptr, uptr Alignment, uptr Size) { - int Res = REAL(posix_memalign)(Memptr, Alignment, Size); - if (Res == 0 && *Memptr) - __nsan_set_value_unknown(static_cast<u8 *>(*Memptr), Size); - return Res; -} - -INTERCEPTOR(char *, strfry, char *S) { - const auto Len = internal_strlen(S); - char *Res = REAL(strfry)(S); - if (Res) - __nsan_set_value_unknown(reinterpret_cast<u8 *>(S), Len); - return Res; -} - -INTERCEPTOR(char *, strsep, char **Stringp, const char *Delim) { - char *OrigStringp = REAL(strsep)(Stringp, Delim); - if (Stringp != nullptr) { - // The previous character has been overwritten with a '\0' char. - __nsan_set_value_unknown(reinterpret_cast<u8 *>(*Stringp) - 1, 1); - } - return OrigStringp; -} - -INTERCEPTOR(char *, strtok, char *Str, const char *Delim) { - // This is overly conservative, but the probability that modern code is using - // strtok on double data is essentially zero anyway. - if (Str) - __nsan_set_value_unknown(reinterpret_cast<u8 *>(Str), internal_strlen(Str)); - return REAL(strtok)(Str, Delim); -} - -static void nsanCopyZeroTerminated(char *Dst, const char *Src, uptr N) { - __nsan_copy_values(reinterpret_cast<u8 *>(Dst), - reinterpret_cast<const u8 *>(Src), N); // Data. - __nsan_set_value_unknown(reinterpret_cast<u8 *>(Dst) + N, 1); // Terminator. -} - -static void nsanWCopyZeroTerminated(wchar_t *Dst, const wchar_t *Src, uptr N) { - __nsan_copy_values(toU8Ptr(Dst), toU8Ptr(Src), sizeof(wchar_t) * N); - __nsan_set_value_unknown(toU8Ptr(Dst + N), sizeof(wchar_t)); -} - -INTERCEPTOR(char *, strdup, const char *S) { - char *Res = REAL(strdup)(S); - if (Res) { - nsanCopyZeroTerminated(Res, S, internal_strlen(S)); - } - return Res; -} - -INTERCEPTOR(wchar_t *, wcsdup, const wchar_t *S) { - wchar_t *Res = REAL(wcsdup)(S); - if (Res) { - nsanWCopyZeroTerminated(Res, S, wcslen(S)); - } - return Res; -} - -INTERCEPTOR(char *, strndup, const char *S, uptr Size) { - char *Res = REAL(strndup)(S, Size); - if (Res) { - nsanCopyZeroTerminated(Res, S, min(internal_strlen(S), Size)); - } - return Res; -} - -INTERCEPTOR(char *, strcpy, char *Dst, const char *Src) { - char *Res = REAL(strcpy)(Dst, Src); - nsanCopyZeroTerminated(Dst, Src, internal_strlen(Src)); - return Res; -} - -INTERCEPTOR(wchar_t *, wcscpy, wchar_t *Dst, const wchar_t *Src) { - wchar_t *Res = REAL(wcscpy)(Dst, Src); - nsanWCopyZeroTerminated(Dst, Src, wcslen(Src)); - return Res; -} - -INTERCEPTOR(char *, strncpy, char *Dst, const char *Src, uptr Size) { - char *Res = REAL(strncpy)(Dst, Src, Size); - nsanCopyZeroTerminated(Dst, Src, min(Size, internal_strlen(Src))); - return Res; -} - -INTERCEPTOR(char *, strcat, char *Dst, const char *Src) { - const auto DstLenBeforeCat = internal_strlen(Dst); - char *Res = REAL(strcat)(Dst, Src); - nsanCopyZeroTerminated(Dst + DstLenBeforeCat, Src, internal_strlen(Src)); - return Res; -} - -INTERCEPTOR(wchar_t *, wcscat, wchar_t *Dst, const wchar_t *Src) { - const auto DstLenBeforeCat = wcslen(Dst); - wchar_t *Res = REAL(wcscat)(Dst, Src); - nsanWCopyZeroTerminated(Dst + DstLenBeforeCat, Src, wcslen(Src)); - return Res; -} - -INTERCEPTOR(char *, strncat, char *Dst, const char *Src, uptr Size) { - const auto DstLen = internal_strlen(Dst); - char *Res = REAL(strncat)(Dst, Src, Size); - nsanCopyZeroTerminated(Dst + DstLen, Src, min(Size, internal_strlen(Src))); - return Res; -} - -INTERCEPTOR(char *, stpcpy, char *Dst, const char *Src) { - char *Res = REAL(stpcpy)(Dst, Src); - nsanCopyZeroTerminated(Dst, Src, internal_strlen(Src)); - return Res; -} - -INTERCEPTOR(wchar_t *, wcpcpy, wchar_t *Dst, const wchar_t *Src) { - wchar_t *Res = REAL(wcpcpy)(Dst, Src); - nsanWCopyZeroTerminated(Dst, Src, wcslen(Src)); - return Res; -} - -INTERCEPTOR(uptr, strxfrm, char *Dst, const char *Src, uptr Size) { - // This is overly conservative, but this function should very rarely be used. - __nsan_set_value_unknown(reinterpret_cast<u8 *>(Dst), internal_strlen(Dst)); - const uptr Res = REAL(strxfrm)(Dst, Src, Size); - return Res; -} - -namespace __nsan { -void initializeInterceptors() { - static bool Initialized = false; - CHECK(!Initialized); - - // Instruct libc malloc to consume less memory. -#if SANITIZER_LINUX - mallopt(1, 0); // M_MXFAST - mallopt(-3, 32 * 1024); // M_MMAP_THRESHOLD -#endif - - INTERCEPT_FUNCTION(malloc); - INTERCEPT_FUNCTION(calloc); - INTERCEPT_FUNCTION(free); - INTERCEPT_FUNCTION(realloc); - INTERCEPT_FUNCTION(valloc); - INTERCEPT_FUNCTION(memalign); - INTERCEPT_FUNCTION(__libc_memalign); - INTERCEPT_FUNCTION(pvalloc); - INTERCEPT_FUNCTION(aligned_alloc); - INTERCEPT_FUNCTION(posix_memalign); - - INTERCEPT_FUNCTION(memset); - INTERCEPT_FUNCTION(wmemset); - INTERCEPT_FUNCTION(memmove); - INTERCEPT_FUNCTION(wmemmove); - INTERCEPT_FUNCTION(memcpy); - INTERCEPT_FUNCTION(wmemcpy); - - INTERCEPT_FUNCTION(strdup); - INTERCEPT_FUNCTION(wcsdup); - INTERCEPT_FUNCTION(strndup); - INTERCEPT_FUNCTION(stpcpy); - INTERCEPT_FUNCTION(wcpcpy); - INTERCEPT_FUNCTION(strcpy); - INTERCEPT_FUNCTION(wcscpy); - INTERCEPT_FUNCTION(strncpy); - INTERCEPT_FUNCTION(strcat); - INTERCEPT_FUNCTION(wcscat); - INTERCEPT_FUNCTION(strncat); - INTERCEPT_FUNCTION(strxfrm); - - INTERCEPT_FUNCTION(strfry); - INTERCEPT_FUNCTION(strsep); - INTERCEPT_FUNCTION(strtok); - - Initialized = 1; -} -} // end namespace __nsan diff --git a/compiler-rt/lib/nsan/nsan_interceptors.cpp b/compiler-rt/lib/nsan/nsan_interceptors.cpp new file mode 100644 index 0000000..68127f1 --- /dev/null +++ b/compiler-rt/lib/nsan/nsan_interceptors.cpp @@ -0,0 +1,356 @@ +//===-- nsan_interceptors.cc ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Interceptors for standard library functions. +// +// A note about `printf`: Make sure none of the interceptor code calls any +// part of the nsan framework that can call `printf`, since this could create +// a loop (`printf` itself uses the libc). printf-free functions are documented +// as such in nsan.h. +// +//===----------------------------------------------------------------------===// + +#include "interception/interception.h" +#include "nsan/nsan.h" +#include "sanitizer_common/sanitizer_common.h" + +#include <wchar.h> + +#if SANITIZER_LINUX +extern "C" int mallopt(int param, int value); +#endif + +using namespace __sanitizer; +using __nsan::nsan_init_is_running; +using __nsan::nsan_initialized; + +constexpr uptr kEarlyAllocBufSize = 16384; +static uptr allocated_bytes; +static char early_alloc_buf[kEarlyAllocBufSize]; + +static bool isInEarlyAllocBuf(const void *ptr) { + return ((uptr)ptr >= (uptr)early_alloc_buf && + ((uptr)ptr - (uptr)early_alloc_buf) < sizeof(early_alloc_buf)); +} + +template <typename T> T min(T a, T b) { return a < b ? a : b; } + +// Handle allocation requests early (before all interceptors are setup). dlsym, +// for example, calls calloc. +static void *HandleEarlyAlloc(uptr size) { + void *Mem = (void *)&early_alloc_buf[allocated_bytes]; + allocated_bytes += size; + CHECK_LT(allocated_bytes, kEarlyAllocBufSize); + return Mem; +} + +INTERCEPTOR(void *, memset, void *dst, int v, uptr size) { + // NOTE: This guard is needed because nsan's initialization code might call + // memset. + if (!nsan_initialized && REAL(memset) == nullptr) + return internal_memset(dst, v, size); + + void *res = REAL(memset)(dst, v, size); + __nsan_set_value_unknown(static_cast<u8 *>(dst), size); + return res; +} + +INTERCEPTOR(wchar_t *, wmemset, wchar_t *dst, wchar_t v, uptr size) { + wchar_t *res = REAL(wmemset)(dst, v, size); + __nsan_set_value_unknown((u8 *)dst, sizeof(wchar_t) * size); + return res; +} + +INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) { + // NOTE: This guard is needed because nsan's initialization code might call + // memmove. + if (!nsan_initialized && REAL(memmove) == nullptr) + return internal_memmove(dst, src, size); + + void *res = REAL(memmove)(dst, src, size); + __nsan_copy_values(static_cast<u8 *>(dst), static_cast<const u8 *>(src), + size); + return res; +} + +INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dst, const wchar_t *src, uptr size) { + wchar_t *res = REAL(wmemmove)(dst, src, size); + __nsan_copy_values((u8 *)dst, (const u8 *)src, sizeof(wchar_t) * size); + return res; +} + +INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) { + // NOTE: This guard is needed because nsan's initialization code might call + // memcpy. + if (!nsan_initialized && REAL(memcpy) == nullptr) { + // memmove is used here because on some platforms this will also + // intercept the memmove implementation. + return internal_memmove(dst, src, size); + } + + void *res = REAL(memcpy)(dst, src, size); + __nsan_copy_values(static_cast<u8 *>(dst), static_cast<const u8 *>(src), + size); + return res; +} + +INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dst, const wchar_t *src, uptr size) { + wchar_t *res = REAL(wmemcpy)(dst, src, size); + __nsan_copy_values((u8 *)dst, (const u8 *)src, sizeof(wchar_t) * size); + return res; +} + +INTERCEPTOR(void *, malloc, uptr size) { + // NOTE: This guard is needed because nsan's initialization code might call + // malloc. + if (nsan_init_is_running && REAL(malloc) == nullptr) + return HandleEarlyAlloc(size); + + void *res = REAL(malloc)(size); + if (res) + __nsan_set_value_unknown(static_cast<u8 *>(res), size); + return res; +} + +INTERCEPTOR(void *, realloc, void *ptr, uptr size) { + void *res = REAL(realloc)(ptr, size); + // FIXME: We might want to copy the types from the original allocation + // (although that would require that we know its size). + if (res) + __nsan_set_value_unknown(static_cast<u8 *>(res), size); + return res; +} + +INTERCEPTOR(void *, calloc, uptr Nmemb, uptr size) { + // NOTE: This guard is needed because nsan's initialization code might call + // calloc. + if (nsan_init_is_running && REAL(calloc) == nullptr) { + // Note: EarlyAllocBuf is initialized with zeros. + return HandleEarlyAlloc(Nmemb * size); + } + + void *res = REAL(calloc)(Nmemb, size); + if (res) + __nsan_set_value_unknown(static_cast<u8 *>(res), Nmemb * size); + return res; +} + +INTERCEPTOR(void, free, void *P) { + // There are only a few early allocation requests, so we simply skip the free. + if (isInEarlyAllocBuf(P)) + return; + REAL(free)(P); +} + +INTERCEPTOR(void *, valloc, uptr size) { + void *const res = REAL(valloc)(size); + if (res) + __nsan_set_value_unknown(static_cast<u8 *>(res), size); + return res; +} + +INTERCEPTOR(void *, memalign, uptr align, uptr size) { + void *const res = REAL(memalign)(align, size); + if (res) + __nsan_set_value_unknown(static_cast<u8 *>(res), size); + return res; +} + +INTERCEPTOR(void *, __libc_memalign, uptr align, uptr size) { + void *const res = REAL(__libc_memalign)(align, size); + if (res) + __nsan_set_value_unknown(static_cast<u8 *>(res), size); + return res; +} + +INTERCEPTOR(void *, pvalloc, uptr size) { + void *const res = REAL(pvalloc)(size); + if (res) + __nsan_set_value_unknown(static_cast<u8 *>(res), size); + return res; +} + +INTERCEPTOR(void *, aligned_alloc, uptr align, uptr size) { + void *const res = REAL(aligned_alloc)(align, size); + if (res) + __nsan_set_value_unknown(static_cast<u8 *>(res), size); + return res; +} + +INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr size) { + int res = REAL(posix_memalign)(memptr, align, size); + if (res == 0 && *memptr) + __nsan_set_value_unknown(static_cast<u8 *>(*memptr), size); + return res; +} + +INTERCEPTOR(char *, strfry, char *s) { + const auto Len = internal_strlen(s); + char *res = REAL(strfry)(s); + if (res) + __nsan_set_value_unknown(reinterpret_cast<u8 *>(s), Len); + return res; +} + +INTERCEPTOR(char *, strsep, char **Stringp, const char *delim) { + char *OrigStringp = REAL(strsep)(Stringp, delim); + if (Stringp != nullptr) { + // The previous character has been overwritten with a '\0' char. + __nsan_set_value_unknown(reinterpret_cast<u8 *>(*Stringp) - 1, 1); + } + return OrigStringp; +} + +INTERCEPTOR(char *, strtok, char *str, const char *delim) { + // This is overly conservative, but the probability that modern code is using + // strtok on double data is essentially zero anyway. + if (str) + __nsan_set_value_unknown(reinterpret_cast<u8 *>(str), internal_strlen(str)); + return REAL(strtok)(str, delim); +} + +static void nsanCopyZeroTerminated(char *dst, const char *src, uptr n) { + __nsan_copy_values(reinterpret_cast<u8 *>(dst), + reinterpret_cast<const u8 *>(src), n); // Data. + __nsan_set_value_unknown(reinterpret_cast<u8 *>(dst) + n, 1); // Terminator. +} + +static void nsanWCopyZeroTerminated(wchar_t *dst, const wchar_t *src, uptr n) { + __nsan_copy_values((u8 *)dst, (const u8 *)(src), sizeof(wchar_t) * n); + __nsan_set_value_unknown((u8 *)(dst + n), sizeof(wchar_t)); +} + +INTERCEPTOR(char *, strdup, const char *S) { + char *res = REAL(strdup)(S); + if (res) { + nsanCopyZeroTerminated(res, S, internal_strlen(S)); + } + return res; +} + +INTERCEPTOR(wchar_t *, wcsdup, const wchar_t *S) { + wchar_t *res = REAL(wcsdup)(S); + if (res) { + nsanWCopyZeroTerminated(res, S, wcslen(S)); + } + return res; +} + +INTERCEPTOR(char *, strndup, const char *S, uptr size) { + char *res = REAL(strndup)(S, size); + if (res) { + nsanCopyZeroTerminated(res, S, min(internal_strlen(S), size)); + } + return res; +} + +INTERCEPTOR(char *, strcpy, char *dst, const char *src) { + char *res = REAL(strcpy)(dst, src); + nsanCopyZeroTerminated(dst, src, internal_strlen(src)); + return res; +} + +INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dst, const wchar_t *src) { + wchar_t *res = REAL(wcscpy)(dst, src); + nsanWCopyZeroTerminated(dst, src, wcslen(src)); + return res; +} + +INTERCEPTOR(char *, strncpy, char *dst, const char *src, uptr size) { + char *res = REAL(strncpy)(dst, src, size); + nsanCopyZeroTerminated(dst, src, min(size, internal_strlen(src))); + return res; +} + +INTERCEPTOR(char *, strcat, char *dst, const char *src) { + const auto DstLenBeforeCat = internal_strlen(dst); + char *res = REAL(strcat)(dst, src); + nsanCopyZeroTerminated(dst + DstLenBeforeCat, src, internal_strlen(src)); + return res; +} + +INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) { + const auto DstLenBeforeCat = wcslen(dst); + wchar_t *res = REAL(wcscat)(dst, src); + nsanWCopyZeroTerminated(dst + DstLenBeforeCat, src, wcslen(src)); + return res; +} + +INTERCEPTOR(char *, strncat, char *dst, const char *src, uptr size) { + const auto DstLen = internal_strlen(dst); + char *res = REAL(strncat)(dst, src, size); + nsanCopyZeroTerminated(dst + DstLen, src, min(size, internal_strlen(src))); + return res; +} + +INTERCEPTOR(char *, stpcpy, char *dst, const char *src) { + char *res = REAL(stpcpy)(dst, src); + nsanCopyZeroTerminated(dst, src, internal_strlen(src)); + return res; +} + +INTERCEPTOR(wchar_t *, wcpcpy, wchar_t *dst, const wchar_t *src) { + wchar_t *res = REAL(wcpcpy)(dst, src); + nsanWCopyZeroTerminated(dst, src, wcslen(src)); + return res; +} + +INTERCEPTOR(uptr, strxfrm, char *dst, const char *src, uptr size) { + // This is overly conservative, but this function should very rarely be used. + __nsan_set_value_unknown(reinterpret_cast<u8 *>(dst), internal_strlen(dst)); + const uptr res = REAL(strxfrm)(dst, src, size); + return res; +} + +void __nsan::InitializeInterceptors() { + static bool initialized = false; + CHECK(!initialized); + + // Instruct libc malloc to consume less memory. +#if SANITIZER_LINUX + mallopt(1, 0); // M_MXFAST + mallopt(-3, 32 * 1024); // M_MMAP_THRESHOLD +#endif + + INTERCEPT_FUNCTION(malloc); + INTERCEPT_FUNCTION(calloc); + INTERCEPT_FUNCTION(free); + INTERCEPT_FUNCTION(realloc); + INTERCEPT_FUNCTION(valloc); + INTERCEPT_FUNCTION(memalign); + INTERCEPT_FUNCTION(__libc_memalign); + INTERCEPT_FUNCTION(pvalloc); + INTERCEPT_FUNCTION(aligned_alloc); + INTERCEPT_FUNCTION(posix_memalign); + + INTERCEPT_FUNCTION(memset); + INTERCEPT_FUNCTION(wmemset); + INTERCEPT_FUNCTION(memmove); + INTERCEPT_FUNCTION(wmemmove); + INTERCEPT_FUNCTION(memcpy); + INTERCEPT_FUNCTION(wmemcpy); + + INTERCEPT_FUNCTION(strdup); + INTERCEPT_FUNCTION(wcsdup); + INTERCEPT_FUNCTION(strndup); + INTERCEPT_FUNCTION(stpcpy); + INTERCEPT_FUNCTION(wcpcpy); + INTERCEPT_FUNCTION(strcpy); + INTERCEPT_FUNCTION(wcscpy); + INTERCEPT_FUNCTION(strncpy); + INTERCEPT_FUNCTION(strcat); + INTERCEPT_FUNCTION(wcscat); + INTERCEPT_FUNCTION(strncat); + INTERCEPT_FUNCTION(strxfrm); + + INTERCEPT_FUNCTION(strfry); + INTERCEPT_FUNCTION(strsep); + INTERCEPT_FUNCTION(strtok); + + initialized = 1; +} diff --git a/compiler-rt/lib/nsan/nsan_stats.cc b/compiler-rt/lib/nsan/nsan_stats.cc deleted file mode 100644 index 4e7a0c5..0000000 --- a/compiler-rt/lib/nsan/nsan_stats.cc +++ /dev/null @@ -1,158 +0,0 @@ -//===-- nsan_stats.cc -----------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file is a part of NumericalStabilitySanitizer. -// -// NumericalStabilitySanitizer statistics. -//===----------------------------------------------------------------------===// - -#include "nsan/nsan_stats.h" - -#include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_placement_new.h" -#include "sanitizer_common/sanitizer_stackdepot.h" -#include "sanitizer_common/sanitizer_stacktrace.h" -#include "sanitizer_common/sanitizer_symbolizer.h" - -#include <assert.h> -#include <stdio.h> - -namespace __nsan { - -using namespace __sanitizer; - -Stats::Stats() { - CheckAndWarnings.Initialize(0); - TrackedLoads.Initialize(0); -} - -Stats::~Stats() { Printf("deleting nsan stats\n"); } - -static uptr key(CheckTypeT CheckType, u32 StackId) { - return static_cast<uptr>(CheckType) + - StackId * static_cast<uptr>(CheckTypeT::kMaxCheckType); -} - -template <typename MapT, typename VectorT, typename Fn> -void UpdateEntry(CheckTypeT CheckTy, uptr PC, uptr BP, MapT *Map, - VectorT *Vector, Mutex *Mutex, Fn F) { - BufferedStackTrace Stack; - Stack.Unwind(PC, BP, nullptr, false); - u32 StackId = StackDepotPut(Stack); - typename MapT::Handle Handle(Map, key(CheckTy, StackId)); - Lock L(Mutex); - if (Handle.created()) { - typename VectorT::value_type Entry; - Entry.StackId = StackId; - Entry.CheckTy = CheckTy; - F(Entry); - Vector->push_back(Entry); - } else { - auto &Entry = (*Vector)[*Handle]; - F(Entry); - } -} - -void Stats::addCheck(CheckTypeT CheckTy, uptr PC, uptr BP, double RelErr) { - UpdateEntry(CheckTy, PC, BP, &CheckAndWarningsMap, &CheckAndWarnings, - &CheckAndWarningsMutex, [RelErr](CheckAndWarningsValue &Entry) { - ++Entry.NumChecks; - if (RelErr > Entry.MaxRelativeError) { - Entry.MaxRelativeError = RelErr; - } - }); -} - -void Stats::addWarning(CheckTypeT CheckTy, uptr PC, uptr BP, double RelErr) { - UpdateEntry(CheckTy, PC, BP, &CheckAndWarningsMap, &CheckAndWarnings, - &CheckAndWarningsMutex, [RelErr](CheckAndWarningsValue &Entry) { - ++Entry.NumWarnings; - if (RelErr > Entry.MaxRelativeError) { - Entry.MaxRelativeError = RelErr; - } - }); -} - -void Stats::addInvalidLoadTrackingEvent(uptr PC, uptr BP) { - UpdateEntry(CheckTypeT::kLoad, PC, BP, &LoadTrackingMap, &TrackedLoads, - &TrackedLoadsMutex, - [](LoadTrackingValue &Entry) { ++Entry.NumInvalid; }); -} - -void Stats::addUnknownLoadTrackingEvent(uptr PC, uptr BP) { - UpdateEntry(CheckTypeT::kLoad, PC, BP, &LoadTrackingMap, &TrackedLoads, - &TrackedLoadsMutex, - [](LoadTrackingValue &Entry) { ++Entry.NumUnknown; }); -} - -static const char *CheckTypeDisplay(CheckTypeT CheckType) { - switch (CheckType) { - case CheckTypeT::kUnknown: - return "unknown"; - case CheckTypeT::kRet: - return "return"; - case CheckTypeT::kArg: - return "argument"; - case CheckTypeT::kLoad: - return "load"; - case CheckTypeT::kStore: - return "store"; - case CheckTypeT::kInsert: - return "vector insert"; - case CheckTypeT::kUser: - return "user-initiated"; - case CheckTypeT::kFcmp: - return "fcmp"; - case CheckTypeT::kMaxCheckType: - return "[max]"; - } - assert(false && "unknown CheckType case"); - return ""; -} - -void Stats::print() const { - { - Lock L(&CheckAndWarningsMutex); - for (const auto &Entry : CheckAndWarnings) { - Printf("warned %llu times out of %llu %s checks ", Entry.NumWarnings, - Entry.NumChecks, CheckTypeDisplay(Entry.CheckTy)); - if (Entry.NumWarnings > 0) { - char RelErrBuf[64]; - snprintf(RelErrBuf, sizeof(RelErrBuf) - 1, "%f", - Entry.MaxRelativeError * 100.0); - Printf("(max relative error: %s%%) ", RelErrBuf); - } - Printf("at:\n"); - StackDepotGet(Entry.StackId).Print(); - } - } - - { - Lock L(&TrackedLoadsMutex); - u64 TotalInvalidLoadTracking = 0; - u64 TotalUnknownLoadTracking = 0; - for (const auto &Entry : TrackedLoads) { - TotalInvalidLoadTracking += Entry.NumInvalid; - TotalUnknownLoadTracking += Entry.NumUnknown; - Printf("invalid/unknown type for %llu/%llu loads at:\n", Entry.NumInvalid, - Entry.NumUnknown); - StackDepotGet(Entry.StackId).Print(); - } - Printf( - "There were %llu/%llu floating-point loads where the shadow type was " - "invalid/unknown.\n", - TotalInvalidLoadTracking, TotalUnknownLoadTracking); - } -} - -ALIGNED(64) static char StatsPlaceholder[sizeof(Stats)]; -Stats *nsan_stats = nullptr; - -void initializeStats() { nsan_stats = new (StatsPlaceholder) Stats(); } - -} // namespace __nsan diff --git a/compiler-rt/lib/nsan/nsan_stats.cpp b/compiler-rt/lib/nsan/nsan_stats.cpp new file mode 100644 index 0000000..d188df1 --- /dev/null +++ b/compiler-rt/lib/nsan/nsan_stats.cpp @@ -0,0 +1,157 @@ +//===-- nsan_stats.cc -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of NumericalStabilitySanitizer. +// +// NumericalStabilitySanitizer statistics. +//===----------------------------------------------------------------------===// + +#include "nsan/nsan_stats.h" + +#include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_placement_new.h" +#include "sanitizer_common/sanitizer_stackdepot.h" +#include "sanitizer_common/sanitizer_stacktrace.h" +#include "sanitizer_common/sanitizer_symbolizer.h" + +#include <assert.h> +#include <stdio.h> + +using namespace __sanitizer; +using namespace __nsan; + +Stats::Stats() { + check_and_warnings.Initialize(0); + TrackedLoads.Initialize(0); +} + +Stats::~Stats() { Printf("deleting nsan stats\n"); } + +static uptr Key(CheckTypeT CheckType, u32 StackId) { + return static_cast<uptr>(CheckType) + + StackId * static_cast<uptr>(CheckTypeT::kMaxCheckType); +} + +template <typename MapT, typename VectorT, typename Fn> +static void UpdateEntry(CheckTypeT check_ty, uptr pc, uptr bp, MapT *map, + VectorT *vector, Mutex *mutex, Fn F) { + BufferedStackTrace Stack; + Stack.Unwind(pc, bp, nullptr, false); + u32 stack_id = StackDepotPut(Stack); + typename MapT::Handle Handle(map, Key(check_ty, stack_id)); + Lock L(mutex); + if (Handle.created()) { + typename VectorT::value_type entry; + entry.stack_id = stack_id; + entry.check_ty = check_ty; + F(entry); + vector->push_back(entry); + } else { + auto &entry = (*vector)[*Handle]; + F(entry); + } +} + +void Stats::AddCheck(CheckTypeT check_ty, uptr pc, uptr bp, double rel_err) { + UpdateEntry(check_ty, pc, bp, &CheckAndWarningsMap, &check_and_warnings, + &check_and_warning_mutex, + [rel_err](CheckAndWarningsValue &entry) { + ++entry.num_checks; + if (rel_err > entry.max_relative_err) { + entry.max_relative_err = rel_err; + } + }); +} + +void Stats::AddWarning(CheckTypeT check_ty, uptr pc, uptr bp, double rel_err) { + UpdateEntry(check_ty, pc, bp, &CheckAndWarningsMap, &check_and_warnings, + &check_and_warning_mutex, + [rel_err](CheckAndWarningsValue &entry) { + ++entry.num_warnings; + if (rel_err > entry.max_relative_err) { + entry.max_relative_err = rel_err; + } + }); +} + +void Stats::AddInvalidLoadTrackingEvent(uptr pc, uptr bp) { + UpdateEntry(CheckTypeT::kLoad, pc, bp, &LoadTrackingMap, &TrackedLoads, + &TrackedLoadsMutex, + [](LoadTrackingValue &entry) { ++entry.num_invalid; }); +} + +void Stats::AddUnknownLoadTrackingEvent(uptr pc, uptr bp) { + UpdateEntry(CheckTypeT::kLoad, pc, bp, &LoadTrackingMap, &TrackedLoads, + &TrackedLoadsMutex, + [](LoadTrackingValue &entry) { ++entry.num_unknown; }); +} + +static const char *CheckTypeDisplay(CheckTypeT CheckType) { + switch (CheckType) { + case CheckTypeT::kUnknown: + return "unknown"; + case CheckTypeT::kRet: + return "return"; + case CheckTypeT::kArg: + return "argument"; + case CheckTypeT::kLoad: + return "load"; + case CheckTypeT::kStore: + return "store"; + case CheckTypeT::kInsert: + return "vector insert"; + case CheckTypeT::kUser: + return "user-initiated"; + case CheckTypeT::kFcmp: + return "fcmp"; + case CheckTypeT::kMaxCheckType: + return "[max]"; + } + assert(false && "unknown CheckType case"); + return ""; +} + +void Stats::Print() const { + { + Lock L(&check_and_warning_mutex); + for (const auto &entry : check_and_warnings) { + Printf("warned %llu times out of %llu %s checks ", entry.num_warnings, + entry.num_checks, CheckTypeDisplay(entry.check_ty)); + if (entry.num_warnings > 0) { + char RelErrBuf[64]; + snprintf(RelErrBuf, sizeof(RelErrBuf) - 1, "%f", + entry.max_relative_err * 100.0); + Printf("(max relative error: %s%%) ", RelErrBuf); + } + Printf("at:\n"); + StackDepotGet(entry.stack_id).Print(); + } + } + + { + Lock L(&TrackedLoadsMutex); + u64 TotalInvalidLoadTracking = 0; + u64 TotalUnknownLoadTracking = 0; + for (const auto &entry : TrackedLoads) { + TotalInvalidLoadTracking += entry.num_invalid; + TotalUnknownLoadTracking += entry.num_unknown; + Printf("invalid/unknown type for %llu/%llu loads at:\n", + entry.num_invalid, entry.num_unknown); + StackDepotGet(entry.stack_id).Print(); + } + Printf( + "There were %llu/%llu floating-point loads where the shadow type was " + "invalid/unknown.\n", + TotalInvalidLoadTracking, TotalUnknownLoadTracking); + } +} + +alignas(64) static char stats_placeholder[sizeof(Stats)]; +Stats *__nsan::nsan_stats = nullptr; + +void __nsan::InitializeStats() { nsan_stats = new (stats_placeholder) Stats(); } diff --git a/compiler-rt/lib/nsan/nsan_stats.h b/compiler-rt/lib/nsan/nsan_stats.h index 7e8c7bb..d1c7e01 100644 --- a/compiler-rt/lib/nsan/nsan_stats.h +++ b/compiler-rt/lib/nsan/nsan_stats.h @@ -40,52 +40,53 @@ public: ~Stats(); // Signal that we checked the instruction at the given address. - void addCheck(CheckTypeT CheckType, __sanitizer::uptr PC, - __sanitizer::uptr BP, double RelErr); + void AddCheck(CheckTypeT check_ty, __sanitizer::uptr pc, __sanitizer::uptr bp, + double rel_err); // Signal that we warned for the instruction at the given address. - void addWarning(CheckTypeT CheckType, __sanitizer::uptr PC, - __sanitizer::uptr BP, double RelErr); + void AddWarning(CheckTypeT check_ty, __sanitizer::uptr pc, + __sanitizer::uptr bp, double rel_err); // Signal that we detected a floating-point load where the shadow type was // invalid. - void addInvalidLoadTrackingEvent(__sanitizer::uptr PC, __sanitizer::uptr BP); + void AddInvalidLoadTrackingEvent(__sanitizer::uptr pc, __sanitizer::uptr bp); // Signal that we detected a floating-point load where the shadow type was // unknown but the value was nonzero. - void addUnknownLoadTrackingEvent(__sanitizer::uptr PC, __sanitizer::uptr BP); + void AddUnknownLoadTrackingEvent(__sanitizer::uptr pc, __sanitizer::uptr bp); - void print() const; + void Print() const; private: using IndexMap = __sanitizer::AddrHashMap<__sanitizer::uptr, 11>; struct CheckAndWarningsValue { - CheckTypeT CheckTy; - __sanitizer::u32 StackId = 0; - __sanitizer::u64 NumChecks = 0; - __sanitizer::u64 NumWarnings = 0; + CheckTypeT check_ty; + __sanitizer::u32 stack_id = 0; + __sanitizer::u64 num_checks = 0; + __sanitizer::u64 num_warnings = 0; // This is a bitcasted double. Doubles have the nice idea to be ordered as // ints. - double MaxRelativeError = 0; + double max_relative_err = 0; }; - // Maps key(CheckType, StackId) to indices in CheckAndWarnings. + // Map Key(check_ty, StackId) to indices in CheckAndWarnings. IndexMap CheckAndWarningsMap; - __sanitizer::InternalMmapVectorNoCtor<CheckAndWarningsValue> CheckAndWarnings; - mutable __sanitizer::Mutex CheckAndWarningsMutex; + __sanitizer::InternalMmapVectorNoCtor<CheckAndWarningsValue> + check_and_warnings; + mutable __sanitizer::Mutex check_and_warning_mutex; struct LoadTrackingValue { - CheckTypeT CheckTy; - __sanitizer::u32 StackId = 0; - __sanitizer::u64 NumInvalid = 0; - __sanitizer::u64 NumUnknown = 0; + CheckTypeT check_ty; + __sanitizer::u32 stack_id = 0; + __sanitizer::u64 num_invalid = 0; + __sanitizer::u64 num_unknown = 0; }; - // Maps key(CheckTypeT::kLoad, StackId) to indices in TrackedLoads. + // Map Key(CheckTypeT::kLoad, StackId) to indices in TrackedLoads. IndexMap LoadTrackingMap; __sanitizer::InternalMmapVectorNoCtor<LoadTrackingValue> TrackedLoads; mutable __sanitizer::Mutex TrackedLoadsMutex; }; extern Stats *nsan_stats; -void initializeStats(); +void InitializeStats(); } // namespace __nsan diff --git a/compiler-rt/lib/nsan/nsan_suppressions.cc b/compiler-rt/lib/nsan/nsan_suppressions.cc deleted file mode 100644 index 9529a8e..0000000 --- a/compiler-rt/lib/nsan/nsan_suppressions.cc +++ /dev/null @@ -1,77 +0,0 @@ -//===-- nsan_suppressions.cc ----------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "nsan_suppressions.h" - -#include "sanitizer_common/sanitizer_placement_new.h" -#include "sanitizer_common/sanitizer_stacktrace.h" -#include "sanitizer_common/sanitizer_symbolizer.h" - -#include "nsan_flags.h" - -// Can be overriden in frontend. -SANITIZER_WEAK_DEFAULT_IMPL -const char *__nsan_default_suppressions() { return 0; } - -namespace __nsan { - -const char *const kSuppressionFcmp = "fcmp"; -const char *const kSuppressionConsistency = "consistency"; - -using namespace __sanitizer; - -ALIGNED(64) static char SuppressionPlaceholder[sizeof(SuppressionContext)]; -static SuppressionContext *SuppressionCtx = nullptr; - -// The order should match the enum CheckKind. -static const char *kSuppressionTypes[] = {kSuppressionFcmp, - kSuppressionConsistency}; - -void InitializeSuppressions() { - CHECK_EQ(nullptr, SuppressionCtx); - SuppressionCtx = new (SuppressionPlaceholder) - SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes)); - SuppressionCtx->ParseFromFile(flags().suppressions); - SuppressionCtx->Parse(__nsan_default_suppressions()); -} - -static Suppression *GetSuppressionForAddr(uptr Addr, const char *SupprType) { - Suppression *S = nullptr; - - // Suppress by module name. - SuppressionContext *Suppressions = SuppressionCtx; - if (const char *ModuleName = - Symbolizer::GetOrInit()->GetModuleNameForPc(Addr)) { - if (Suppressions->Match(ModuleName, SupprType, &S)) - return S; - } - - // Suppress by file or function name. - SymbolizedStack *Frames = Symbolizer::GetOrInit()->SymbolizePC(Addr); - for (SymbolizedStack *Cur = Frames; Cur; Cur = Cur->next) { - if (Suppressions->Match(Cur->info.function, SupprType, &S) || - Suppressions->Match(Cur->info.file, SupprType, &S)) { - break; - } - } - Frames->ClearAll(); - return S; -} - -Suppression *GetSuppressionForStack(const StackTrace *Stack, CheckKind K) { - for (uptr I = 0, E = Stack->size; I < E; I++) { - Suppression *S = GetSuppressionForAddr( - StackTrace::GetPreviousInstructionPc(Stack->trace[I]), - kSuppressionTypes[static_cast<int>(K)]); - if (S) - return S; - } - return nullptr; -} - -} // end namespace __nsan diff --git a/compiler-rt/lib/nsan/nsan_suppressions.cpp b/compiler-rt/lib/nsan/nsan_suppressions.cpp new file mode 100644 index 0000000..c4d438e --- /dev/null +++ b/compiler-rt/lib/nsan/nsan_suppressions.cpp @@ -0,0 +1,73 @@ +//===-- nsan_suppressions.cc ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "nsan_suppressions.h" +#include "nsan_flags.h" +#include "sanitizer_common/sanitizer_placement_new.h" +#include "sanitizer_common/sanitizer_stacktrace.h" +#include "sanitizer_common/sanitizer_symbolizer.h" + +using namespace __sanitizer; +using namespace __nsan; + +SANITIZER_INTERFACE_WEAK_DEF(const char *, __nsan_default_suppressions, void) { + return 0; +} + +const char kSuppressionFcmp[] = "fcmp"; +const char kSuppressionConsistency[] = "consistency"; + +alignas(64) static char suppression_placeholder[sizeof(SuppressionContext)]; +static SuppressionContext *suppression_ctx; + +// The order should match the enum CheckKind. +static const char *kSuppressionTypes[] = {kSuppressionFcmp, + kSuppressionConsistency}; + +void __nsan::InitializeSuppressions() { + CHECK_EQ(nullptr, suppression_ctx); + suppression_ctx = new (suppression_placeholder) + SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes)); + suppression_ctx->ParseFromFile(flags().suppressions); + suppression_ctx->Parse(__nsan_default_suppressions()); +} + +static Suppression *GetSuppressionForAddr(uptr addr, const char *suppr_type) { + Suppression *s = nullptr; + + // Suppress by module name. + SuppressionContext *suppressions = suppression_ctx; + if (const char *moduleName = + Symbolizer::GetOrInit()->GetModuleNameForPc(addr)) { + if (suppressions->Match(moduleName, suppr_type, &s)) + return s; + } + + // Suppress by file or function name. + SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(addr); + for (SymbolizedStack *cur = frames; cur; cur = cur->next) { + if (suppressions->Match(cur->info.function, suppr_type, &s) || + suppressions->Match(cur->info.file, suppr_type, &s)) { + break; + } + } + frames->ClearAll(); + return s; +} + +Suppression *__nsan::GetSuppressionForStack(const StackTrace *stack, + CheckKind k) { + for (uptr i = 0, e = stack->size; i < e; i++) { + Suppression *s = GetSuppressionForAddr( + StackTrace::GetPreviousInstructionPc(stack->trace[i]), + kSuppressionTypes[static_cast<int>(k)]); + if (s) + return s; + } + return nullptr; +} diff --git a/compiler-rt/lib/nsan/tests/NSanUnitTest.cpp b/compiler-rt/lib/nsan/tests/NSanUnitTest.cpp index 3c6b505..d121292 100644 --- a/compiler-rt/lib/nsan/tests/NSanUnitTest.cpp +++ b/compiler-rt/lib/nsan/tests/NSanUnitTest.cpp @@ -14,41 +14,41 @@ namespace __nsan { template <typename FT, auto next> void TestFT() { // Basic local tests anchored at 0.0. - ASSERT_EQ(getULPDiff<FT>(0.0, 0.0), 0); - ASSERT_EQ(getULPDiff<FT>(-0.0, 0.0), 0); - ASSERT_EQ(getULPDiff<FT>(next(-0.0, -1.0), 0.0), 1); - ASSERT_EQ(getULPDiff<FT>(next(0.0, 1.0), -0.0), 1); - ASSERT_EQ(getULPDiff<FT>(next(-0.0, -1.0), next(0.0, 1.0)), 2); + ASSERT_EQ(GetULPDiff<FT>(0.0, 0.0), 0); + ASSERT_EQ(GetULPDiff<FT>(-0.0, 0.0), 0); + ASSERT_EQ(GetULPDiff<FT>(next(-0.0, -1.0), 0.0), 1); + ASSERT_EQ(GetULPDiff<FT>(next(0.0, 1.0), -0.0), 1); + ASSERT_EQ(GetULPDiff<FT>(next(-0.0, -1.0), next(0.0, 1.0)), 2); // Basic local tests anchored at 2.0. - ASSERT_EQ(getULPDiff<FT>(next(2.0, 1.0), 2.0), 1); - ASSERT_EQ(getULPDiff<FT>(next(2.0, 3.0), 2.0), 1); - ASSERT_EQ(getULPDiff<FT>(next(2.0, 1.0), next(2.0, 3.0)), 2); + ASSERT_EQ(GetULPDiff<FT>(next(2.0, 1.0), 2.0), 1); + ASSERT_EQ(GetULPDiff<FT>(next(2.0, 3.0), 2.0), 1); + ASSERT_EQ(GetULPDiff<FT>(next(2.0, 1.0), next(2.0, 3.0)), 2); - ASSERT_NE(getULPDiff<FT>(-0.01, 0.01), kMaxULPDiff); + ASSERT_NE(GetULPDiff<FT>(-0.01, 0.01), kMaxULPDiff); // Basic local tests anchored at a random number. const FT X = 4863.5123; const FT To = 2 * X; FT Y = X; - ASSERT_EQ(getULPDiff<FT>(X, Y), 0); - ASSERT_EQ(getULPDiff<FT>(-X, -Y), 0); + ASSERT_EQ(GetULPDiff<FT>(X, Y), 0); + ASSERT_EQ(GetULPDiff<FT>(-X, -Y), 0); Y = next(Y, To); - ASSERT_EQ(getULPDiff<FT>(X, Y), 1); - ASSERT_EQ(getULPDiff<FT>(-X, -Y), 1); + ASSERT_EQ(GetULPDiff<FT>(X, Y), 1); + ASSERT_EQ(GetULPDiff<FT>(-X, -Y), 1); Y = next(Y, To); - ASSERT_EQ(getULPDiff<FT>(X, Y), 2); - ASSERT_EQ(getULPDiff<FT>(-X, -Y), 2); + ASSERT_EQ(GetULPDiff<FT>(X, Y), 2); + ASSERT_EQ(GetULPDiff<FT>(-X, -Y), 2); Y = next(Y, To); - ASSERT_EQ(getULPDiff<FT>(X, Y), 3); - ASSERT_EQ(getULPDiff<FT>(-X, -Y), 3); + ASSERT_EQ(GetULPDiff<FT>(X, Y), 3); + ASSERT_EQ(GetULPDiff<FT>(-X, -Y), 3); // Values with larger differences. static constexpr const __sanitizer::u64 MantissaSize = __sanitizer::u64{1} << FTInfo<FT>::kMantissaBits; - ASSERT_EQ(getULPDiff<FT>(1.0, next(2.0, 1.0)), MantissaSize - 1); - ASSERT_EQ(getULPDiff<FT>(1.0, 2.0), MantissaSize); - ASSERT_EQ(getULPDiff<FT>(1.0, next(2.0, 3.0)), MantissaSize + 1); - ASSERT_EQ(getULPDiff<FT>(1.0, 3.0), (3 * MantissaSize) / 2); + ASSERT_EQ(GetULPDiff<FT>(1.0, next(2.0, 1.0)), MantissaSize - 1); + ASSERT_EQ(GetULPDiff<FT>(1.0, 2.0), MantissaSize); + ASSERT_EQ(GetULPDiff<FT>(1.0, next(2.0, 3.0)), MantissaSize + 1); + ASSERT_EQ(GetULPDiff<FT>(1.0, 3.0), (3 * MantissaSize) / 2); } TEST(NSanTest, Float) { TestFT<float, nextafterf>(); } @@ -59,9 +59,9 @@ TEST(NSanTest, Double) { TEST(NSanTest, Float128) { // Very basic tests. FIXME: improve when we have nextafter<__float128>. - ASSERT_EQ(getULPDiff<__float128>(0.0, 0.0), 0); - ASSERT_EQ(getULPDiff<__float128>(-0.0, 0.0), 0); - ASSERT_NE(getULPDiff<__float128>(-0.01, 0.01), kMaxULPDiff); + ASSERT_EQ(GetULPDiff<__float128>(0.0, 0.0), 0); + ASSERT_EQ(GetULPDiff<__float128>(-0.0, 0.0), 0); + ASSERT_NE(GetULPDiff<__float128>(-0.01, 0.01), kMaxULPDiff); } } // end namespace __nsan |