sanitizer_libignore.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //===-- sanitizer_libignore.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. #include "sanitizer_platform.h"
  9. #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \
  10. SANITIZER_NETBSD
  11. #include "sanitizer_libignore.h"
  12. #include "sanitizer_flags.h"
  13. #include "sanitizer_posix.h"
  14. #include "sanitizer_procmaps.h"
  15. namespace __sanitizer {
  16. LibIgnore::LibIgnore(LinkerInitialized) {
  17. }
  18. void LibIgnore::AddIgnoredLibrary(const char *name_templ) {
  19. Lock lock(&mutex_);
  20. if (count_ >= kMaxLibs) {
  21. Report("%s: too many ignored libraries (max: %zu)\n", SanitizerToolName,
  22. kMaxLibs);
  23. Die();
  24. }
  25. Lib *lib = &libs_[count_++];
  26. lib->templ = internal_strdup(name_templ);
  27. lib->name = nullptr;
  28. lib->real_name = nullptr;
  29. lib->loaded = false;
  30. }
  31. void LibIgnore::OnLibraryLoaded(const char *name) {
  32. Lock lock(&mutex_);
  33. // Try to match suppressions with symlink target.
  34. InternalMmapVector<char> buf(kMaxPathLength);
  35. if (name && internal_readlink(name, buf.data(), buf.size() - 1) > 0 &&
  36. buf[0]) {
  37. for (uptr i = 0; i < count_; i++) {
  38. Lib *lib = &libs_[i];
  39. if (!lib->loaded && (!lib->real_name) &&
  40. TemplateMatch(lib->templ, name))
  41. lib->real_name = internal_strdup(buf.data());
  42. }
  43. }
  44. // Scan suppressions list and find newly loaded and unloaded libraries.
  45. ListOfModules modules;
  46. modules.init();
  47. for (uptr i = 0; i < count_; i++) {
  48. Lib *lib = &libs_[i];
  49. bool loaded = false;
  50. for (const auto &mod : modules) {
  51. for (const auto &range : mod.ranges()) {
  52. if (!range.executable)
  53. continue;
  54. if (!TemplateMatch(lib->templ, mod.full_name()) &&
  55. !(lib->real_name &&
  56. internal_strcmp(lib->real_name, mod.full_name()) == 0))
  57. continue;
  58. if (loaded) {
  59. Report("%s: called_from_lib suppression '%s' is matched against"
  60. " 2 libraries: '%s' and '%s'\n",
  61. SanitizerToolName, lib->templ, lib->name, mod.full_name());
  62. Die();
  63. }
  64. loaded = true;
  65. if (lib->loaded)
  66. continue;
  67. VReport(1,
  68. "Matched called_from_lib suppression '%s' against library"
  69. " '%s'\n",
  70. lib->templ, mod.full_name());
  71. lib->loaded = true;
  72. lib->name = internal_strdup(mod.full_name());
  73. const uptr idx =
  74. atomic_load(&ignored_ranges_count_, memory_order_relaxed);
  75. CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_));
  76. ignored_code_ranges_[idx].begin = range.beg;
  77. ignored_code_ranges_[idx].end = range.end;
  78. atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release);
  79. break;
  80. }
  81. }
  82. if (lib->loaded && !loaded) {
  83. Report("%s: library '%s' that was matched against called_from_lib"
  84. " suppression '%s' is unloaded\n",
  85. SanitizerToolName, lib->name, lib->templ);
  86. Die();
  87. }
  88. }
  89. // Track instrumented ranges.
  90. if (track_instrumented_libs_) {
  91. for (const auto &mod : modules) {
  92. if (!mod.instrumented())
  93. continue;
  94. for (const auto &range : mod.ranges()) {
  95. if (!range.executable)
  96. continue;
  97. if (IsPcInstrumented(range.beg) && IsPcInstrumented(range.end - 1))
  98. continue;
  99. VReport(1, "Adding instrumented range 0x%zx-0x%zx from library '%s'\n",
  100. range.beg, range.end, mod.full_name());
  101. const uptr idx =
  102. atomic_load(&instrumented_ranges_count_, memory_order_relaxed);
  103. CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_));
  104. instrumented_code_ranges_[idx].begin = range.beg;
  105. instrumented_code_ranges_[idx].end = range.end;
  106. atomic_store(&instrumented_ranges_count_, idx + 1,
  107. memory_order_release);
  108. }
  109. }
  110. }
  111. }
  112. void LibIgnore::OnLibraryUnloaded() {
  113. OnLibraryLoaded(nullptr);
  114. }
  115. } // namespace __sanitizer
  116. #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE ||
  117. // SANITIZER_NETBSD