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
23namespace __nsan {
24
25enum 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
37class Stats {
38public:
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
58private:
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
88extern Stats *nsan_stats;
89void InitializeStats();
90
91} // namespace __nsan
92
93#endif // NSAN_STATS_H
94