aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2024-06-20 00:46:10 -0700
committerGitHub <noreply@github.com>2024-06-20 00:46:10 -0700
commitef83c25b0e56438d1697138915273dc71b8acf82 (patch)
tree2fe8eab214814a7e8e8d8fc2e0adfd21fba468c1
parent11344249e1e8360e75490733660ee1439d571228 (diff)
downloadllvm-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.txt10
-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.h68
-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.cc364
-rw-r--r--compiler-rt/lib/nsan/nsan_interceptors.cpp356
-rw-r--r--compiler-rt/lib/nsan/nsan_stats.cc158
-rw-r--r--compiler-rt/lib/nsan/nsan_stats.cpp157
-rw-r--r--compiler-rt/lib/nsan/nsan_stats.h43
-rw-r--r--compiler-rt/lib/nsan/nsan_suppressions.cc77
-rw-r--r--compiler-rt/lib/nsan/nsan_suppressions.cpp73
-rw-r--r--compiler-rt/lib/nsan/tests/NSanUnitTest.cpp48
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