1 /*--------------------------------------------------------------------*/ 2 /*--- Client-space code for drd. drd_qtcore_intercepts.c ---*/ 3 /*--------------------------------------------------------------------*/ 4 5 /* 6 This file is part of drd, a thread error detector. 7 8 Copyright (C) 2006-2013 Bart Van Assche <bvanassche (at) 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 <assert.h> 42 #include "drd_clientreq.h" 43 #include "pub_tool_redir.h" 44 45 46 // Defines. 47 48 #define QT4CORE_FUNC(ret_ty, f, args...) \ 49 ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args); \ 50 ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args) 51 52 53 54 ////////////////////////////////////////////////////////////////// 55 // QMutex intercepts. 56 ////////////////////////////////////////////////////////////////// 57 58 59 typedef enum { qt_nonrecursive = 0, qt_recursive = 1 } qt_mutex_mode; 60 61 62 /** Convert a Qt4 mutex type to a DRD mutex type. */ 63 static MutexT qt_to_drd_mutex_type(qt_mutex_mode mode) 64 { 65 switch (mode) 66 { 67 case qt_nonrecursive: 68 return mutex_type_default_mutex; 69 case qt_recursive: 70 return mutex_type_recursive_mutex; 71 } 72 return mutex_type_invalid_mutex; 73 } 74 75 /** Find out the type of a Qt4 mutex (recursive or not). 76 * Since it's not possible to do this in a portable way, return 77 * mutex_type_unknown and let drd_mutex.c look up the real mutex type. 78 */ 79 static MutexT mutex_type(void* qt4_mutex) 80 { 81 return mutex_type_unknown; 82 } 83 84 85 // QMutex::QMutex(RecursionMode) -- _ZN6QMutexC1ENS_13RecursionModeE, 86 QT4CORE_FUNC(void, _ZN6QMutexC1ENS_13RecursionModeE, 87 void* mutex, 88 qt_mutex_mode mode) 89 { 90 int ret; 91 OrigFn fn; 92 VALGRIND_GET_ORIG_FN(fn); 93 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_INIT, 94 mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); 95 CALL_FN_W_WW(ret, fn, mutex, mode); 96 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_INIT, 97 mutex, 0, 0, 0, 0); 98 } 99 100 // QMutex::QMutex(RecursionMode) -- _ZN6QMutexC2ENS_13RecursionModeE 101 QT4CORE_FUNC(void, _ZN6QMutexC2ENS_13RecursionModeE, 102 void* mutex, 103 qt_mutex_mode mode) 104 { 105 int ret; 106 OrigFn fn; 107 VALGRIND_GET_ORIG_FN(fn); 108 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_INIT, 109 mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); 110 CALL_FN_W_WW(ret, fn, mutex, mode); 111 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_INIT, 112 mutex, 0, 0, 0, 0); 113 } 114 115 // QMutex::~QMutex() -- _ZN6QMutexD1Ev 116 QT4CORE_FUNC(void, _ZN6QMutexD1Ev, 117 void* mutex) 118 { 119 int ret; 120 OrigFn fn; 121 VALGRIND_GET_ORIG_FN(fn); 122 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY, 123 mutex, 0, 0, 0, 0); 124 CALL_FN_W_W(ret, fn, mutex); 125 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY, 126 mutex, mutex_type(mutex), 0, 0, 0); 127 } 128 129 // QMutex::~QMutex() -- _ZN6QMutexD2Ev 130 QT4CORE_FUNC(void, _ZN6QMutexD2Ev, 131 void** mutex) 132 { 133 int ret; 134 OrigFn fn; 135 VALGRIND_GET_ORIG_FN(fn); 136 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY, 137 mutex, 0, 0, 0, 0); 138 CALL_FN_W_W(ret, fn, mutex); 139 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY, 140 mutex, mutex_type(mutex), 0, 0, 0); 141 } 142 143 // QMutex::lock() -- _ZN6QMutex4lockEv 144 QT4CORE_FUNC(void, _ZN6QMutex4lockEv, 145 void* mutex) 146 { 147 int ret; 148 OrigFn fn; 149 VALGRIND_GET_ORIG_FN(fn); 150 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 151 mutex, mutex_type(mutex), 0, 0, 0); 152 CALL_FN_W_W(ret, fn, mutex); 153 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 154 mutex, 1, 0, 0, 0); 155 } 156 157 // QMutex::tryLock() -- _ZN6QMutex7tryLockEv 158 QT4CORE_FUNC(int, _ZN6QMutex7tryLockEv, 159 void* mutex) 160 { 161 int ret; 162 OrigFn fn; 163 VALGRIND_GET_ORIG_FN(fn); 164 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 165 mutex, mutex_type(mutex), 1, 0, 0); 166 CALL_FN_W_W(ret, fn, mutex); 167 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 168 mutex, ret, 0, 0, 0); 169 return ret; 170 } 171 172 // QMutex::tryLock(int) -- _ZN6QMutex7tryLockEi 173 QT4CORE_FUNC(int, _ZN6QMutex7tryLockEi, 174 void* mutex, 175 int timeout_ms) 176 { 177 int ret; 178 OrigFn fn; 179 VALGRIND_GET_ORIG_FN(fn); 180 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 181 mutex, mutex_type(mutex), 1, 0, 0); 182 CALL_FN_W_WW(ret, fn, mutex, timeout_ms); 183 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 184 mutex, ret, 0, 0, 0); 185 return ret; 186 } 187 188 // QMutex::unlock() -- _ZN6QMutex6unlockEv 189 QT4CORE_FUNC(void, _ZN6QMutex6unlockEv, 190 void* mutex) 191 { 192 int ret; 193 OrigFn fn; 194 VALGRIND_GET_ORIG_FN(fn); 195 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_UNLOCK, 196 mutex, mutex_type(mutex), 0, 0, 0); 197 CALL_FN_W_W(ret, fn, mutex); 198 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_UNLOCK, 199 mutex, 0, 0, 0, 0); 200 } 201