1 //===-- stats.cc ----------------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Sanitizer statistics gathering. Manages statistics for a process and is
11 // responsible for writing the report file.
13 //===----------------------------------------------------------------------===//
15 #include "sanitizer_common/sanitizer_common.h"
16 #include "sanitizer_common/sanitizer_file.h"
17 #include "sanitizer_common/sanitizer_internal_defs.h"
19 #include "sanitizer_common/sanitizer_posix.h"
21 #include "sanitizer_common/sanitizer_symbolizer.h"
22 #include "stats/stats.h"
27 using namespace __sanitizer;
31 InternalMmapVectorNoCtor<StatModule **> modules;
32 StaticSpinMutex modules_mutex;
36 void WriteLE(fd_t fd, uptr val) {
37 char chars[sizeof(uptr)];
38 for (unsigned i = 0; i != sizeof(uptr); ++i) {
39 chars[i] = val >> (i * 8);
41 WriteToFile(fd, chars, sizeof(uptr));
44 void OpenStatsFile(const char *path_env) {
45 InternalMmapVector<char> path(kMaxPathLength);
46 SubstituteForFlagValue(path_env, path.data(), kMaxPathLength);
49 stats_fd = OpenFile(path.data(), WrOnly, &err);
50 if (stats_fd == kInvalidFd) {
51 Report("stats: failed to open %s for writing (reason: %d)\n", path.data(),
55 char sizeof_uptr = sizeof(uptr);
56 WriteToFile(stats_fd, &sizeof_uptr, 1);
59 void WriteModuleReport(StatModule **smodp) {
61 const char *path_env = GetEnv("SANITIZER_STATS_PATH");
62 if (!path_env || stats_fd == kInvalidFd)
65 OpenStatsFile(path_env);
66 const LoadedModule *mod = Symbolizer::GetOrInit()->FindModuleForAddress(
67 reinterpret_cast<uptr>(smodp));
68 WriteToFile(stats_fd, mod->full_name(),
69 internal_strlen(mod->full_name()) + 1);
70 for (StatModule *smod = *smodp; smod; smod = smod->next) {
71 for (u32 i = 0; i != smod->size; ++i) {
72 StatInfo *s = &smod->infos[i];
75 WriteLE(stats_fd, s->addr - mod->base_address());
76 WriteLE(stats_fd, s->data);
86 SANITIZER_INTERFACE_ATTRIBUTE
87 unsigned __sanitizer_stats_register(StatModule **mod) {
88 SpinMutexLock l(&modules_mutex);
89 modules.push_back(mod);
90 return modules.size() - 1;
94 SANITIZER_INTERFACE_ATTRIBUTE
95 void __sanitizer_stats_unregister(unsigned index) {
96 SpinMutexLock l(&modules_mutex);
97 WriteModuleReport(modules[index]);
103 void WriteFullReport() {
104 SpinMutexLock l(&modules_mutex);
105 for (StatModule **mod : modules) {
108 WriteModuleReport(mod);
110 if (stats_fd != 0 && stats_fd != kInvalidFd) {
112 stats_fd = kInvalidFd;
117 void USR2Handler(int sig) {
122 struct WriteReportOnExitOrSignal {
123 WriteReportOnExitOrSignal() {
125 struct sigaction sigact;
126 internal_memset(&sigact, 0, sizeof(sigact));
127 sigact.sa_handler = USR2Handler;
128 internal_sigaction(SIGUSR2, &sigact, nullptr);
132 ~WriteReportOnExitOrSignal() {