Home | History | Annotate | Download | only in sanitizer_common
      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 remembers all "called_from_lib" suppressions
     12 // from the provided SuppressionContext; 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_suppressions.h"
     23 #include "sanitizer_atomic.h"
     24 #include "sanitizer_mutex.h"
     25 
     26 namespace __sanitizer {
     27 
     28 class LibIgnore {
     29  public:
     30   explicit LibIgnore(LinkerInitialized);
     31 
     32   // Fetches all "called_from_lib" suppressions from the SuppressionContext.
     33   void Init(const SuppressionContext &supp);
     34 
     35   // Must be called after a new dynamic library is loaded.
     36   void OnLibraryLoaded(const char *name);
     37 
     38   // Must be called after a dynamic library is unloaded.
     39   void OnLibraryUnloaded();
     40 
     41   // Checks whether the provided PC belongs to one of the ignored libraries.
     42   bool IsIgnored(uptr pc) const;
     43 
     44  private:
     45   struct Lib {
     46     char *templ;
     47     char *name;
     48     char *real_name;  // target of symlink
     49     bool loaded;
     50   };
     51 
     52   struct LibCodeRange {
     53     uptr begin;
     54     uptr end;
     55   };
     56 
     57   static const uptr kMaxLibs = 128;
     58 
     59   // Hot part:
     60   atomic_uintptr_t loaded_count_;
     61   LibCodeRange code_ranges_[kMaxLibs];
     62 
     63   // Cold part:
     64   BlockingMutex mutex_;
     65   uptr count_;
     66   Lib libs_[kMaxLibs];
     67 
     68   // Disallow copying of LibIgnore objects.
     69   LibIgnore(const LibIgnore&);  // not implemented
     70   void operator = (const LibIgnore&);  // not implemented
     71 };
     72 
     73 inline bool LibIgnore::IsIgnored(uptr pc) const {
     74   const uptr n = atomic_load(&loaded_count_, memory_order_acquire);
     75   for (uptr i = 0; i < n; i++) {
     76     if (pc >= code_ranges_[i].begin && pc < code_ranges_[i].end)
     77       return true;
     78   }
     79   return false;
     80 }
     81 
     82 }  // namespace __sanitizer
     83 
     84 #endif  // SANITIZER_LIBIGNORE_H
     85