Home | History | Annotate | Download | only in drd
      1 /* -*- mode: C; c-basic-offset: 3; -*- */
      2 /*
      3   This file is part of drd, a thread error detector.
      4 
      5   Copyright (C) 2006-2010 Bart Van Assche <bvanassche (at) acm.org>.
      6 
      7   This program is free software; you can redistribute it and/or
      8   modify it under the terms of the GNU General Public License as
      9   published by the Free Software Foundation; either version 2 of the
     10   License, or (at your option) any later version.
     11 
     12   This program is distributed in the hope that it will be useful, but
     13   WITHOUT ANY WARRANTY; without even the implied warranty of
     14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15   General Public License for more details.
     16 
     17   You should have received a copy of the GNU General Public License
     18   along with this program; if not, write to the Free Software
     19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     20   02111-1307, USA.
     21 
     22   The GNU General Public License is contained in the file COPYING.
     23 */
     24 
     25 
     26 #include "drd_barrier.h"
     27 #include "drd_clientreq.h"
     28 #include "drd_cond.h"
     29 #include "drd_error.h"
     30 #include "drd_hb.h"
     31 #include "drd_load_store.h"
     32 #include "drd_malloc_wrappers.h"
     33 #include "drd_mutex.h"
     34 #include "drd_rwlock.h"
     35 #include "drd_semaphore.h"
     36 #include "drd_suppression.h"      // drd_start_suppression()
     37 #include "drd_thread.h"
     38 #include "pub_tool_basics.h"      // Bool
     39 #include "pub_tool_debuginfo.h"   // VG_(describe_IP)()
     40 #include "pub_tool_libcassert.h"
     41 #include "pub_tool_libcassert.h"  // tl_assert()
     42 #include "pub_tool_libcprint.h"   // VG_(message)()
     43 #include "pub_tool_machine.h"     // VG_(get_SP)()
     44 #include "pub_tool_threadstate.h"
     45 #include "pub_tool_tooliface.h"   // VG_(needs_...)()
     46 
     47 
     48 /* Local function declarations. */
     49 
     50 static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret);
     51 
     52 
     53 /* Function definitions. */
     54 
     55 /**
     56  * Tell the Valgrind core the address of the DRD function that processes
     57  * client requests. Must be called before any client code is run.
     58  */
     59 void DRD_(clientreq_init)(void)
     60 {
     61    VG_(needs_client_requests)(handle_client_request);
     62 }
     63 
     64 /**
     65  * DRD's handler for Valgrind client requests. The code below handles both
     66  * DRD's public and tool-internal client requests.
     67  */
     68 static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret)
     69 {
     70    UWord result = 0;
     71    const DrdThreadId drd_tid = DRD_(thread_get_running_tid)();
     72 
     73    tl_assert(vg_tid == VG_(get_running_tid()));
     74    tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_tid) == drd_tid);
     75 
     76    switch (arg[0])
     77    {
     78    case VG_USERREQ__MALLOCLIKE_BLOCK:
     79       if (arg[1])
     80          DRD_(malloclike_block)(vg_tid, arg[1]/*addr*/, arg[2]/*size*/);
     81       break;
     82 
     83    case VG_USERREQ__FREELIKE_BLOCK:
     84       if (arg[1] && ! DRD_(freelike_block)(vg_tid, arg[1]/*addr*/))
     85       {
     86          GenericErrInfo GEI = {
     87 	    .tid = DRD_(thread_get_running_tid)(),
     88 	    .addr = 0,
     89 	 };
     90          VG_(maybe_record_error)(vg_tid,
     91                                  GenericErr,
     92                                  VG_(get_IP)(vg_tid),
     93                                  "Invalid VG_USERREQ__FREELIKE_BLOCK request",
     94                                  &GEI);
     95       }
     96       break;
     97 
     98    case VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID:
     99       result = vg_tid;
    100       break;
    101 
    102    case VG_USERREQ__DRD_GET_DRD_THREAD_ID:
    103       result = drd_tid;
    104       break;
    105 
    106    case VG_USERREQ__DRD_SET_THREAD_NAME:
    107       DRD_(thread_set_name)(drd_tid, (const char*)arg[1]);
    108       break;
    109 
    110    case VG_USERREQ__DRD_START_SUPPRESSION:
    111       /*_VG_USERREQ__HG_ARANGE_MAKE_UNTRACKED*/
    112    case VG_USERREQ_TOOL_BASE('H','G') + 256 + 39:
    113       DRD_(start_suppression)(arg[1], arg[1] + arg[2], "client");
    114       break;
    115 
    116    case VG_USERREQ__DRD_FINISH_SUPPRESSION:
    117       /*_VG_USERREQ__HG_ARANGE_MAKE_TRACKED*/
    118    case VG_USERREQ_TOOL_BASE('H','G') + 256 + 40:
    119       DRD_(finish_suppression)(arg[1], arg[1] + arg[2]);
    120       break;
    121 
    122    case VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE:
    123       DRD_(hb_happens_before)(drd_tid, arg[1]);
    124       break;
    125 
    126    case VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER:
    127       DRD_(hb_happens_after)(drd_tid, arg[1]);
    128       break;
    129 
    130    case VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE:
    131       if (arg[1])
    132       {
    133          struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
    134          if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
    135             break;
    136       }
    137       DRD_(rwlock_pre_init)(arg[1], user_rwlock);
    138       break;
    139 
    140    case VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY:
    141       if (arg[1])
    142       {
    143          struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
    144          if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
    145             break;
    146       }
    147       DRD_(rwlock_post_destroy)(arg[1], user_rwlock);
    148       break;
    149 
    150    case VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED:
    151       if (arg[1])
    152       {
    153          struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
    154          if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
    155             break;
    156       }
    157       tl_assert(arg[2] == !! arg[2]);
    158       if (arg[2])
    159       {
    160          DRD_(rwlock_pre_wrlock)(arg[1], user_rwlock);
    161          DRD_(rwlock_post_wrlock)(arg[1], user_rwlock, True);
    162       }
    163       else
    164       {
    165          DRD_(rwlock_pre_rdlock)(arg[1], user_rwlock);
    166          DRD_(rwlock_post_rdlock)(arg[1], user_rwlock, True);
    167       }
    168       break;
    169 
    170    case VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED:
    171       if (arg[1])
    172       {
    173          struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
    174          if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
    175             break;
    176       }
    177       tl_assert(arg[2] == !! arg[2]);
    178       DRD_(rwlock_pre_unlock)(arg[1], user_rwlock);
    179       break;
    180 
    181    case VG_USERREQ__SET_PTHREAD_COND_INITIALIZER:
    182       DRD_(pthread_cond_initializer) = (Addr)arg[1];
    183       DRD_(pthread_cond_initializer_size) = arg[2];
    184       break;
    185 
    186    case VG_USERREQ__DRD_START_NEW_SEGMENT:
    187       DRD_(thread_new_segment)(DRD_(PtThreadIdToDrdThreadId)(arg[1]));
    188       break;
    189 
    190    case VG_USERREQ__DRD_START_TRACE_ADDR:
    191       DRD_(start_tracing_address_range)(arg[1], arg[1] + arg[2]);
    192       break;
    193 
    194    case VG_USERREQ__DRD_STOP_TRACE_ADDR:
    195       DRD_(stop_tracing_address_range)(arg[1], arg[1] + arg[2]);
    196       break;
    197 
    198    case VG_USERREQ__DRD_RECORD_LOADS:
    199       DRD_(thread_set_record_loads)(drd_tid, arg[1]);
    200       break;
    201 
    202    case VG_USERREQ__DRD_RECORD_STORES:
    203       DRD_(thread_set_record_stores)(drd_tid, arg[1]);
    204       break;
    205 
    206    case VG_USERREQ__SET_PTHREADID:
    207       // pthread_self() returns 0 for programs not linked with libpthread.so.
    208       if (arg[1] != INVALID_POSIX_THREADID)
    209          DRD_(thread_set_pthreadid)(drd_tid, arg[1]);
    210       break;
    211 
    212    case VG_USERREQ__SET_JOINABLE:
    213       DRD_(thread_set_joinable)(DRD_(PtThreadIdToDrdThreadId)(arg[1]),
    214                                 (Bool)arg[2]);
    215       break;
    216 
    217    case VG_USERREQ__ENTERING_PTHREAD_CREATE:
    218       DRD_(thread_entering_pthread_create)(drd_tid);
    219       break;
    220 
    221    case VG_USERREQ__LEFT_PTHREAD_CREATE:
    222       DRD_(thread_left_pthread_create)(drd_tid);
    223       break;
    224 
    225    case VG_USERREQ__POST_THREAD_JOIN:
    226    {
    227       const DrdThreadId thread_to_join = DRD_(PtThreadIdToDrdThreadId)(arg[1]);
    228       if (thread_to_join == DRD_INVALID_THREADID)
    229       {
    230          InvalidThreadIdInfo ITI = { DRD_(thread_get_running_tid)(), arg[1] };
    231          VG_(maybe_record_error)(vg_tid,
    232                                  InvalidThreadId,
    233                                  VG_(get_IP)(vg_tid),
    234                                  "pthread_join(): invalid thread ID",
    235                                  &ITI);
    236       }
    237       else
    238       {
    239          DRD_(thread_post_join)(drd_tid, thread_to_join);
    240       }
    241       break;
    242    }
    243 
    244    case VG_USERREQ__PRE_THREAD_CANCEL:
    245    {
    246       const DrdThreadId thread_to_cancel =DRD_(PtThreadIdToDrdThreadId)(arg[1]);
    247       if (thread_to_cancel == DRD_INVALID_THREADID)
    248       {
    249          InvalidThreadIdInfo ITI = { DRD_(thread_get_running_tid)(), arg[1] };
    250          VG_(maybe_record_error)(vg_tid,
    251                                  InvalidThreadId,
    252                                  VG_(get_IP)(vg_tid),
    253                                  "pthread_cancel(): invalid thread ID",
    254                                  &ITI);
    255       }
    256       else
    257       {
    258          DRD_(thread_pre_cancel)(thread_to_cancel);
    259       }
    260       break;
    261    }
    262 
    263    case VG_USERREQ__POST_THREAD_CANCEL:
    264       break;
    265 
    266    case VG_USERREQ__PRE_MUTEX_INIT:
    267       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    268          DRD_(mutex_init)(arg[1], arg[2]);
    269       break;
    270 
    271    case VG_USERREQ__POST_MUTEX_INIT:
    272       DRD_(thread_leave_synchr)(drd_tid);
    273       break;
    274 
    275    case VG_USERREQ__PRE_MUTEX_DESTROY:
    276       DRD_(thread_enter_synchr)(drd_tid);
    277       break;
    278 
    279    case VG_USERREQ__POST_MUTEX_DESTROY:
    280       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    281          DRD_(mutex_post_destroy)(arg[1]);
    282       break;
    283 
    284    case VG_USERREQ__PRE_MUTEX_LOCK:
    285       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    286          DRD_(mutex_pre_lock)(arg[1], arg[2], arg[3]);
    287       break;
    288 
    289    case VG_USERREQ__POST_MUTEX_LOCK:
    290       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    291          DRD_(mutex_post_lock)(arg[1], arg[2], False/*post_cond_wait*/);
    292       break;
    293 
    294    case VG_USERREQ__PRE_MUTEX_UNLOCK:
    295       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    296          DRD_(mutex_unlock)(arg[1], arg[2]);
    297       break;
    298 
    299    case VG_USERREQ__POST_MUTEX_UNLOCK:
    300       DRD_(thread_leave_synchr)(drd_tid);
    301       break;
    302 
    303    case VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK:
    304       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    305          DRD_(spinlock_init_or_unlock)(arg[1]);
    306       break;
    307 
    308    case VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK:
    309       DRD_(thread_leave_synchr)(drd_tid);
    310       break;
    311 
    312    case VG_USERREQ__PRE_COND_INIT:
    313       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    314          DRD_(cond_pre_init)(arg[1]);
    315       break;
    316 
    317    case VG_USERREQ__POST_COND_INIT:
    318       DRD_(thread_leave_synchr)(drd_tid);
    319       break;
    320 
    321    case VG_USERREQ__PRE_COND_DESTROY:
    322       DRD_(thread_enter_synchr)(drd_tid);
    323       break;
    324 
    325    case VG_USERREQ__POST_COND_DESTROY:
    326       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    327          DRD_(cond_post_destroy)(arg[1]);
    328       break;
    329 
    330    case VG_USERREQ__PRE_COND_WAIT:
    331       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    332       {
    333          const Addr cond = arg[1];
    334          const Addr mutex = arg[2];
    335          const MutexT mutex_type = arg[3];
    336          DRD_(mutex_unlock)(mutex, mutex_type);
    337          DRD_(cond_pre_wait)(cond, mutex);
    338       }
    339       break;
    340 
    341    case VG_USERREQ__POST_COND_WAIT:
    342       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    343       {
    344          const Addr cond = arg[1];
    345          const Addr mutex = arg[2];
    346          const Bool took_lock = arg[3];
    347          DRD_(cond_post_wait)(cond);
    348          DRD_(mutex_post_lock)(mutex, took_lock, True);
    349       }
    350       break;
    351 
    352    case VG_USERREQ__PRE_COND_SIGNAL:
    353       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    354          DRD_(cond_pre_signal)(arg[1]);
    355       break;
    356 
    357    case VG_USERREQ__POST_COND_SIGNAL:
    358       DRD_(thread_leave_synchr)(drd_tid);
    359       break;
    360 
    361    case VG_USERREQ__PRE_COND_BROADCAST:
    362       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    363          DRD_(cond_pre_broadcast)(arg[1]);
    364       break;
    365 
    366    case VG_USERREQ__POST_COND_BROADCAST:
    367       DRD_(thread_leave_synchr)(drd_tid);
    368       break;
    369 
    370    case VG_USERREQ__PRE_SEM_INIT:
    371       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    372          DRD_(semaphore_init)(arg[1], arg[2], arg[3]);
    373       break;
    374 
    375    case VG_USERREQ__POST_SEM_INIT:
    376       DRD_(thread_leave_synchr)(drd_tid);
    377       break;
    378 
    379    case VG_USERREQ__PRE_SEM_DESTROY:
    380       DRD_(thread_enter_synchr)(drd_tid);
    381       break;
    382 
    383    case VG_USERREQ__POST_SEM_DESTROY:
    384       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    385          DRD_(semaphore_destroy)(arg[1]);
    386       break;
    387 
    388    case VG_USERREQ__PRE_SEM_OPEN:
    389       DRD_(thread_enter_synchr)(drd_tid);
    390       break;
    391 
    392    case VG_USERREQ__POST_SEM_OPEN:
    393       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    394          DRD_(semaphore_open)(arg[1], (Char*)arg[2], arg[3], arg[4], arg[5]);
    395       break;
    396 
    397    case VG_USERREQ__PRE_SEM_CLOSE:
    398       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    399          DRD_(semaphore_close)(arg[1]);
    400       break;
    401 
    402    case VG_USERREQ__POST_SEM_CLOSE:
    403       DRD_(thread_leave_synchr)(drd_tid);
    404       break;
    405 
    406    case VG_USERREQ__PRE_SEM_WAIT:
    407       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    408          DRD_(semaphore_pre_wait)(arg[1]);
    409       break;
    410 
    411    case VG_USERREQ__POST_SEM_WAIT:
    412       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    413          DRD_(semaphore_post_wait)(drd_tid, arg[1], arg[2]);
    414       break;
    415 
    416    case VG_USERREQ__PRE_SEM_POST:
    417       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    418          DRD_(semaphore_pre_post)(drd_tid, arg[1]);
    419       break;
    420 
    421    case VG_USERREQ__POST_SEM_POST:
    422       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    423          DRD_(semaphore_post_post)(drd_tid, arg[1], arg[2]);
    424       break;
    425 
    426    case VG_USERREQ__PRE_BARRIER_INIT:
    427       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    428          DRD_(barrier_init)(arg[1], arg[2], arg[3], arg[4]);
    429       break;
    430 
    431    case VG_USERREQ__POST_BARRIER_INIT:
    432       DRD_(thread_leave_synchr)(drd_tid);
    433       break;
    434 
    435    case VG_USERREQ__PRE_BARRIER_DESTROY:
    436       DRD_(thread_enter_synchr)(drd_tid);
    437       break;
    438 
    439    case VG_USERREQ__POST_BARRIER_DESTROY:
    440       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    441          DRD_(barrier_destroy)(arg[1], arg[2]);
    442       break;
    443 
    444    case VG_USERREQ__PRE_BARRIER_WAIT:
    445       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    446          DRD_(barrier_pre_wait)(drd_tid, arg[1], arg[2]);
    447       break;
    448 
    449    case VG_USERREQ__POST_BARRIER_WAIT:
    450       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    451          DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3], arg[4]);
    452       break;
    453 
    454    case VG_USERREQ__PRE_RWLOCK_INIT:
    455       DRD_(rwlock_pre_init)(arg[1], pthread_rwlock);
    456       break;
    457 
    458    case VG_USERREQ__POST_RWLOCK_DESTROY:
    459       DRD_(rwlock_post_destroy)(arg[1], pthread_rwlock);
    460       break;
    461 
    462    case VG_USERREQ__PRE_RWLOCK_RDLOCK:
    463       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    464          DRD_(rwlock_pre_rdlock)(arg[1], pthread_rwlock);
    465       break;
    466 
    467    case VG_USERREQ__POST_RWLOCK_RDLOCK:
    468       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    469          DRD_(rwlock_post_rdlock)(arg[1], pthread_rwlock, arg[2]);
    470       break;
    471 
    472    case VG_USERREQ__PRE_RWLOCK_WRLOCK:
    473       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    474          DRD_(rwlock_pre_wrlock)(arg[1], pthread_rwlock);
    475       break;
    476 
    477    case VG_USERREQ__POST_RWLOCK_WRLOCK:
    478       if (DRD_(thread_leave_synchr)(drd_tid) == 0)
    479          DRD_(rwlock_post_wrlock)(arg[1], pthread_rwlock, arg[2]);
    480       break;
    481 
    482    case VG_USERREQ__PRE_RWLOCK_UNLOCK:
    483       if (DRD_(thread_enter_synchr)(drd_tid) == 0)
    484          DRD_(rwlock_pre_unlock)(arg[1], pthread_rwlock);
    485       break;
    486 
    487    case VG_USERREQ__POST_RWLOCK_UNLOCK:
    488       DRD_(thread_leave_synchr)(drd_tid);
    489       break;
    490 
    491    case VG_USERREQ__DRD_CLEAN_MEMORY:
    492       if (arg[2] > 0)
    493          DRD_(clean_memory)(arg[1], arg[2]);
    494       break;
    495 
    496    case VG_USERREQ__HELGRIND_ANNOTATION_UNIMP:
    497       {
    498          /* Note: it is assumed below that the text arg[1] points to is never
    499           * freed, e.g. because it points to static data.
    500           */
    501          UnimpClReqInfo UICR =
    502             { DRD_(thread_get_running_tid)(), (Char*)arg[1] };
    503          VG_(maybe_record_error)(vg_tid,
    504                                  UnimpHgClReq,
    505                                  VG_(get_IP)(vg_tid),
    506                                  "",
    507                                  &UICR);
    508       }
    509       break;
    510 
    511    case VG_USERREQ__DRD_ANNOTATION_UNIMP:
    512       {
    513          /* Note: it is assumed below that the text arg[1] points to is never
    514           * freed, e.g. because it points to static data.
    515           */
    516          UnimpClReqInfo UICR =
    517             { DRD_(thread_get_running_tid)(), (Char*)arg[1] };
    518          VG_(maybe_record_error)(vg_tid,
    519                                  UnimpDrdClReq,
    520                                  VG_(get_IP)(vg_tid),
    521                                  "",
    522                                  &UICR);
    523       }
    524       break;
    525 
    526    default:
    527 #if 0
    528       VG_(message)(Vg_DebugMsg, "Unrecognized client request 0x%lx 0x%lx",
    529                    arg[0], arg[1]);
    530       tl_assert(0);
    531 #endif
    532       return False;
    533    }
    534 
    535    *ret = result;
    536    return True;
    537 }
    538