Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/nsan/nsan_stats.cpp
35233 views
1
//===-- nsan_stats.cc -----------------------------------------------------===//
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
// NumericalStabilitySanitizer statistics.
12
//===----------------------------------------------------------------------===//
13
14
#include "nsan/nsan_stats.h"
15
16
#include "sanitizer_common/sanitizer_common.h"
17
#include "sanitizer_common/sanitizer_placement_new.h"
18
#include "sanitizer_common/sanitizer_stackdepot.h"
19
#include "sanitizer_common/sanitizer_stacktrace.h"
20
#include "sanitizer_common/sanitizer_symbolizer.h"
21
22
#include <assert.h>
23
#include <stdio.h>
24
25
using namespace __sanitizer;
26
using namespace __nsan;
27
28
Stats::Stats() {
29
check_and_warnings.Initialize(0);
30
TrackedLoads.Initialize(0);
31
}
32
33
Stats::~Stats() { Printf("deleting nsan stats\n"); }
34
35
static uptr Key(CheckTypeT CheckType, u32 StackId) {
36
return static_cast<uptr>(CheckType) +
37
StackId * static_cast<uptr>(CheckTypeT::kMaxCheckType);
38
}
39
40
template <typename MapT, typename VectorT, typename Fn>
41
static void UpdateEntry(CheckTypeT check_ty, uptr pc, uptr bp, MapT *map,
42
VectorT *vector, Mutex *mutex, Fn F) {
43
BufferedStackTrace Stack;
44
Stack.Unwind(pc, bp, nullptr, false);
45
u32 stack_id = StackDepotPut(Stack);
46
typename MapT::Handle Handle(map, Key(check_ty, stack_id));
47
Lock L(mutex);
48
if (Handle.created()) {
49
typename VectorT::value_type entry;
50
entry.stack_id = stack_id;
51
entry.check_ty = check_ty;
52
F(entry);
53
vector->push_back(entry);
54
} else {
55
auto &entry = (*vector)[*Handle];
56
F(entry);
57
}
58
}
59
60
void Stats::AddCheck(CheckTypeT check_ty, uptr pc, uptr bp, double rel_err) {
61
UpdateEntry(check_ty, pc, bp, &CheckAndWarningsMap, &check_and_warnings,
62
&check_and_warning_mutex,
63
[rel_err](CheckAndWarningsValue &entry) {
64
++entry.num_checks;
65
if (rel_err > entry.max_relative_err) {
66
entry.max_relative_err = rel_err;
67
}
68
});
69
}
70
71
void Stats::AddWarning(CheckTypeT check_ty, uptr pc, uptr bp, double rel_err) {
72
UpdateEntry(check_ty, pc, bp, &CheckAndWarningsMap, &check_and_warnings,
73
&check_and_warning_mutex,
74
[rel_err](CheckAndWarningsValue &entry) {
75
++entry.num_warnings;
76
if (rel_err > entry.max_relative_err) {
77
entry.max_relative_err = rel_err;
78
}
79
});
80
}
81
82
void Stats::AddInvalidLoadTrackingEvent(uptr pc, uptr bp) {
83
UpdateEntry(CheckTypeT::kLoad, pc, bp, &LoadTrackingMap, &TrackedLoads,
84
&TrackedLoadsMutex,
85
[](LoadTrackingValue &entry) { ++entry.num_invalid; });
86
}
87
88
void Stats::AddUnknownLoadTrackingEvent(uptr pc, uptr bp) {
89
UpdateEntry(CheckTypeT::kLoad, pc, bp, &LoadTrackingMap, &TrackedLoads,
90
&TrackedLoadsMutex,
91
[](LoadTrackingValue &entry) { ++entry.num_unknown; });
92
}
93
94
static const char *CheckTypeDisplay(CheckTypeT CheckType) {
95
switch (CheckType) {
96
case CheckTypeT::kUnknown:
97
return "unknown";
98
case CheckTypeT::kRet:
99
return "return";
100
case CheckTypeT::kArg:
101
return "argument";
102
case CheckTypeT::kLoad:
103
return "load";
104
case CheckTypeT::kStore:
105
return "store";
106
case CheckTypeT::kInsert:
107
return "vector insert";
108
case CheckTypeT::kUser:
109
return "user-initiated";
110
case CheckTypeT::kFcmp:
111
return "fcmp";
112
case CheckTypeT::kMaxCheckType:
113
return "[max]";
114
}
115
assert(false && "unknown CheckType case");
116
return "";
117
}
118
119
void Stats::Print() const {
120
{
121
Lock L(&check_and_warning_mutex);
122
for (const auto &entry : check_and_warnings) {
123
Printf("warned %llu times out of %llu %s checks ", entry.num_warnings,
124
entry.num_checks, CheckTypeDisplay(entry.check_ty));
125
if (entry.num_warnings > 0) {
126
char RelErrBuf[64];
127
snprintf(RelErrBuf, sizeof(RelErrBuf) - 1, "%f",
128
entry.max_relative_err * 100.0);
129
Printf("(max relative error: %s%%) ", RelErrBuf);
130
}
131
Printf("at:\n");
132
StackDepotGet(entry.stack_id).Print();
133
}
134
}
135
136
{
137
Lock L(&TrackedLoadsMutex);
138
u64 TotalInvalidLoadTracking = 0;
139
u64 TotalUnknownLoadTracking = 0;
140
for (const auto &entry : TrackedLoads) {
141
TotalInvalidLoadTracking += entry.num_invalid;
142
TotalUnknownLoadTracking += entry.num_unknown;
143
Printf("invalid/unknown type for %llu/%llu loads at:\n",
144
entry.num_invalid, entry.num_unknown);
145
StackDepotGet(entry.stack_id).Print();
146
}
147
Printf(
148
"There were %llu/%llu floating-point loads where the shadow type was "
149
"invalid/unknown.\n",
150
TotalInvalidLoadTracking, TotalUnknownLoadTracking);
151
}
152
}
153
154
alignas(64) static char stats_placeholder[sizeof(Stats)];
155
Stats *__nsan::nsan_stats = nullptr;
156
157
void __nsan::InitializeStats() { nsan_stats = new (stats_placeholder) Stats(); }
158
159