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