lsan_common_linux.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. //=-- lsan_common_linux.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. // This file is a part of LeakSanitizer.
  10. // Implementation of common leak checking functionality. Linux/NetBSD-specific
  11. // code.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "sanitizer_common/sanitizer_platform.h"
  15. #include "lsan_common.h"
  16. #if CAN_SANITIZE_LEAKS && (SANITIZER_LINUX || SANITIZER_NETBSD)
  17. #include <link.h>
  18. #include "sanitizer_common/sanitizer_common.h"
  19. #include "sanitizer_common/sanitizer_flags.h"
  20. #include "sanitizer_common/sanitizer_getauxval.h"
  21. #include "sanitizer_common/sanitizer_linux.h"
  22. #include "sanitizer_common/sanitizer_stackdepot.h"
  23. namespace __lsan {
  24. static const char kLinkerName[] = "ld";
  25. static char linker_placeholder[sizeof(LoadedModule)] ALIGNED(64);
  26. static LoadedModule *linker = nullptr;
  27. static bool IsLinker(const LoadedModule& module) {
  28. #if SANITIZER_USE_GETAUXVAL
  29. return module.base_address() == getauxval(AT_BASE);
  30. #else
  31. return LibraryNameIs(module.full_name(), kLinkerName);
  32. #endif // SANITIZER_USE_GETAUXVAL
  33. }
  34. __attribute__((tls_model("initial-exec")))
  35. THREADLOCAL int disable_counter;
  36. bool DisabledInThisThread() { return disable_counter > 0; }
  37. void DisableInThisThread() { disable_counter++; }
  38. void EnableInThisThread() {
  39. if (disable_counter == 0) {
  40. DisableCounterUnderflow();
  41. }
  42. disable_counter--;
  43. }
  44. void InitializePlatformSpecificModules() {
  45. ListOfModules modules;
  46. modules.init();
  47. for (LoadedModule &module : modules) {
  48. if (!IsLinker(module))
  49. continue;
  50. if (linker == nullptr) {
  51. linker = reinterpret_cast<LoadedModule *>(linker_placeholder);
  52. *linker = module;
  53. module = LoadedModule();
  54. } else {
  55. VReport(1, "LeakSanitizer: Multiple modules match \"%s\". "
  56. "TLS and other allocations originating from linker might be "
  57. "falsely reported as leaks.\n", kLinkerName);
  58. linker->clear();
  59. linker = nullptr;
  60. return;
  61. }
  62. }
  63. if (linker == nullptr) {
  64. VReport(1, "LeakSanitizer: Dynamic linker not found. TLS and other "
  65. "allocations originating from linker might be falsely reported "
  66. "as leaks.\n");
  67. }
  68. }
  69. static int ProcessGlobalRegionsCallback(struct dl_phdr_info *info, size_t size,
  70. void *data) {
  71. Frontier *frontier = reinterpret_cast<Frontier *>(data);
  72. for (uptr j = 0; j < info->dlpi_phnum; j++) {
  73. const ElfW(Phdr) *phdr = &(info->dlpi_phdr[j]);
  74. // We're looking for .data and .bss sections, which reside in writeable,
  75. // loadable segments.
  76. if (!(phdr->p_flags & PF_W) || (phdr->p_type != PT_LOAD) ||
  77. (phdr->p_memsz == 0))
  78. continue;
  79. uptr begin = info->dlpi_addr + phdr->p_vaddr;
  80. uptr end = begin + phdr->p_memsz;
  81. ScanGlobalRange(begin, end, frontier);
  82. }
  83. return 0;
  84. }
  85. #if SANITIZER_ANDROID && __ANDROID_API__ < 21
  86. extern "C" __attribute__((weak)) int dl_iterate_phdr(
  87. int (*)(struct dl_phdr_info *, size_t, void *), void *);
  88. #endif
  89. // Scans global variables for heap pointers.
  90. void ProcessGlobalRegions(Frontier *frontier) {
  91. if (!flags()->use_globals) return;
  92. dl_iterate_phdr(ProcessGlobalRegionsCallback, frontier);
  93. }
  94. LoadedModule *GetLinker() { return linker; }
  95. void ProcessPlatformSpecificAllocations(Frontier *frontier) {}
  96. struct DoStopTheWorldParam {
  97. StopTheWorldCallback callback;
  98. void *argument;
  99. };
  100. // While calling Die() here is undefined behavior and can potentially
  101. // cause race conditions, it isn't possible to intercept exit on linux,
  102. // so we have no choice but to call Die() from the atexit handler.
  103. void HandleLeaks() {
  104. if (common_flags()->exitcode) Die();
  105. }
  106. static int LockStuffAndStopTheWorldCallback(struct dl_phdr_info *info,
  107. size_t size, void *data) {
  108. ScopedStopTheWorldLock lock;
  109. DoStopTheWorldParam *param = reinterpret_cast<DoStopTheWorldParam *>(data);
  110. StopTheWorld(param->callback, param->argument);
  111. return 1;
  112. }
  113. // LSan calls dl_iterate_phdr() from the tracer task. This may deadlock: if one
  114. // of the threads is frozen while holding the libdl lock, the tracer will hang
  115. // in dl_iterate_phdr() forever.
  116. // Luckily, (a) the lock is reentrant and (b) libc can't distinguish between the
  117. // tracer task and the thread that spawned it. Thus, if we run the tracer task
  118. // while holding the libdl lock in the parent thread, we can safely reenter it
  119. // in the tracer. The solution is to run stoptheworld from a dl_iterate_phdr()
  120. // callback in the parent thread.
  121. void LockStuffAndStopTheWorld(StopTheWorldCallback callback,
  122. CheckForLeaksParam *argument) {
  123. DoStopTheWorldParam param = {callback, argument};
  124. dl_iterate_phdr(LockStuffAndStopTheWorldCallback, &param);
  125. }
  126. } // namespace __lsan
  127. #endif