diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2013-10-03 13:37:17 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2013-10-03 13:37:17 +0000 |
commit | 4af0f21c0c98950df1136dbec8824a029ed5bb8e (patch) | |
tree | c627364c732421ba62a21cbf7f96d86fbfbd3c0d /lib/sanitizer_common/sanitizer_libignore.h | |
parent | 984930932ac6d85af5b07294a91b203ce822dc68 (diff) |
tsan: ignore interceptors coming from specified libraries
LibIgnore allows to ignore all interceptors called from a particular set
of dynamic libraries. LibIgnore remembers all "called_from_lib" suppressions
from the provided SuppressionContext; finds code ranges for the libraries;
and checks whether the provided PC value belongs to the code ranges.
Also make malloc and friends interceptors use SCOPED_INTERCEPTOR_RAW instead of
SCOPED_TSAN_INTERCEPTOR, because if they are called from an ignored lib,
then must call our internal allocator instead of libc malloc.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@191897 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_libignore.h')
-rw-r--r-- | lib/sanitizer_common/sanitizer_libignore.h | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_libignore.h b/lib/sanitizer_common/sanitizer_libignore.h new file mode 100644 index 000000000..4e6f5a97a --- /dev/null +++ b/lib/sanitizer_common/sanitizer_libignore.h @@ -0,0 +1,83 @@ +//===-- sanitizer_libignore.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// LibIgnore allows to ignore all interceptors called from a particular set +// of dynamic libraries. LibIgnore remembers all "called_from_lib" suppressions +// from the provided SuppressionContext; finds code ranges for the libraries; +// and checks whether the provided PC value belongs to the code ranges. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_LIBIGNORE_H +#define SANITIZER_LIBIGNORE_H + +#include "sanitizer_internal_defs.h" +#include "sanitizer_common.h" +#include "sanitizer_suppressions.h" +#include "sanitizer_atomic.h" +#include "sanitizer_mutex.h" + +namespace __sanitizer { + +class LibIgnore { + public: + explicit LibIgnore(LinkerInitialized); + + // Fetches all "called_from_lib" suppressions from the SuppressionContext. + void Init(const SuppressionContext &supp); + + // Must be called after a new dynamic library is loaded. + void OnLibraryLoaded(); + + // Must be called after a dynamic library is unloaded. + void OnLibraryUnloaded(); + + // Checks whether the provided PC belongs to one of the ignored libraries. + bool IsIgnored(uptr pc) const; + + private: + struct Lib { + char *templ; + char *name; + bool loaded; + }; + + struct LibCodeRange { + uptr begin; + uptr end; + }; + + static const uptr kMaxLibs = 128; + + // Hot part: + atomic_uintptr_t loaded_count_; + LibCodeRange code_ranges_[kMaxLibs]; + + // Cold part: + BlockingMutex mutex_; + uptr count_; + Lib libs_[kMaxLibs]; + + // Disallow copying of LibIgnore objects. + LibIgnore(const LibIgnore&); // not implemented + void operator = (const LibIgnore&); // not implemented +}; + +inline bool LibIgnore::IsIgnored(uptr pc) const { + const uptr n = atomic_load(&loaded_count_, memory_order_acquire); + for (uptr i = 0; i < n; i++) { + if (pc >= code_ranges_[i].begin && pc < code_ranges_[i].end) + return true; + } + return false; +} + +} // namespace __sanitizer + +#endif // SANITIZER_LIBIGNORE_H |