sanitizer_libignore.cc 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. //===-- sanitizer_libignore.cc --------------------------------------------===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. #include "sanitizer_platform.h"
  8. #if SANITIZER_FREEBSD || SANITIZER_LINUX
  9. #include "sanitizer_libignore.h"
  10. #include "sanitizer_flags.h"
  11. #include "sanitizer_procmaps.h"
  12. namespace __sanitizer {
  13. LibIgnore::LibIgnore(LinkerInitialized) {
  14. }
  15. void LibIgnore::Init(const SuppressionContext &supp) {
  16. BlockingMutexLock lock(&mutex_);
  17. CHECK_EQ(count_, 0);
  18. const uptr n = supp.SuppressionCount();
  19. for (uptr i = 0; i < n; i++) {
  20. const Suppression *s = supp.SuppressionAt(i);
  21. if (s->type != SuppressionLib)
  22. continue;
  23. if (count_ >= kMaxLibs) {
  24. Report("%s: too many called_from_lib suppressions (max: %d)\n",
  25. SanitizerToolName, kMaxLibs);
  26. Die();
  27. }
  28. Lib *lib = &libs_[count_++];
  29. lib->templ = internal_strdup(s->templ);
  30. lib->name = 0;
  31. lib->loaded = false;
  32. }
  33. }
  34. void LibIgnore::OnLibraryLoaded(const char *name) {
  35. BlockingMutexLock lock(&mutex_);
  36. // Try to match suppressions with symlink target.
  37. InternalScopedBuffer<char> buf(4096);
  38. if (name != 0 && internal_readlink(name, buf.data(), buf.size() - 1) > 0 &&
  39. buf.data()[0]) {
  40. for (uptr i = 0; i < count_; i++) {
  41. Lib *lib = &libs_[i];
  42. if (!lib->loaded && lib->real_name == 0 &&
  43. TemplateMatch(lib->templ, name))
  44. lib->real_name = internal_strdup(buf.data());
  45. }
  46. }
  47. // Scan suppressions list and find newly loaded and unloaded libraries.
  48. MemoryMappingLayout proc_maps(/*cache_enabled*/false);
  49. InternalScopedBuffer<char> module(4096);
  50. for (uptr i = 0; i < count_; i++) {
  51. Lib *lib = &libs_[i];
  52. bool loaded = false;
  53. proc_maps.Reset();
  54. uptr b, e, off, prot;
  55. while (proc_maps.Next(&b, &e, &off, module.data(), module.size(), &prot)) {
  56. if ((prot & MemoryMappingLayout::kProtectionExecute) == 0)
  57. continue;
  58. if (TemplateMatch(lib->templ, module.data()) ||
  59. (lib->real_name != 0 &&
  60. internal_strcmp(lib->real_name, module.data()) == 0)) {
  61. if (loaded) {
  62. Report("%s: called_from_lib suppression '%s' is matched against"
  63. " 2 libraries: '%s' and '%s'\n",
  64. SanitizerToolName, lib->templ, lib->name, module.data());
  65. Die();
  66. }
  67. loaded = true;
  68. if (lib->loaded)
  69. continue;
  70. VReport(1,
  71. "Matched called_from_lib suppression '%s' against library"
  72. " '%s'\n",
  73. lib->templ, module.data());
  74. lib->loaded = true;
  75. lib->name = internal_strdup(module.data());
  76. const uptr idx = atomic_load(&loaded_count_, memory_order_relaxed);
  77. code_ranges_[idx].begin = b;
  78. code_ranges_[idx].end = e;
  79. atomic_store(&loaded_count_, idx + 1, memory_order_release);
  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. }
  90. void LibIgnore::OnLibraryUnloaded() {
  91. OnLibraryLoaded(0);
  92. }
  93. } // namespace __sanitizer
  94. #endif // #if SANITIZER_FREEBSD || SANITIZER_LINUX