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