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