1 //===-- stats.cc ----------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Sanitizer statistics gathering. Manages statistics for a process and is
10 // responsible for writing the report file.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_common/sanitizer_common.h"
15 #include "sanitizer_common/sanitizer_file.h"
16 #include "sanitizer_common/sanitizer_internal_defs.h"
18 #include "sanitizer_common/sanitizer_posix.h"
20 #include "sanitizer_common/sanitizer_symbolizer.h"
21 #include "stats/stats.h"
26 using namespace __sanitizer;
30 InternalMmapVectorNoCtor<StatModule **> modules;
31 StaticSpinMutex modules_mutex;
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);
40 WriteToFile(fd, chars, sizeof(uptr));
43 void OpenStatsFile(const char *path_env) {
44 InternalMmapVector<char> path(kMaxPathLength);
45 SubstituteForFlagValue(path_env, path.data(), kMaxPathLength);
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(),
54 char sizeof_uptr = sizeof(uptr);
55 WriteToFile(stats_fd, &sizeof_uptr, 1);
58 void WriteModuleReport(StatModule **smodp) {
60 const char *path_env = GetEnv("SANITIZER_STATS_PATH");
61 if (!path_env || stats_fd == kInvalidFd)
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];
74 WriteLE(stats_fd, s->addr - mod->base_address());
75 WriteLE(stats_fd, s->data);
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;
93 SANITIZER_INTERFACE_ATTRIBUTE
94 void __sanitizer_stats_unregister(unsigned index) {
95 SpinMutexLock l(&modules_mutex);
96 WriteModuleReport(modules[index]);
102 void WriteFullReport() {
103 SpinMutexLock l(&modules_mutex);
104 for (StatModule **mod : modules) {
107 WriteModuleReport(mod);
109 if (stats_fd != 0 && stats_fd != kInvalidFd) {
111 stats_fd = kInvalidFd;
116 void USR2Handler(int sig) {
121 struct WriteReportOnExitOrSignal {
122 WriteReportOnExitOrSignal() {
124 struct sigaction sigact;
125 internal_memset(&sigact, 0, sizeof(sigact));
126 sigact.sa_handler = USR2Handler;
127 internal_sigaction(SIGUSR2, &sigact, nullptr);
131 ~WriteReportOnExitOrSignal() {