127 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// LibIgnore allows to ignore all interceptors called from a particular set10// of dynamic libraries. LibIgnore can be initialized with several templates11// 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_H17#define SANITIZER_LIBIGNORE_H18 19#include "sanitizer_internal_defs.h"20#include "sanitizer_common.h"21#include "sanitizer_atomic.h"22#include "sanitizer_mutex.h"23 24namespace __sanitizer {25 26class 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 or43 // the PC should be ignored because it belongs to an non-instrumented module44 // (when ignore_noninstrumented_modules=1). Also returns true via45 // "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 symlink61 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 implemented98 void operator = (const LibIgnore&); // not implemented99};100 101inline 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 115inline 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 __sanitizer125 126#endif // SANITIZER_LIBIGNORE_H127