stats_client.cpp 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. //===-- stats_client.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 module (executable
  10. // or DSO) and registers statistics with the process.
  11. //
  12. // This is linked into each individual modle and cannot directly use functions
  13. // declared in sanitizer_common.
  14. //
  15. //===----------------------------------------------------------------------===//
  16. #ifdef _WIN32
  17. #define WIN32_LEAN_AND_MEAN
  18. #include <windows.h>
  19. #else
  20. #include <dlfcn.h>
  21. #endif
  22. #include <stdint.h>
  23. #include <stdio.h>
  24. #include "sanitizer_common/sanitizer_internal_defs.h"
  25. #include "stats/stats.h"
  26. using namespace __sanitizer;
  27. namespace {
  28. void *LookupSymbolFromMain(const char *name) {
  29. #ifdef _WIN32
  30. return reinterpret_cast<void *>(GetProcAddress(GetModuleHandle(0), name));
  31. #else
  32. return dlsym(RTLD_DEFAULT, name);
  33. #endif
  34. }
  35. StatModule *list;
  36. struct RegisterSanStats {
  37. unsigned module_id;
  38. RegisterSanStats() {
  39. typedef unsigned (*reg_func_t)(StatModule **);
  40. reg_func_t reg_func = reinterpret_cast<reg_func_t>(
  41. LookupSymbolFromMain("__sanitizer_stats_register"));
  42. if (reg_func)
  43. module_id = reg_func(&list);
  44. }
  45. ~RegisterSanStats() {
  46. typedef void (*unreg_func_t)(unsigned);
  47. unreg_func_t unreg_func = reinterpret_cast<unreg_func_t>(
  48. LookupSymbolFromMain("__sanitizer_stats_unregister"));
  49. if (unreg_func)
  50. unreg_func(module_id);
  51. }
  52. } reg;
  53. }
  54. extern "C" void __sanitizer_stat_init(StatModule *mod) {
  55. mod->next = list;
  56. list = mod;
  57. }
  58. extern "C" void __sanitizer_stat_report(StatInfo *s) {
  59. s->addr = GET_CALLER_PC();
  60. #if defined(_WIN64) && !defined(__clang__)
  61. uptr old_data = InterlockedIncrement64(reinterpret_cast<LONG64 *>(&s->data));
  62. #elif defined(_WIN32) && !defined(__clang__)
  63. uptr old_data = InterlockedIncrement(&s->data);
  64. #else
  65. uptr old_data = __sync_fetch_and_add(&s->data, 1);
  66. #endif
  67. // Overflow check.
  68. if (CountFromData(old_data + 1) == 0)
  69. Trap();
  70. }