1/*--------------------------------------------------------------------*/ 2/*--- Client-space code for DRD. drd_libstdcxx_intercepts.c ---*/ 3/*--------------------------------------------------------------------*/ 4 5/* 6 This file is part of DRD, a thread error detector. 7 8 Copyright (C) 2014-2015 Bart Van Assche <bvanassche@acm.org>. 9 10 This program is free software; you can redistribute it and/or 11 modify it under the terms of the GNU General Public License as 12 published by the Free Software Foundation; either version 2 of the 13 License, or (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, but 16 WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 23 02111-1307, USA. 24 25 The GNU General Public License is contained in the file COPYING. 26*/ 27 28/* --------------------------------------------------------------------- 29 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU. 30 31 These functions are not called directly - they're the targets of code 32 redirection or load notifications (see pub_core_redir.h for info). 33 They're named weirdly so that the intercept code can find them when the 34 shared object is initially loaded. 35 36 Note that this filename has the "drd_" prefix because it can appear 37 in stack traces, and the "drd_" makes it a little clearer that it 38 originates from Valgrind. 39 ------------------------------------------------------------------ */ 40 41#include "drd_basics.h" /* DRD_() */ 42#include "drd_clientreq.h" 43#include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */ 44 45/* From <cxxabi.h> */ 46int __cxa_guard_acquire(void* guard); 47void __cxa_guard_release(void* guard) __attribute__((__nothrow__)); 48void __cxa_guard_abort(void* guard) __attribute__((__nothrow__)); 49 50#define LIBSTDCXX_FUNC(ret_ty, zf, implf, argl_decl, argl) \ 51 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBSTDCXX_SONAME,zf) argl_decl; \ 52 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBSTDCXX_SONAME,zf) argl_decl \ 53 { return implf argl; } 54 55/* 56 * Not inlining one of the intercept functions will cause the regression 57 * tests to fail because this would cause an additional stackfram to appear 58 * in the output. The __always_inline macro guarantees that inlining will 59 * happen, even when compiling with optimization disabled. 60 */ 61#undef __always_inline /* since already defined in <cdefs.h> */ 62#if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 2 63#define __always_inline __inline__ __attribute__((always_inline)) 64#else 65#define __always_inline __inline__ 66#endif 67 68static __always_inline 69int __cxa_guard_acquire_intercept(void *guard) 70{ 71 int ret; 72 OrigFn fn; 73 VALGRIND_GET_ORIG_FN(fn); 74 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 75 guard, mutex_type_cxa_guard, 0, 0, 0); 76 CALL_FN_W_W(ret, fn, guard); 77 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 78 guard, 1, 0, 0, 0); 79 if (ret == 0) { 80 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_UNLOCK, 81 guard, mutex_type_cxa_guard, 0, 0, 0); 82 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_UNLOCK, 83 guard, 0, 0, 0, 0); 84 } 85 return ret; 86} 87 88LIBSTDCXX_FUNC(int, ZuZucxaZuguardZuacquire, __cxa_guard_acquire_intercept, 89 (void *guard), (guard)); 90LIBSTDCXX_FUNC(int, ZuZucxaZuguardZuacquireZAZACXXABIZu1Zd3, 91 __cxa_guard_acquire_intercept, (void *guard), (guard)); 92 93static __always_inline 94void __cxa_guard_abort_release_intercept(void *guard) 95{ 96 int ret; 97 OrigFn fn; 98 VALGRIND_GET_ORIG_FN(fn); 99 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_UNLOCK, 100 guard, mutex_type_cxa_guard, 0, 0, 0); 101 CALL_FN_W_W(ret, fn, guard); 102 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_UNLOCK, 103 guard, 0, 0, 0, 0); 104} 105 106LIBSTDCXX_FUNC(void, ZuZucxaZuguardZurelease, 107 __cxa_guard_abort_release_intercept, (void *guard), (guard)); 108LIBSTDCXX_FUNC(void, ZuZucxaZuguardZuabort, 109 __cxa_guard_abort_release_intercept, (void *guard), (guard)); 110