1 //===-- stats.cpp ---------------------------------------------------------===//
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() {