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 16 #ifndef SANITIZER_LIBIGNORE_H 17 #define SANITIZER_LIBIGNORE_H 18 19 #include "sanitizer_internal_defs.h" 20 #include "sanitizer_common.h" 21 #include "sanitizer_atomic.h" 22 #include "sanitizer_mutex.h" 23 24 namespace __sanitizer { 25 26 class LibIgnore { 27 public: 28 explicit LibIgnore(LinkerInitialized); 29 30 // Must be called during initialization. 31 void AddIgnoredLibrary(const char *name_templ); 32 void IgnoreNoninstrumentedModules(bool enable) { 33 track_instrumented_libs_ = enable; 34 } 35 36 // Must be called after a new dynamic library is loaded. 37 void OnLibraryLoaded(const char *name); 38 39 // Must be called after a dynamic library is unloaded. 40 void OnLibraryUnloaded(); 41 42 // Checks whether the provided PC belongs to one of the ignored libraries or 43 // the PC should be ignored because it belongs to an non-instrumented module 44 // (when ignore_noninstrumented_modules=1). Also returns true via 45 // "pc_in_ignored_lib" if the PC is in an ignored library, false otherwise. 46 bool IsIgnored(uptr pc, bool *pc_in_ignored_lib) const; 47 48 // Checks whether the provided PC belongs to an instrumented module. 49 bool IsPcInstrumented(uptr pc) const; 50 51 private: 52 static const uptr kMaxIgnoredRanges = 128; 53 static const uptr kMaxInstrumentedRanges = 1024; 54 static const uptr kMaxLibs = 1024; 55 static const uptr kInvalidCodeRangeId = -1; 56 57 struct Lib { 58 char *templ; 59 char *name; 60 char *real_name; // target of symlink 61 uptr range_id; 62 bool loaded() const { return range_id != kInvalidCodeRangeId; }; 63 }; 64 65 struct LibCodeRange { 66 bool IsInRange(uptr pc) const { 67 return (pc >= begin && pc < atomic_load(&end, memory_order_acquire)); 68 } 69 70 void OnLoad(uptr b, uptr e) { 71 begin = b; 72 atomic_store(&end, e, memory_order_release); 73 } 74 75 void OnUnload() { atomic_store(&end, 0, memory_order_release); } 76 77 private: 78 uptr begin; 79 // A value of 0 means the associated module was unloaded. 80 atomic_uintptr_t end; 81 }; 82 83 // Hot part: 84 atomic_uintptr_t ignored_ranges_count_; 85 LibCodeRange ignored_code_ranges_[kMaxIgnoredRanges]; 86 87 atomic_uintptr_t instrumented_ranges_count_; 88 LibCodeRange instrumented_code_ranges_[kMaxInstrumentedRanges]; 89 90 // Cold part: 91 Mutex mutex_; 92 uptr count_; 93 Lib libs_[kMaxLibs]; 94 bool track_instrumented_libs_; 95 96 // Disallow copying of LibIgnore objects. 97 LibIgnore(const LibIgnore&); // not implemented 98 void operator = (const LibIgnore&); // not implemented 99 }; 100 101 inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const { 102 const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire); 103 for (uptr i = 0; i < n; i++) { 104 if (ignored_code_ranges_[i].IsInRange(pc)) { 105 *pc_in_ignored_lib = true; 106 return true; 107 } 108 } 109 *pc_in_ignored_lib = false; 110 if (track_instrumented_libs_ && !IsPcInstrumented(pc)) 111 return true; 112 return false; 113 } 114 115 inline bool LibIgnore::IsPcInstrumented(uptr pc) const { 116 const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire); 117 for (uptr i = 0; i < n; i++) { 118 if (instrumented_code_ranges_[i].IsInRange(pc)) 119 return true; 120 } 121 return false; 122 } 123 124 } // namespace __sanitizer 125 126 #endif // SANITIZER_LIBIGNORE_H 127