drd: Add __cxa_guard_*() intercepts
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14012 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/drd/Makefile.am b/drd/Makefile.am
index 153b384..4ead4ec 100644
--- a/drd/Makefile.am
+++ b/drd/Makefile.am
@@ -122,6 +122,7 @@
endif
VGPRELOAD_DRD_SOURCES_COMMON = \
+ drd_libstdcxx_intercepts.c \
drd_pthread_intercepts.c \
drd_qtcore_intercepts.c \
drd_strmem_intercepts.c
diff --git a/drd/drd_clientreq.h b/drd/drd_clientreq.h
index c5d0623..929b60d 100644
--- a/drd/drd_clientreq.h
+++ b/drd/drd_clientreq.h
@@ -240,6 +240,7 @@
mutex_type_errorcheck_mutex = 2,
mutex_type_default_mutex = 3,
mutex_type_spinlock = 4,
+ mutex_type_cxa_guard = 5,
} MutexT;
/**
diff --git a/drd/drd_libstdcxx_intercepts.c b/drd/drd_libstdcxx_intercepts.c
new file mode 100644
index 0000000..99cbd3f
--- /dev/null
+++ b/drd/drd_libstdcxx_intercepts.c
@@ -0,0 +1,109 @@
+/*--------------------------------------------------------------------*/
+/*--- Client-space code for DRD. drd_libstdcxx_intercepts.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of DRD, a thread error detector.
+
+ Copyright (C) 2014 Bart Van Assche <bvanassche@acm.org>.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* ---------------------------------------------------------------------
+ ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
+
+ These functions are not called directly - they're the targets of code
+ redirection or load notifications (see pub_core_redir.h for info).
+ They're named weirdly so that the intercept code can find them when the
+ shared object is initially loaded.
+
+ Note that this filename has the "drd_" prefix because it can appear
+ in stack traces, and the "drd_" makes it a little clearer that it
+ originates from Valgrind.
+ ------------------------------------------------------------------ */
+
+#include "drd_basics.h" /* DRD_() */
+#include "drd_clientreq.h"
+#include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */
+
+/* From <cxxabi.h> */
+int __cxa_guard_acquire(void* guard);
+void __cxa_guard_release(void* guard) __attribute__((__nothrow__));
+void __cxa_guard_abort(void* guard) __attribute__((__nothrow__));
+
+#define LIBSTDCXX_FUNC(ret_ty, zf, implf, argl_decl, argl) \
+ ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBSTDCXX_SONAME,zf) argl_decl; \
+ ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBSTDCXX_SONAME,zf) argl_decl \
+ { return implf argl; }
+
+/*
+ * Not inlining one of the intercept functions will cause the regression
+ * tests to fail because this would cause an additional stackfram to appear
+ * in the output. The __always_inline macro guarantees that inlining will
+ * happen, even when compiling with optimization disabled.
+ */
+#undef __always_inline /* since already defined in <cdefs.h> */
+#if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 2
+#define __always_inline __inline__ __attribute__((always_inline))
+#else
+#define __always_inline __inline__
+#endif
+
+static __always_inline
+int __cxa_guard_acquire_intercept(void *guard)
+{
+ int ret;
+ OrigFn fn;
+ VALGRIND_GET_ORIG_FN(fn);
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
+ guard, mutex_type_cxa_guard, 0, 0, 0);
+ CALL_FN_W_W(ret, fn, guard);
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
+ guard, 1, 0, 0, 0);
+ if (ret == 0) {
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_UNLOCK,
+ guard, mutex_type_cxa_guard, 0, 0, 0);
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_UNLOCK,
+ guard, 0, 0, 0, 0);
+ }
+ return ret;
+}
+
+LIBSTDCXX_FUNC(int, ZuZucxaZuguardZuacquire, __cxa_guard_acquire_intercept,
+ (void *guard), (guard));
+LIBSTDCXX_FUNC(int, ZuZucxaZuguardZuacquireZAZACXXABIZu1Zd3,
+ __cxa_guard_acquire_intercept, (void *guard), (guard));
+
+static __always_inline
+void __cxa_guard_abort_release_intercept(void *guard)
+{
+ int ret;
+ OrigFn fn;
+ VALGRIND_GET_ORIG_FN(fn);
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_UNLOCK,
+ guard, mutex_type_cxa_guard, 0, 0, 0);
+ CALL_FN_W_W(ret, fn, guard);
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_UNLOCK,
+ guard, 0, 0, 0, 0);
+}
+
+LIBSTDCXX_FUNC(void, ZuZucxaZuguardZurelease,
+ __cxa_guard_abort_release_intercept, (void *guard), (guard));
+LIBSTDCXX_FUNC(void, ZuZucxaZuguardZuabort,
+ __cxa_guard_abort_release_intercept, (void *guard), (guard));
diff --git a/drd/drd_mutex.c b/drd/drd_mutex.c
index 4c836fd..12ee4de 100644
--- a/drd/drd_mutex.c
+++ b/drd/drd_mutex.c
@@ -468,6 +468,8 @@
return "mutex";
case mutex_type_spinlock:
return "spinlock";
+ case mutex_type_cxa_guard:
+ return "cxa_guard";
}
tl_assert(0);
return "?";