Path: blob/main/contrib/llvm-project/compiler-rt/lib/stats/stats.cpp
35262 views
//===-- stats.cpp ---------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Sanitizer statistics gathering. Manages statistics for a process and is9// responsible for writing the report file.10//11//===----------------------------------------------------------------------===//1213#include "sanitizer_common/sanitizer_common.h"14#include "sanitizer_common/sanitizer_file.h"15#include "sanitizer_common/sanitizer_internal_defs.h"16#if SANITIZER_POSIX17#include "sanitizer_common/sanitizer_posix.h"18#endif19#include "sanitizer_common/sanitizer_symbolizer.h"20#include "stats/stats.h"21#if SANITIZER_POSIX22#include <signal.h>23#endif2425using namespace __sanitizer;2627namespace {2829InternalMmapVectorNoCtor<StatModule **> modules;30StaticSpinMutex modules_mutex;3132fd_t stats_fd;3334void WriteLE(fd_t fd, uptr val) {35char chars[sizeof(uptr)];36for (unsigned i = 0; i != sizeof(uptr); ++i) {37chars[i] = val >> (i * 8);38}39WriteToFile(fd, chars, sizeof(uptr));40}4142void OpenStatsFile(const char *path_env) {43InternalMmapVector<char> path(kMaxPathLength);44SubstituteForFlagValue(path_env, path.data(), kMaxPathLength);4546error_t err;47stats_fd = OpenFile(path.data(), WrOnly, &err);48if (stats_fd == kInvalidFd) {49Report("stats: failed to open %s for writing (reason: %d)\n", path.data(),50err);51return;52}53char sizeof_uptr = sizeof(uptr);54WriteToFile(stats_fd, &sizeof_uptr, 1);55}5657void WriteModuleReport(StatModule **smodp) {58CHECK(smodp);59const char *path_env = GetEnv("SANITIZER_STATS_PATH");60if (!path_env || stats_fd == kInvalidFd)61return;62if (!stats_fd)63OpenStatsFile(path_env);64const LoadedModule *mod = Symbolizer::GetOrInit()->FindModuleForAddress(65reinterpret_cast<uptr>(smodp));66WriteToFile(stats_fd, mod->full_name(),67internal_strlen(mod->full_name()) + 1);68for (StatModule *smod = *smodp; smod; smod = smod->next) {69for (u32 i = 0; i != smod->size; ++i) {70StatInfo *s = &smod->infos[i];71if (!s->addr)72continue;73WriteLE(stats_fd, s->addr - mod->base_address());74WriteLE(stats_fd, s->data);75}76}77WriteLE(stats_fd, 0);78WriteLE(stats_fd, 0);79}8081} // namespace8283extern "C"84SANITIZER_INTERFACE_ATTRIBUTE85unsigned __sanitizer_stats_register(StatModule **mod) {86SpinMutexLock l(&modules_mutex);87modules.push_back(mod);88return modules.size() - 1;89}9091extern "C"92SANITIZER_INTERFACE_ATTRIBUTE93void __sanitizer_stats_unregister(unsigned index) {94SpinMutexLock l(&modules_mutex);95WriteModuleReport(modules[index]);96modules[index] = 0;97}9899namespace {100101void WriteFullReport() {102SpinMutexLock l(&modules_mutex);103for (StatModule **mod : modules) {104if (!mod)105continue;106WriteModuleReport(mod);107}108if (stats_fd != 0 && stats_fd != kInvalidFd) {109CloseFile(stats_fd);110stats_fd = kInvalidFd;111}112}113114#if SANITIZER_POSIX115void USR2Handler(int sig) {116WriteFullReport();117}118#endif119120struct WriteReportOnExitOrSignal {121WriteReportOnExitOrSignal() {122#if SANITIZER_POSIX123struct sigaction sigact;124internal_memset(&sigact, 0, sizeof(sigact));125sigact.sa_handler = USR2Handler;126internal_sigaction(SIGUSR2, &sigact, nullptr);127#endif128}129130~WriteReportOnExitOrSignal() {131WriteFullReport();132}133} wr;134135} // namespace136137138