brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.5 KiB · da254fd Raw
137 lines · cpp
1//===-- stats.cpp ---------------------------------------------------------===//2//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-exception6//7//===----------------------------------------------------------------------===//8//9// Sanitizer statistics gathering. Manages statistics for a process and is10// responsible for writing the report file.11//12//===----------------------------------------------------------------------===//13 14#include "sanitizer_common/sanitizer_common.h"15#include "sanitizer_common/sanitizer_file.h"16#include "sanitizer_common/sanitizer_internal_defs.h"17#if SANITIZER_POSIX18#include "sanitizer_common/sanitizer_posix.h"19#endif20#include "sanitizer_common/sanitizer_symbolizer.h"21#include "stats/stats.h"22#if SANITIZER_POSIX23#include <signal.h>24#endif25 26using namespace __sanitizer;27 28namespace {29 30InternalMmapVectorNoCtor<StatModule **> modules;31StaticSpinMutex modules_mutex;32 33fd_t stats_fd;34 35void 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);39  }40  WriteToFile(fd, chars, sizeof(uptr));41}42 43void OpenStatsFile(const char *path_env) {44  InternalMmapVector<char> path(kMaxPathLength);45  SubstituteForFlagValue(path_env, path.data(), kMaxPathLength);46 47  error_t err;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(),51           err);52    return;53  }54  char sizeof_uptr = sizeof(uptr);55  WriteToFile(stats_fd, &sizeof_uptr, 1);56}57 58void WriteModuleReport(StatModule **smodp) {59  CHECK(smodp);60  const char *path_env = GetEnv("SANITIZER_STATS_PATH");61  if (!path_env || stats_fd == kInvalidFd)62    return;63  if (!stats_fd)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];72      if (!s->addr)73        continue;74      WriteLE(stats_fd, s->addr - mod->base_address());75      WriteLE(stats_fd, s->data);76    }77  }78  WriteLE(stats_fd, 0);79  WriteLE(stats_fd, 0);80}81 82} // namespace83 84extern "C"85SANITIZER_INTERFACE_ATTRIBUTE86unsigned __sanitizer_stats_register(StatModule **mod) {87  SpinMutexLock l(&modules_mutex);88  modules.push_back(mod);89  return modules.size() - 1;90}91 92extern "C"93SANITIZER_INTERFACE_ATTRIBUTE94void __sanitizer_stats_unregister(unsigned index) {95  SpinMutexLock l(&modules_mutex);96  WriteModuleReport(modules[index]);97  modules[index] = 0;98}99 100namespace {101 102void WriteFullReport() {103  SpinMutexLock l(&modules_mutex);104  for (StatModule **mod : modules) {105    if (!mod)106      continue;107    WriteModuleReport(mod);108  }109  if (stats_fd != 0 && stats_fd != kInvalidFd) {110    CloseFile(stats_fd);111    stats_fd = kInvalidFd;112  }113}114 115#if SANITIZER_POSIX116void USR2Handler(int sig) {117  WriteFullReport();118}119#endif120 121struct WriteReportOnExitOrSignal {122  WriteReportOnExitOrSignal() {123#if SANITIZER_POSIX124    struct sigaction sigact;125    internal_memset(&sigact, 0, sizeof(sigact));126    sigact.sa_handler = USR2Handler;127    internal_sigaction(SIGUSR2, &sigact, nullptr);128#endif129  }130 131  ~WriteReportOnExitOrSignal() {132    WriteFullReport();133  }134} wr;135 136} // namespace137