xref: /openbsd-src/gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===-- sanitizer_libignore.h -----------------------------------*- C++ -*-===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // LibIgnore allows to ignore all interceptors called from a particular set
103cab2bb3Spatrick // of dynamic libraries. LibIgnore can be initialized with several templates
113cab2bb3Spatrick // of names of libraries to be ignored. It finds code ranges for the libraries;
123cab2bb3Spatrick // and checks whether the provided PC value belongs to the code ranges.
133cab2bb3Spatrick //
143cab2bb3Spatrick //===----------------------------------------------------------------------===//
153cab2bb3Spatrick 
163cab2bb3Spatrick #ifndef SANITIZER_LIBIGNORE_H
173cab2bb3Spatrick #define SANITIZER_LIBIGNORE_H
183cab2bb3Spatrick 
193cab2bb3Spatrick #include "sanitizer_internal_defs.h"
203cab2bb3Spatrick #include "sanitizer_common.h"
213cab2bb3Spatrick #include "sanitizer_atomic.h"
223cab2bb3Spatrick #include "sanitizer_mutex.h"
233cab2bb3Spatrick 
243cab2bb3Spatrick namespace __sanitizer {
253cab2bb3Spatrick 
263cab2bb3Spatrick class LibIgnore {
273cab2bb3Spatrick  public:
283cab2bb3Spatrick   explicit LibIgnore(LinkerInitialized);
293cab2bb3Spatrick 
303cab2bb3Spatrick   // Must be called during initialization.
313cab2bb3Spatrick   void AddIgnoredLibrary(const char *name_templ);
IgnoreNoninstrumentedModules(bool enable)323cab2bb3Spatrick   void IgnoreNoninstrumentedModules(bool enable) {
333cab2bb3Spatrick     track_instrumented_libs_ = enable;
343cab2bb3Spatrick   }
353cab2bb3Spatrick 
363cab2bb3Spatrick   // Must be called after a new dynamic library is loaded.
373cab2bb3Spatrick   void OnLibraryLoaded(const char *name);
383cab2bb3Spatrick 
393cab2bb3Spatrick   // Must be called after a dynamic library is unloaded.
403cab2bb3Spatrick   void OnLibraryUnloaded();
413cab2bb3Spatrick 
423cab2bb3Spatrick   // Checks whether the provided PC belongs to one of the ignored libraries or
433cab2bb3Spatrick   // the PC should be ignored because it belongs to an non-instrumented module
443cab2bb3Spatrick   // (when ignore_noninstrumented_modules=1). Also returns true via
453cab2bb3Spatrick   // "pc_in_ignored_lib" if the PC is in an ignored library, false otherwise.
463cab2bb3Spatrick   bool IsIgnored(uptr pc, bool *pc_in_ignored_lib) const;
473cab2bb3Spatrick 
483cab2bb3Spatrick   // Checks whether the provided PC belongs to an instrumented module.
493cab2bb3Spatrick   bool IsPcInstrumented(uptr pc) const;
503cab2bb3Spatrick 
513cab2bb3Spatrick  private:
523cab2bb3Spatrick   struct Lib {
533cab2bb3Spatrick     char *templ;
543cab2bb3Spatrick     char *name;
553cab2bb3Spatrick     char *real_name;  // target of symlink
563cab2bb3Spatrick     bool loaded;
573cab2bb3Spatrick   };
583cab2bb3Spatrick 
593cab2bb3Spatrick   struct LibCodeRange {
603cab2bb3Spatrick     uptr begin;
613cab2bb3Spatrick     uptr end;
623cab2bb3Spatrick   };
633cab2bb3Spatrick 
IsInRange(uptr pc,const LibCodeRange & range)643cab2bb3Spatrick   inline bool IsInRange(uptr pc, const LibCodeRange &range) const {
653cab2bb3Spatrick     return (pc >= range.begin && pc < range.end);
663cab2bb3Spatrick   }
673cab2bb3Spatrick 
683cab2bb3Spatrick   static const uptr kMaxIgnoredRanges = 128;
693cab2bb3Spatrick   static const uptr kMaxInstrumentedRanges = 1024;
703cab2bb3Spatrick   static const uptr kMaxLibs = 1024;
713cab2bb3Spatrick 
723cab2bb3Spatrick   // Hot part:
733cab2bb3Spatrick   atomic_uintptr_t ignored_ranges_count_;
743cab2bb3Spatrick   LibCodeRange ignored_code_ranges_[kMaxIgnoredRanges];
753cab2bb3Spatrick 
763cab2bb3Spatrick   atomic_uintptr_t instrumented_ranges_count_;
773cab2bb3Spatrick   LibCodeRange instrumented_code_ranges_[kMaxInstrumentedRanges];
783cab2bb3Spatrick 
793cab2bb3Spatrick   // Cold part:
80*810390e3Srobert   Mutex mutex_;
813cab2bb3Spatrick   uptr count_;
823cab2bb3Spatrick   Lib libs_[kMaxLibs];
833cab2bb3Spatrick   bool track_instrumented_libs_;
843cab2bb3Spatrick 
853cab2bb3Spatrick   // Disallow copying of LibIgnore objects.
863cab2bb3Spatrick   LibIgnore(const LibIgnore&);  // not implemented
873cab2bb3Spatrick   void operator = (const LibIgnore&);  // not implemented
883cab2bb3Spatrick };
893cab2bb3Spatrick 
IsIgnored(uptr pc,bool * pc_in_ignored_lib)903cab2bb3Spatrick inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const {
913cab2bb3Spatrick   const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire);
923cab2bb3Spatrick   for (uptr i = 0; i < n; i++) {
933cab2bb3Spatrick     if (IsInRange(pc, ignored_code_ranges_[i])) {
943cab2bb3Spatrick       *pc_in_ignored_lib = true;
953cab2bb3Spatrick       return true;
963cab2bb3Spatrick     }
973cab2bb3Spatrick   }
983cab2bb3Spatrick   *pc_in_ignored_lib = false;
993cab2bb3Spatrick   if (track_instrumented_libs_ && !IsPcInstrumented(pc))
1003cab2bb3Spatrick     return true;
1013cab2bb3Spatrick   return false;
1023cab2bb3Spatrick }
1033cab2bb3Spatrick 
IsPcInstrumented(uptr pc)1043cab2bb3Spatrick inline bool LibIgnore::IsPcInstrumented(uptr pc) const {
1053cab2bb3Spatrick   const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire);
1063cab2bb3Spatrick   for (uptr i = 0; i < n; i++) {
1073cab2bb3Spatrick     if (IsInRange(pc, instrumented_code_ranges_[i]))
1083cab2bb3Spatrick       return true;
1093cab2bb3Spatrick   }
1103cab2bb3Spatrick   return false;
1113cab2bb3Spatrick }
1123cab2bb3Spatrick 
1133cab2bb3Spatrick }  // namespace __sanitizer
1143cab2bb3Spatrick 
1153cab2bb3Spatrick #endif  // SANITIZER_LIBIGNORE_H
116