14af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov//===-- sanitizer_libignore.h -----------------------------------*- C++ -*-===//
24af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov//
34af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov//                     The LLVM Compiler Infrastructure
44af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov//
54af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov// This file is distributed under the University of Illinois Open Source
64af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov// License. See LICENSE.TXT for details.
74af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov//
84af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov//===----------------------------------------------------------------------===//
94af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov//
104af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov// LibIgnore allows to ignore all interceptors called from a particular set
1186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// of dynamic libraries. LibIgnore can be initialized with several templates
1286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// of names of libraries to be ignored. It finds code ranges for the libraries;
134af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov// and checks whether the provided PC value belongs to the code ranges.
144af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov//
154af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov//===----------------------------------------------------------------------===//
164af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
174af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov#ifndef SANITIZER_LIBIGNORE_H
184af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov#define SANITIZER_LIBIGNORE_H
194af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
204af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov#include "sanitizer_internal_defs.h"
214af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov#include "sanitizer_common.h"
224af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov#include "sanitizer_atomic.h"
234af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov#include "sanitizer_mutex.h"
244af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
254af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukovnamespace __sanitizer {
264af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
274af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukovclass LibIgnore {
284af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov public:
294af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  explicit LibIgnore(LinkerInitialized);
304af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
3186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Must be called during initialization.
3286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void AddIgnoredLibrary(const char *name_templ);
334af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
344af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  // Must be called after a new dynamic library is loaded.
353dbbd850cde5728c35aa4c15a279d858604fc6eeDmitry Vyukov  void OnLibraryLoaded(const char *name);
364af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
374af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  // Must be called after a dynamic library is unloaded.
384af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  void OnLibraryUnloaded();
394af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
404af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  // Checks whether the provided PC belongs to one of the ignored libraries.
414af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  bool IsIgnored(uptr pc) const;
424af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
434af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov private:
444af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  struct Lib {
454af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov    char *templ;
464af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov    char *name;
473dbbd850cde5728c35aa4c15a279d858604fc6eeDmitry Vyukov    char *real_name;  // target of symlink
484af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov    bool loaded;
494af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  };
504af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
514af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  struct LibCodeRange {
524af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov    uptr begin;
534af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov    uptr end;
544af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  };
554af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
564af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  static const uptr kMaxLibs = 128;
574af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
584af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  // Hot part:
594af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  atomic_uintptr_t loaded_count_;
604af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  LibCodeRange code_ranges_[kMaxLibs];
614af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
624af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  // Cold part:
634af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  BlockingMutex mutex_;
644af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  uptr count_;
654af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  Lib libs_[kMaxLibs];
664af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
674af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  // Disallow copying of LibIgnore objects.
684af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  LibIgnore(const LibIgnore&);  // not implemented
694af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  void operator = (const LibIgnore&);  // not implemented
704af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov};
714af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
724af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukovinline bool LibIgnore::IsIgnored(uptr pc) const {
734af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  const uptr n = atomic_load(&loaded_count_, memory_order_acquire);
744af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  for (uptr i = 0; i < n; i++) {
754af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov    if (pc >= code_ranges_[i].begin && pc < code_ranges_[i].end)
764af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov      return true;
774af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  }
784af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  return false;
794af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov}
804af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
814af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov}  // namespace __sanitizer
824af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov
834af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov#endif  // SANITIZER_LIBIGNORE_H
84