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