Home | History | Annotate | Download | only in drd
      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