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