sanitizer_thread_registry.cc \
sanitizer_tls_get_addr.cc \
sanitizer_unwind_linux_libcdep.cc \
- sanitizer_win.cc
+ sanitizer_win.cc \
+ sanitizer_forward_calls.cc
libsanitizer_common_la_SOURCES = $(sanitizer_common_files)
sanitizer_symbolizer_posix_libcdep.lo \
sanitizer_symbolizer_win.lo sanitizer_termination.lo \
sanitizer_thread_registry.lo sanitizer_tls_get_addr.lo \
- sanitizer_unwind_linux_libcdep.lo sanitizer_win.lo
+ sanitizer_unwind_linux_libcdep.lo sanitizer_win.lo \
+ sanitizer_forward_calls.lo
am_libsanitizer_common_la_OBJECTS = $(am__objects_1)
libsanitizer_common_la_OBJECTS = $(am_libsanitizer_common_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
sanitizer_thread_registry.cc \
sanitizer_tls_get_addr.cc \
sanitizer_unwind_linux_libcdep.cc \
- sanitizer_win.cc
+ sanitizer_win.cc \
+ sanitizer_forward_calls.cc
libsanitizer_common_la_SOURCES = $(sanitizer_common_files)
EXTRA_libsanitizer_common_la_SOURCES = sanitizer_linux_mips64.S sanitizer_linux_x86_64.S
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_deadlock_detector2.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_flag_parser.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_flags.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_forward_calls.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_libc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_libignore.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux.Plo@am__quote@
--- /dev/null
+//===-- sanitizer_forward_calls.cc ----------------------------------------===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of calls forwarding interface.
+// Used in applications to enable/disable forwarding calls from interceptors
+// to libc versions.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_forward_calls.h"
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_flags.h"
+
+#if SANITIZER_CALLS_FORWARDING
+
+namespace __sanitizer {
+// This flag controls the state of calls forwarding mechanism:
+// if unset, interceptors work as usual (they're "enabled");
+// if set, calls to interceptors are being forwarded to libc versions
+// (interceptors are "disabled").
+__attribute__((tls_model("initial-exec")))
+static THREADLOCAL bool *forward_flag;
+
+static bool *GetFlag()
+{
+ if (UNLIKELY(!forward_flag)) {
+ // We will not release the memory.
+ forward_flag = (bool *)InternalAlloc(sizeof(*forward_flag));
+ *forward_flag = !common_flags()->enable_interceptors;
+ }
+
+ return forward_flag;
+}
+
+static void SetForwardingCalls(bool val) {
+ *GetFlag() = val;
+}
+
+static bool GetForwardingCalls() {
+ return *GetFlag();
+}
+
+bool ForwardCalls() {
+ return __sanitizer::GetForwardingCalls();
+}
+} // namespace __sanitizer
+
+extern "C" {
+// "Enables" interceptors (disabling calls forwarding mechanism):
+// interceptors now work in usual mode.
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+void __sanitizer_enable_interceptors() {
+ __sanitizer::SetForwardingCalls(false);
+}
+
+// "Disables" interceptors (enabling calls forwarding mechanism):
+// interceptors become transparent and calls to them are forwarded to libc.
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+void __sanitizer_disable_interceptors() {
+ __sanitizer::SetForwardingCalls(true);
+}
+
+// Checks current state of calls forwarding mechanism: whether interceptors
+// enabled or not.
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+bool __sanitizer_interceptors_are_enabled() {
+ return !__sanitizer::ForwardCalls();
+}
+} // extern "C"
+
+#endif // SANITIZER_CALLS_FORWARDING
--- /dev/null
+//===-- sanitizer_forward_calls.h -------------------------------*- C++ -*-===//
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// General calls forwarding interface. Used in interceptors.
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_FORWARD_CALLS_H
+#define SANITIZER_FORWARD_CALLS_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+
+#if SANITIZER_CALLS_FORWARDING
+
+namespace __sanitizer {
+bool ForwardCalls();
+}
+
+// This macro checks whether calls forwarding mechanism is currently enabled
+// (flag sanitizer_forward_calls is set). If it is, we call the libc version,
+// which is REAL(func).
+// If REAL(func) is unset, i.e. this symbol hasn't been intercepted yet, we
+// first try to intercept it (via call to dlsym), then call the libc version.
+//
+// Note: as dlsym may use memory allocations internally, we enable interceptors
+// (i.e. disable calls forwarding) before and disable them after calling
+// INTERCEPT_FUNCTION, thus enforcing usage of ASan memory-related functions
+// and avoiding alloc-dealloc mismatch issues.
+#define MAYBE_FORWARD_TO_REAL(func, ...) \
+ do { \
+ if (__sanitizer::ForwardCalls()) { \
+ if (LIKELY(REAL(func))) \
+ return REAL(func)(__VA_ARGS__); \
+ else { \
+ VReport(1, "WARNING: function '"#func"' wasn't" \
+ " intercepted; intercepting now\n"); \
+ __sanitizer_enable_interceptors(); \
+ bool int_res = INTERCEPT_FUNCTION(func); \
+ __sanitizer_disable_interceptors(); \
+ if (!int_res || !REAL(func)) \
+ VReport(1, "Failed to intercept function '"#func"'\n"); \
+ else \
+ return REAL(func)(__VA_ARGS__); \
+ } \
+ } \
+ } while (0)
+
+#else
+
+#define MAYBE_FORWARD_TO_REAL(func, ...) {}
+
+#endif // SANITIZER_CALLS_FORWARDING
+
+#endif // SANITIZER_FORWARD_CALLS_H
char *module_name,
__sanitizer::uptr module_name_len,
__sanitizer::uptr *pc_offset);
+
+#if SANITIZER_CALLS_FORWARDING
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ void __sanitizer_enable_interceptors();
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ void __sanitizer_disable_interceptors();
+ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ bool __sanitizer_interceptors_are_enabled();
+#endif // SANITIZER_CALLS_FORWARDING
} // extern "C"
#endif // SANITIZER_INTERFACE_INTERNAL_H
# define SANITIZER_CAN_USE_PREINIT_ARRAY 0
#endif
+#ifdef SANITIZER_SWITCHABLE_INTERCEPTORS
+# if SANITIZER_LINUX && !SANITIZER_ANDROID
+# define SANITIZER_CALLS_FORWARDING 1
+# else
+# error "This platform does not support switchable interceptors"
+# endif
+#else
+# define SANITIZER_CALLS_FORWARDING 0
+#endif // SANITIZER_SWITCHABLE_INTERCEPTORS
+
// GCC does not understand __has_feature
#if !defined(__has_feature)
# define __has_feature(x) 0