• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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