summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Drobyshev <a.drobyshev@samsung.com>2019-04-25 12:20:00 +0300
committerDongkyun Son <dongkyun.s@samsung.com>2019-07-27 16:37:14 +0000
commit3bb58afb11d68578d6d9bbb35ebf22c33d3a4aee (patch)
treee9cab03cf802c31ef60171ba1a199a86984b3511
parent01baebcf2719b6e9f67b91f4856a4875fb2f2852 (diff)
downloadlinaro-gcc-3bb58afb11d68578d6d9bbb35ebf22c33d3a4aee.tar.gz
linaro-gcc-3bb58afb11d68578d6d9bbb35ebf22c33d3a4aee.tar.bz2
linaro-gcc-3bb58afb11d68578d6d9bbb35ebf22c33d3a4aee.zip
libsanitizer: introduce calls forwarding mechanism.
* libsanitizer/sanitizer_common/Makefile.am: add file sanitizer_forward_calls.cc * libsanitizer/sanitizer_common/Makefile.in: regenerated * libsanitizer/sanitizer_common/sanitizer_forward_calls.cc: new file, implementation of calls forwarding interface * libsanitizer/sanitizer_common/sanitizer_forward_calls.h: new file, macro MAYBE_FORWARD_TO_REAL used in interceptors * libsanitizer/sanitizer_common/sanitizer_interface_internal.h: add declarations of interface functions for enabling/disabling interceptors * libsanitizer/sanitizer_common/sanitizer_internal_defs.h: add SANITIZER_CALLS_FORWARDING macro Change-Id: I41367e63283798920a4cabc8a01f0192146b9057 Signed-off-by: Andrey Drobyshev <a.drobyshev@samsung.com>
-rw-r--r--libsanitizer/sanitizer_common/Makefile.am3
-rw-r--r--libsanitizer/sanitizer_common/Makefile.in7
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_forward_calls.cc74
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_forward_calls.h58
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_interface_internal.h9
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_internal_defs.h10
6 files changed, 158 insertions, 3 deletions
diff --git a/libsanitizer/sanitizer_common/Makefile.am b/libsanitizer/sanitizer_common/Makefile.am
index 4996b9ec36b..4cb75245dbe 100644
--- a/libsanitizer/sanitizer_common/Makefile.am
+++ b/libsanitizer/sanitizer_common/Makefile.am
@@ -61,7 +61,8 @@ sanitizer_common_files = \
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)
diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in
index 87eb3d3c3a3..05ef11f65aa 100644
--- a/libsanitizer/sanitizer_common/Makefile.in
+++ b/libsanitizer/sanitizer_common/Makefile.in
@@ -105,7 +105,8 @@ am__objects_1 = sanitizer_allocator.lo sanitizer_common.lo \
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)
@@ -344,7 +345,8 @@ sanitizer_common_files = \
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
@@ -452,6 +454,7 @@ distclean-compile:
@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@
diff --git a/libsanitizer/sanitizer_common/sanitizer_forward_calls.cc b/libsanitizer/sanitizer_common/sanitizer_forward_calls.cc
new file mode 100644
index 00000000000..ac996a6678f
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_forward_calls.cc
@@ -0,0 +1,74 @@
+//===-- 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
diff --git a/libsanitizer/sanitizer_common/sanitizer_forward_calls.h b/libsanitizer/sanitizer_common/sanitizer_forward_calls.h
new file mode 100644
index 00000000000..92c29bc1765
--- /dev/null
+++ b/libsanitizer/sanitizer_common/sanitizer_forward_calls.h
@@ -0,0 +1,58 @@
+//===-- 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
diff --git a/libsanitizer/sanitizer_common/sanitizer_interface_internal.h b/libsanitizer/sanitizer_common/sanitizer_interface_internal.h
index 04b8226eee7..363af03854a 100644
--- a/libsanitizer/sanitizer_common/sanitizer_interface_internal.h
+++ b/libsanitizer/sanitizer_common/sanitizer_interface_internal.h
@@ -67,6 +67,15 @@ extern "C" {
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
diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
index b9c906669de..b9f076bdcd9 100644
--- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
+++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h
@@ -45,6 +45,16 @@
# 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