123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- //===-- stats.cpp ---------------------------------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // Sanitizer statistics gathering. Manages statistics for a process and is
- // responsible for writing the report file.
- //
- //===----------------------------------------------------------------------===//
- #include "sanitizer_common/sanitizer_common.h"
- #include "sanitizer_common/sanitizer_file.h"
- #include "sanitizer_common/sanitizer_internal_defs.h"
- #if SANITIZER_POSIX
- #include "sanitizer_common/sanitizer_posix.h"
- #endif
- #include "sanitizer_common/sanitizer_symbolizer.h"
- #include "stats/stats.h"
- #if SANITIZER_POSIX
- #include <signal.h>
- #endif
- using namespace __sanitizer;
- namespace {
- InternalMmapVectorNoCtor<StatModule **> modules;
- StaticSpinMutex modules_mutex;
- fd_t stats_fd;
- void WriteLE(fd_t fd, uptr val) {
- char chars[sizeof(uptr)];
- for (unsigned i = 0; i != sizeof(uptr); ++i) {
- chars[i] = val >> (i * 8);
- }
- WriteToFile(fd, chars, sizeof(uptr));
- }
- void OpenStatsFile(const char *path_env) {
- InternalMmapVector<char> path(kMaxPathLength);
- SubstituteForFlagValue(path_env, path.data(), kMaxPathLength);
- error_t err;
- stats_fd = OpenFile(path.data(), WrOnly, &err);
- if (stats_fd == kInvalidFd) {
- Report("stats: failed to open %s for writing (reason: %d)\n", path.data(),
- err);
- return;
- }
- char sizeof_uptr = sizeof(uptr);
- WriteToFile(stats_fd, &sizeof_uptr, 1);
- }
- void WriteModuleReport(StatModule **smodp) {
- CHECK(smodp);
- const char *path_env = GetEnv("SANITIZER_STATS_PATH");
- if (!path_env || stats_fd == kInvalidFd)
- return;
- if (!stats_fd)
- OpenStatsFile(path_env);
- const LoadedModule *mod = Symbolizer::GetOrInit()->FindModuleForAddress(
- reinterpret_cast<uptr>(smodp));
- WriteToFile(stats_fd, mod->full_name(),
- internal_strlen(mod->full_name()) + 1);
- for (StatModule *smod = *smodp; smod; smod = smod->next) {
- for (u32 i = 0; i != smod->size; ++i) {
- StatInfo *s = &smod->infos[i];
- if (!s->addr)
- continue;
- WriteLE(stats_fd, s->addr - mod->base_address());
- WriteLE(stats_fd, s->data);
- }
- }
- WriteLE(stats_fd, 0);
- WriteLE(stats_fd, 0);
- }
- } // namespace
- extern "C"
- SANITIZER_INTERFACE_ATTRIBUTE
- unsigned __sanitizer_stats_register(StatModule **mod) {
- SpinMutexLock l(&modules_mutex);
- modules.push_back(mod);
- return modules.size() - 1;
- }
- extern "C"
- SANITIZER_INTERFACE_ATTRIBUTE
- void __sanitizer_stats_unregister(unsigned index) {
- SpinMutexLock l(&modules_mutex);
- WriteModuleReport(modules[index]);
- modules[index] = 0;
- }
- namespace {
- void WriteFullReport() {
- SpinMutexLock l(&modules_mutex);
- for (StatModule **mod : modules) {
- if (!mod)
- continue;
- WriteModuleReport(mod);
- }
- if (stats_fd != 0 && stats_fd != kInvalidFd) {
- CloseFile(stats_fd);
- stats_fd = kInvalidFd;
- }
- }
- #if SANITIZER_POSIX
- void USR2Handler(int sig) {
- WriteFullReport();
- }
- #endif
- struct WriteReportOnExitOrSignal {
- WriteReportOnExitOrSignal() {
- #if SANITIZER_POSIX
- struct sigaction sigact;
- internal_memset(&sigact, 0, sizeof(sigact));
- sigact.sa_handler = USR2Handler;
- internal_sigaction(SIGUSR2, &sigact, nullptr);
- #endif
- }
- ~WriteReportOnExitOrSignal() {
- WriteFullReport();
- }
- } wr;
- } // namespace
|