aboutsummaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_libignore.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sanitizer_common/sanitizer_libignore.h')
-rw-r--r--lib/sanitizer_common/sanitizer_libignore.h84
1 files changed, 84 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_libignore.h b/lib/sanitizer_common/sanitizer_libignore.h
new file mode 100644
index 000000000000..8e1d584d8e3c
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_libignore.h
@@ -0,0 +1,84 @@
+//===-- 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(const char *name);
+
+ // 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;
+ char *real_name; // target of symlink
+ 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