1 //===-- nsan_stats.h --------------------------------------------*- C++- *-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of NumericalStabilitySanitizer. 10 // 11 // NSan statistics. This class counts the number of checks per code location, 12 // and is used to output statistics (typically when using 13 // `disable_warnings=1,enable_check_stats=1,enable_warning_stats=1`). 14 //===----------------------------------------------------------------------===// 15 16 #ifndef NSAN_STATS_H 17 #define NSAN_STATS_H 18 19 #include "sanitizer_common/sanitizer_addrhashmap.h" 20 #include "sanitizer_common/sanitizer_internal_defs.h" 21 #include "sanitizer_common/sanitizer_mutex.h" 22 23 namespace __nsan { 24 25 enum class CheckTypeT { 26 kUnknown = 0, 27 kRet, 28 kArg, 29 kLoad, 30 kStore, 31 kInsert, 32 kUser, // User initiated. 33 kFcmp, 34 kMaxCheckType, 35 }; 36 37 class Stats { 38 public: 39 Stats(); 40 ~Stats(); 41 42 // Signal that we checked the instruction at the given address. 43 void AddCheck(CheckTypeT check_ty, __sanitizer::uptr pc, __sanitizer::uptr bp, 44 double rel_err); 45 // Signal that we warned for the instruction at the given address. 46 void AddWarning(CheckTypeT check_ty, __sanitizer::uptr pc, 47 __sanitizer::uptr bp, double rel_err); 48 49 // Signal that we detected a floating-point load where the shadow type was 50 // invalid. 51 void AddInvalidLoadTrackingEvent(__sanitizer::uptr pc, __sanitizer::uptr bp); 52 // Signal that we detected a floating-point load where the shadow type was 53 // unknown but the value was nonzero. 54 void AddUnknownLoadTrackingEvent(__sanitizer::uptr pc, __sanitizer::uptr bp); 55 56 void Print() const; 57 58 private: 59 using IndexMap = __sanitizer::AddrHashMap<__sanitizer::uptr, 11>; 60 61 struct CheckAndWarningsValue { 62 CheckTypeT check_ty; 63 __sanitizer::u32 stack_id = 0; 64 __sanitizer::u64 num_checks = 0; 65 __sanitizer::u64 num_warnings = 0; 66 // This is a bitcasted double. Doubles have the nice idea to be ordered as 67 // ints. 68 double max_relative_err = 0; 69 }; 70 // Map Key(check_ty, StackId) to indices in CheckAndWarnings. 71 IndexMap CheckAndWarningsMap; 72 __sanitizer::InternalMmapVectorNoCtor<CheckAndWarningsValue> 73 check_and_warnings; 74 mutable __sanitizer::Mutex check_and_warning_mutex; 75 76 struct LoadTrackingValue { 77 CheckTypeT check_ty; 78 __sanitizer::u32 stack_id = 0; 79 __sanitizer::u64 num_invalid = 0; 80 __sanitizer::u64 num_unknown = 0; 81 }; 82 // Map Key(CheckTypeT::kLoad, StackId) to indices in TrackedLoads. 83 IndexMap LoadTrackingMap; 84 __sanitizer::InternalMmapVectorNoCtor<LoadTrackingValue> TrackedLoads; 85 mutable __sanitizer::Mutex TrackedLoadsMutex; 86 }; 87 88 extern Stats *nsan_stats; 89 void InitializeStats(); 90 91 } // namespace __nsan 92 93 #endif // NSAN_STATS_H 94