From: Bart Van Assche Date: Mon, 9 Jun 2014 07:55:14 +0000 (+0000) Subject: drd: Add __cxa_guard_*() intercepts X-Git-Tag: svn/VALGRIND_3_10_0~425 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d665dce62ecbc7c108c7e4081a908be977c5fa09;p=thirdparty%2Fvalgrind.git drd: Add __cxa_guard_*() intercepts git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14012 --- diff --git a/drd/Makefile.am b/drd/Makefile.am index 153b38484c..4ead4ecb8f 100644 --- a/drd/Makefile.am +++ b/drd/Makefile.am @@ -122,6 +122,7 @@ noinst_DSYMS = $(noinst_PROGRAMS) 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 c5d0623ef3..929b60d100 100644 --- a/drd/drd_clientreq.h +++ b/drd/drd_clientreq.h @@ -240,6 +240,7 @@ typedef enum { 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 0000000000..99cbd3f5c6 --- /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 . + + 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 */ +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 */ +#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 4c836fde09..12ee4de3ec 100644 --- a/drd/drd_mutex.c +++ b/drd/drd_mutex.c @@ -468,6 +468,8 @@ const HChar* DRD_(mutex_type_name)(const MutexT mt) return "mutex"; case mutex_type_spinlock: return "spinlock"; + case mutex_type_cxa_guard: + return "cxa_guard"; } tl_assert(0); return "?";