1 /* -*- mode: C; c-basic-offset: 3; -*- */ 2 3 /*--------------------------------------------------------------------*/ 4 /*--- Client-space code for drd. drd_qtcore_intercepts.c ---*/ 5 /*--------------------------------------------------------------------*/ 6 7 /* 8 This file is part of drd, a thread error detector. 9 10 Copyright (C) 2006-2010 Bart Van Assche <bvanassche (at) acm.org>. 11 12 This program is free software; you can redistribute it and/or 13 modify it under the terms of the GNU General Public License as 14 published by the Free Software Foundation; either version 2 of the 15 License, or (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, but 18 WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 25 02111-1307, USA. 26 27 The GNU General Public License is contained in the file COPYING. 28 */ 29 30 /* --------------------------------------------------------------------- 31 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU. 32 33 These functions are not called directly - they're the targets of code 34 redirection or load notifications (see pub_core_redir.h for info). 35 They're named weirdly so that the intercept code can find them when the 36 shared object is initially loaded. 37 38 Note that this filename has the "drd_" prefix because it can appear 39 in stack traces, and the "drd_" makes it a little clearer that it 40 originates from Valgrind. 41 ------------------------------------------------------------------ */ 42 43 #include <assert.h> 44 #include "drd_clientreq.h" 45 #include "pub_tool_redir.h" 46 47 48 // Defines. 49 50 #define QT4CORE_FUNC(ret_ty, f, args...) \ 51 ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args); \ 52 ret_ty VG_WRAP_FUNCTION_ZU(libQtCoreZdsoZd4,f)(args) 53 54 55 56 ////////////////////////////////////////////////////////////////// 57 // QMutex intercepts. 58 ////////////////////////////////////////////////////////////////// 59 60 61 typedef enum { qt_nonrecursive = 0, qt_recursive = 1 } qt_mutex_mode; 62 63 64 /** Convert a Qt4 mutex type to a DRD mutex type. */ 65 static MutexT qt_to_drd_mutex_type(qt_mutex_mode mode) 66 { 67 switch (mode) 68 { 69 case qt_nonrecursive: 70 return mutex_type_default_mutex; 71 case qt_recursive: 72 return mutex_type_recursive_mutex; 73 } 74 return mutex_type_invalid_mutex; 75 } 76 77 /** Find out the type of a Qt4 mutex (recursive or not). 78 * Since it's not possible to do this in a portable way, return 79 * mutex_type_unknown and let drd_mutex.c look up the real mutex type. 80 */ 81 static MutexT mutex_type(void* qt4_mutex) 82 { 83 return mutex_type_unknown; 84 } 85 86 87 // QMutex::QMutex(RecursionMode) -- _ZN6QMutexC1ENS_13RecursionModeE, 88 QT4CORE_FUNC(void, _ZN6QMutexC1ENS_13RecursionModeE, 89 void* mutex, 90 qt_mutex_mode mode) 91 { 92 int ret; 93 int res; 94 OrigFn fn; 95 VALGRIND_GET_ORIG_FN(fn); 96 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT, 97 mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); 98 CALL_FN_W_WW(ret, fn, mutex, mode); 99 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, 100 mutex, 0, 0, 0, 0); 101 } 102 103 // QMutex::QMutex(RecursionMode) -- _ZN6QMutexC2ENS_13RecursionModeE 104 QT4CORE_FUNC(void, _ZN6QMutexC2ENS_13RecursionModeE, 105 void* mutex, 106 qt_mutex_mode mode) 107 { 108 int ret; 109 int res; 110 OrigFn fn; 111 VALGRIND_GET_ORIG_FN(fn); 112 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT, 113 mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); 114 CALL_FN_W_WW(ret, fn, mutex, mode); 115 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, 116 mutex, 0, 0, 0, 0); 117 } 118 119 // QMutex::~QMutex() -- _ZN6QMutexD1Ev 120 QT4CORE_FUNC(void, _ZN6QMutexD1Ev, 121 void* mutex) 122 { 123 int ret; 124 int res; 125 OrigFn fn; 126 VALGRIND_GET_ORIG_FN(fn); 127 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, 128 mutex, 0, 0, 0, 0); 129 CALL_FN_W_W(ret, fn, mutex); 130 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, 131 mutex, mutex_type(mutex), 0, 0, 0); 132 } 133 134 // QMutex::~QMutex() -- _ZN6QMutexD2Ev 135 QT4CORE_FUNC(void, _ZN6QMutexD2Ev, 136 void** mutex) 137 { 138 int ret; 139 int res; 140 OrigFn fn; 141 VALGRIND_GET_ORIG_FN(fn); 142 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, 143 mutex, 0, 0, 0, 0); 144 CALL_FN_W_W(ret, fn, mutex); 145 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, 146 mutex, mutex_type(mutex), 0, 0, 0); 147 } 148 149 // QMutex::lock() -- _ZN6QMutex4lockEv 150 QT4CORE_FUNC(void, _ZN6QMutex4lockEv, 151 void* mutex) 152 { 153 int ret; 154 int res; 155 OrigFn fn; 156 VALGRIND_GET_ORIG_FN(fn); 157 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 158 mutex, mutex_type(mutex), 0, 0, 0); 159 CALL_FN_W_W(ret, fn, mutex); 160 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK, 161 mutex, 1, 0, 0, 0); 162 } 163 164 // QMutex::tryLock() -- _ZN6QMutex7tryLockEv 165 QT4CORE_FUNC(int, _ZN6QMutex7tryLockEv, 166 void* mutex) 167 { 168 int ret; 169 int res; 170 OrigFn fn; 171 VALGRIND_GET_ORIG_FN(fn); 172 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 173 mutex, mutex_type(mutex), 1, 0, 0); 174 CALL_FN_W_W(ret, fn, mutex); 175 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 176 mutex, ret, 0, 0, 0); 177 return ret; 178 } 179 180 // QMutex::tryLock(int) -- _ZN6QMutex7tryLockEi 181 QT4CORE_FUNC(int, _ZN6QMutex7tryLockEi, 182 void* mutex, 183 int timeout_ms) 184 { 185 int ret; 186 int res; 187 OrigFn fn; 188 VALGRIND_GET_ORIG_FN(fn); 189 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 190 mutex, mutex_type(mutex), 1, 0, 0); 191 CALL_FN_W_WW(ret, fn, mutex, timeout_ms); 192 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 193 mutex, ret, 0, 0, 0); 194 return ret; 195 } 196 197 // QMutex::unlock() -- _ZN6QMutex6unlockEv 198 QT4CORE_FUNC(void, _ZN6QMutex6unlockEv, 199 void* mutex) 200 { 201 int ret; 202 int res; 203 OrigFn fn; 204 VALGRIND_GET_ORIG_FN(fn); 205 VALGRIND_DO_CLIENT_REQUEST(res, -1, 206 VG_USERREQ__PRE_MUTEX_UNLOCK, 207 mutex, mutex_type(mutex), 0, 0, 0); 208 CALL_FN_W_W(ret, fn, mutex); 209 VALGRIND_DO_CLIENT_REQUEST(res, -1, 210 VG_USERREQ__POST_MUTEX_UNLOCK, 211 mutex, 0, 0, 0, 0); 212 } 213