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@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. */
qt_to_drd_mutex_type(qt_mutex_mode mode)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 */
mutex_type(void * qt4_mutex)81 static MutexT mutex_type(void* qt4_mutex)
82 {
83 return mutex_type_unknown;
84 }
85
86
87 // QMutex::QMutex(RecursionMode) -- _ZN6QMutexC1ENS_13RecursionModeE,
QT4CORE_FUNC(void,_ZN6QMutexC1ENS_13RecursionModeE,void * mutex,qt_mutex_mode mode)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
QT4CORE_FUNC(void,_ZN6QMutexC2ENS_13RecursionModeE,void * mutex,qt_mutex_mode mode)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
QT4CORE_FUNC(void,_ZN6QMutexD1Ev,void * mutex)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
QT4CORE_FUNC(void,_ZN6QMutexD2Ev,void ** mutex)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
QT4CORE_FUNC(void,_ZN6QMutex4lockEv,void * mutex)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
QT4CORE_FUNC(int,_ZN6QMutex7tryLockEv,void * mutex)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
QT4CORE_FUNC(int,_ZN6QMutex7tryLockEi,void * mutex,int timeout_ms)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
QT4CORE_FUNC(void,_ZN6QMutex6unlockEv,void * mutex)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