Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/stats/stats.cpp
35262 views
1
//===-- stats.cpp ---------------------------------------------------------===//
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
// Sanitizer statistics gathering. Manages statistics for a process and is
10
// responsible for writing the report file.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "sanitizer_common/sanitizer_common.h"
15
#include "sanitizer_common/sanitizer_file.h"
16
#include "sanitizer_common/sanitizer_internal_defs.h"
17
#if SANITIZER_POSIX
18
#include "sanitizer_common/sanitizer_posix.h"
19
#endif
20
#include "sanitizer_common/sanitizer_symbolizer.h"
21
#include "stats/stats.h"
22
#if SANITIZER_POSIX
23
#include <signal.h>
24
#endif
25
26
using namespace __sanitizer;
27
28
namespace {
29
30
InternalMmapVectorNoCtor<StatModule **> modules;
31
StaticSpinMutex modules_mutex;
32
33
fd_t stats_fd;
34
35
void WriteLE(fd_t fd, uptr val) {
36
char chars[sizeof(uptr)];
37
for (unsigned i = 0; i != sizeof(uptr); ++i) {
38
chars[i] = val >> (i * 8);
39
}
40
WriteToFile(fd, chars, sizeof(uptr));
41
}
42
43
void OpenStatsFile(const char *path_env) {
44
InternalMmapVector<char> path(kMaxPathLength);
45
SubstituteForFlagValue(path_env, path.data(), kMaxPathLength);
46
47
error_t err;
48
stats_fd = OpenFile(path.data(), WrOnly, &err);
49
if (stats_fd == kInvalidFd) {
50
Report("stats: failed to open %s for writing (reason: %d)\n", path.data(),
51
err);
52
return;
53
}
54
char sizeof_uptr = sizeof(uptr);
55
WriteToFile(stats_fd, &sizeof_uptr, 1);
56
}
57
58
void WriteModuleReport(StatModule **smodp) {
59
CHECK(smodp);
60
const char *path_env = GetEnv("SANITIZER_STATS_PATH");
61
if (!path_env || stats_fd == kInvalidFd)
62
return;
63
if (!stats_fd)
64
OpenStatsFile(path_env);
65
const LoadedModule *mod = Symbolizer::GetOrInit()->FindModuleForAddress(
66
reinterpret_cast<uptr>(smodp));
67
WriteToFile(stats_fd, mod->full_name(),
68
internal_strlen(mod->full_name()) + 1);
69
for (StatModule *smod = *smodp; smod; smod = smod->next) {
70
for (u32 i = 0; i != smod->size; ++i) {
71
StatInfo *s = &smod->infos[i];
72
if (!s->addr)
73
continue;
74
WriteLE(stats_fd, s->addr - mod->base_address());
75
WriteLE(stats_fd, s->data);
76
}
77
}
78
WriteLE(stats_fd, 0);
79
WriteLE(stats_fd, 0);
80
}
81
82
} // namespace
83
84
extern "C"
85
SANITIZER_INTERFACE_ATTRIBUTE
86
unsigned __sanitizer_stats_register(StatModule **mod) {
87
SpinMutexLock l(&modules_mutex);
88
modules.push_back(mod);
89
return modules.size() - 1;
90
}
91
92
extern "C"
93
SANITIZER_INTERFACE_ATTRIBUTE
94
void __sanitizer_stats_unregister(unsigned index) {
95
SpinMutexLock l(&modules_mutex);
96
WriteModuleReport(modules[index]);
97
modules[index] = 0;
98
}
99
100
namespace {
101
102
void WriteFullReport() {
103
SpinMutexLock l(&modules_mutex);
104
for (StatModule **mod : modules) {
105
if (!mod)
106
continue;
107
WriteModuleReport(mod);
108
}
109
if (stats_fd != 0 && stats_fd != kInvalidFd) {
110
CloseFile(stats_fd);
111
stats_fd = kInvalidFd;
112
}
113
}
114
115
#if SANITIZER_POSIX
116
void USR2Handler(int sig) {
117
WriteFullReport();
118
}
119
#endif
120
121
struct WriteReportOnExitOrSignal {
122
WriteReportOnExitOrSignal() {
123
#if SANITIZER_POSIX
124
struct sigaction sigact;
125
internal_memset(&sigact, 0, sizeof(sigact));
126
sigact.sa_handler = USR2Handler;
127
internal_sigaction(SIGUSR2, &sigact, nullptr);
128
#endif
129
}
130
131
~WriteReportOnExitOrSignal() {
132
WriteFullReport();
133
}
134
} wr;
135
136
} // namespace
137
138