1 /* -*- mode: C; c-basic-offset: 3; indent-tabs-mode: nil; -*- */ 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-2011 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 OrigFn fn; 94 VALGRIND_GET_ORIG_FN(fn); 95 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_MUTEX_INIT, 96 mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); 97 CALL_FN_W_WW(ret, fn, mutex, mode); 98 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_INIT, 99 mutex, 0, 0, 0, 0); 100 } 101 102 // QMutex::QMutex(RecursionMode) -- _ZN6QMutexC2ENS_13RecursionModeE 103 QT4CORE_FUNC(void, _ZN6QMutexC2ENS_13RecursionModeE, 104 void* mutex, 105 qt_mutex_mode mode) 106 { 107 int ret; 108 OrigFn fn; 109 VALGRIND_GET_ORIG_FN(fn); 110 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_MUTEX_INIT, 111 mutex, qt_to_drd_mutex_type(mode), 0, 0, 0); 112 CALL_FN_W_WW(ret, fn, mutex, mode); 113 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_INIT, 114 mutex, 0, 0, 0, 0); 115 } 116 117 // QMutex::~QMutex() -- _ZN6QMutexD1Ev 118 QT4CORE_FUNC(void, _ZN6QMutexD1Ev, 119 void* mutex) 120 { 121 int ret; 122 OrigFn fn; 123 VALGRIND_GET_ORIG_FN(fn); 124 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_MUTEX_DESTROY, 125 mutex, 0, 0, 0, 0); 126 CALL_FN_W_W(ret, fn, mutex); 127 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_DESTROY, 128 mutex, mutex_type(mutex), 0, 0, 0); 129 } 130 131 // QMutex::~QMutex() -- _ZN6QMutexD2Ev 132 QT4CORE_FUNC(void, _ZN6QMutexD2Ev, 133 void** mutex) 134 { 135 int ret; 136 OrigFn fn; 137 VALGRIND_GET_ORIG_FN(fn); 138 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_MUTEX_DESTROY, 139 mutex, 0, 0, 0, 0); 140 CALL_FN_W_W(ret, fn, mutex); 141 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_DESTROY, 142 mutex, mutex_type(mutex), 0, 0, 0); 143 } 144 145 // QMutex::lock() -- _ZN6QMutex4lockEv 146 QT4CORE_FUNC(void, _ZN6QMutex4lockEv, 147 void* mutex) 148 { 149 int ret; 150 OrigFn fn; 151 VALGRIND_GET_ORIG_FN(fn); 152 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRE_MUTEX_LOCK, 153 mutex, mutex_type(mutex), 0, 0, 0); 154 CALL_FN_W_W(ret, fn, mutex); 155 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__POST_MUTEX_LOCK, 156 mutex, 1, 0, 0, 0); 157 } 158 159 // QMutex::tryLock() -- _ZN6QMutex7tryLockEv 160 QT4CORE_FUNC(int, _ZN6QMutex7tryLockEv, 161 void* mutex) 162 { 163 int ret; 164 OrigFn fn; 165 VALGRIND_GET_ORIG_FN(fn); 166 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRE_MUTEX_LOCK, 167 mutex, mutex_type(mutex), 1, 0, 0); 168 CALL_FN_W_W(ret, fn, mutex); 169 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_LOCK, 170 mutex, ret, 0, 0, 0); 171 return ret; 172 } 173 174 // QMutex::tryLock(int) -- _ZN6QMutex7tryLockEi 175 QT4CORE_FUNC(int, _ZN6QMutex7tryLockEi, 176 void* mutex, 177 int timeout_ms) 178 { 179 int ret; 180 OrigFn fn; 181 VALGRIND_GET_ORIG_FN(fn); 182 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRE_MUTEX_LOCK, 183 mutex, mutex_type(mutex), 1, 0, 0); 184 CALL_FN_W_WW(ret, fn, mutex, timeout_ms); 185 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_LOCK, 186 mutex, ret, 0, 0, 0); 187 return ret; 188 } 189 190 // QMutex::unlock() -- _ZN6QMutex6unlockEv 191 QT4CORE_FUNC(void, _ZN6QMutex6unlockEv, 192 void* mutex) 193 { 194 int ret; 195 OrigFn fn; 196 VALGRIND_GET_ORIG_FN(fn); 197 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_MUTEX_UNLOCK, 198 mutex, mutex_type(mutex), 0, 0, 0); 199 CALL_FN_W_W(ret, fn, mutex); 200 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_UNLOCK, 201 mutex, 0, 0, 0, 0); 202 } 203