stats.cpp 3.5 KB

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