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