sanitizer_libignore.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. //===-- sanitizer_libignore.h -----------------------------------*- C++ -*-===//
  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. // LibIgnore allows to ignore all interceptors called from a particular set
  10. // of dynamic libraries. LibIgnore can be initialized with several templates
  11. // of names of libraries to be ignored. It finds code ranges for the libraries;
  12. // and checks whether the provided PC value belongs to the code ranges.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #ifndef SANITIZER_LIBIGNORE_H
  16. #define SANITIZER_LIBIGNORE_H
  17. #include "sanitizer_internal_defs.h"
  18. #include "sanitizer_common.h"
  19. #include "sanitizer_atomic.h"
  20. #include "sanitizer_mutex.h"
  21. namespace __sanitizer {
  22. class LibIgnore {
  23. public:
  24. explicit LibIgnore(LinkerInitialized);
  25. // Must be called during initialization.
  26. void AddIgnoredLibrary(const char *name_templ);
  27. void IgnoreNoninstrumentedModules(bool enable) {
  28. track_instrumented_libs_ = enable;
  29. }
  30. // Must be called after a new dynamic library is loaded.
  31. void OnLibraryLoaded(const char *name);
  32. // Must be called after a dynamic library is unloaded.
  33. void OnLibraryUnloaded();
  34. // Checks whether the provided PC belongs to one of the ignored libraries or
  35. // the PC should be ignored because it belongs to an non-instrumented module
  36. // (when ignore_noninstrumented_modules=1). Also returns true via
  37. // "pc_in_ignored_lib" if the PC is in an ignored library, false otherwise.
  38. bool IsIgnored(uptr pc, bool *pc_in_ignored_lib) const;
  39. // Checks whether the provided PC belongs to an instrumented module.
  40. bool IsPcInstrumented(uptr pc) const;
  41. private:
  42. struct Lib {
  43. char *templ;
  44. char *name;
  45. char *real_name; // target of symlink
  46. bool loaded;
  47. };
  48. struct LibCodeRange {
  49. uptr begin;
  50. uptr end;
  51. };
  52. inline bool IsInRange(uptr pc, const LibCodeRange &range) const {
  53. return (pc >= range.begin && pc < range.end);
  54. }
  55. static const uptr kMaxIgnoredRanges = 128;
  56. static const uptr kMaxInstrumentedRanges = 1024;
  57. static const uptr kMaxLibs = 1024;
  58. // Hot part:
  59. atomic_uintptr_t ignored_ranges_count_;
  60. LibCodeRange ignored_code_ranges_[kMaxIgnoredRanges];
  61. atomic_uintptr_t instrumented_ranges_count_;
  62. LibCodeRange instrumented_code_ranges_[kMaxInstrumentedRanges];
  63. // Cold part:
  64. Mutex mutex_;
  65. uptr count_;
  66. Lib libs_[kMaxLibs];
  67. bool track_instrumented_libs_;
  68. // Disallow copying of LibIgnore objects.
  69. LibIgnore(const LibIgnore&); // not implemented
  70. void operator = (const LibIgnore&); // not implemented
  71. };
  72. inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
  73. const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire);
  74. for (uptr i = 0; i < n; i++) {
  75. if (IsInRange(pc, ignored_code_ranges_[i])) {
  76. *pc_in_ignored_lib = true;
  77. return true;
  78. }
  79. }
  80. *pc_in_ignored_lib = false;
  81. if (track_instrumented_libs_ && !IsPcInstrumented(pc))
  82. return true;
  83. return false;
  84. }
  85. inline bool LibIgnore::IsPcInstrumented(uptr pc) const {
  86. const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire);
  87. for (uptr i = 0; i < n; i++) {
  88. if (IsInRange(pc, instrumented_code_ranges_[i]))
  89. return true;
  90. }
  91. return false;
  92. }
  93. } // namespace __sanitizer
  94. #endif // SANITIZER_LIBIGNORE_H