(root)/
gcc-13.2.0/
libsanitizer/
sanitizer_common/
sanitizer_libignore.h
       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    struct Lib {
      53      char *templ;
      54      char *name;
      55      char *real_name;  // target of symlink
      56      bool loaded;
      57    };
      58  
      59    struct LibCodeRange {
      60      uptr begin;
      61      uptr end;
      62    };
      63  
      64    inline bool IsInRange(uptr pc, const LibCodeRange &range) const {
      65      return (pc >= range.begin && pc < range.end);
      66    }
      67  
      68    static const uptr kMaxIgnoredRanges = 128;
      69    static const uptr kMaxInstrumentedRanges = 1024;
      70    static const uptr kMaxLibs = 1024;
      71  
      72    // Hot part:
      73    atomic_uintptr_t ignored_ranges_count_;
      74    LibCodeRange ignored_code_ranges_[kMaxIgnoredRanges];
      75  
      76    atomic_uintptr_t instrumented_ranges_count_;
      77    LibCodeRange instrumented_code_ranges_[kMaxInstrumentedRanges];
      78  
      79    // Cold part:
      80    Mutex mutex_;
      81    uptr count_;
      82    Lib libs_[kMaxLibs];
      83    bool track_instrumented_libs_;
      84  
      85    // Disallow copying of LibIgnore objects.
      86    LibIgnore(const LibIgnore&);  // not implemented
      87    void operator = (const LibIgnore&);  // not implemented
      88  };
      89  
      90  inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
      91    const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire);
      92    for (uptr i = 0; i < n; i++) {
      93      if (IsInRange(pc, ignored_code_ranges_[i])) {
      94        *pc_in_ignored_lib = true;
      95        return true;
      96      }
      97    }
      98    *pc_in_ignored_lib = false;
      99    if (track_instrumented_libs_ && !IsPcInstrumented(pc))
     100      return true;
     101    return false;
     102  }
     103  
     104  inline bool LibIgnore::IsPcInstrumented(uptr pc) const {
     105    const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire);
     106    for (uptr i = 0; i < n; i++) {
     107      if (IsInRange(pc, instrumented_code_ranges_[i]))
     108        return true;
     109    }
     110    return false;
     111  }
     112  
     113  }  // namespace __sanitizer
     114  
     115  #endif  // SANITIZER_LIBIGNORE_H