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