Home | History | Annotate | Download | only in drd
      1 /*
      2   This file is part of drd, a thread error detector.
      3 
      4   Copyright (C) 2006-2013 Bart Van Assche <bvanassche (at) acm.org>.
      5 
      6   This program is free software; you can redistribute it and/or
      7   modify it under the terms of the GNU General Public License as
      8   published by the Free Software Foundation; either version 2 of the
      9   License, or (at your option) any later version.
     10 
     11   This program is distributed in the hope that it will be useful, but
     12   WITHOUT ANY WARRANTY; without even the implied warranty of
     13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14   General Public License for more details.
     15 
     16   You should have received a copy of the GNU General Public License
     17   along with this program; if not, write to the Free Software
     18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     19   02111-1307, USA.
     20 
     21   The GNU General Public License is contained in the file COPYING.
     22 */
     23 
     24 
     25 #include "drd_suppression.h"
     26 #include "pub_drd_bitmap.h"
     27 #include "pub_tool_libcassert.h"  // tl_assert()
     28 #include "pub_tool_stacktrace.h"  // VG_(get_and_pp_StackTrace)()
     29 #include "pub_tool_threadstate.h" // VG_(get_running_tid)()
     30 #include "pub_tool_libcprint.h"   // Vg_DebugMsg
     31 
     32 
     33 /* Global variables. */
     34 
     35 Bool DRD_(g_any_address_traced) = False;
     36 
     37 
     38 /* Local variables. */
     39 
     40 static struct bitmap* s_suppressed;
     41 static struct bitmap* s_traced;
     42 static Bool s_trace_suppression;
     43 
     44 
     45 /* Function definitions. */
     46 
     47 void DRD_(suppression_set_trace)(const Bool trace_suppression)
     48 {
     49    s_trace_suppression = trace_suppression;
     50 }
     51 
     52 void DRD_(suppression_init)(void)
     53 {
     54    tl_assert(s_suppressed == 0);
     55    tl_assert(s_traced     == 0);
     56    s_suppressed = DRD_(bm_new)();
     57    s_traced     = DRD_(bm_new)();
     58    tl_assert(s_suppressed);
     59    tl_assert(s_traced);
     60 }
     61 
     62 void DRD_(start_suppression)(const Addr a1, const Addr a2,
     63                              const HChar* const reason)
     64 {
     65    if (s_trace_suppression)
     66       VG_(message)(Vg_DebugMsg, "start suppression of 0x%lx sz %ld (%s)\n",
     67                    a1, a2 - a1, reason);
     68 
     69    tl_assert(a1 <= a2);
     70    DRD_(bm_access_range_store)(s_suppressed, a1, a2);
     71 }
     72 
     73 void DRD_(finish_suppression)(const Addr a1, const Addr a2)
     74 {
     75    if (s_trace_suppression) {
     76       VG_(message)(Vg_DebugMsg, "finish suppression of 0x%lx sz %ld\n",
     77                    a1, a2 - a1);
     78       VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12);
     79    }
     80 
     81    tl_assert(a1 <= a2);
     82    DRD_(bm_clear_store)(s_suppressed, a1, a2);
     83 }
     84 
     85 /**
     86  * Return true if data race detection suppression has been requested for all
     87  * bytes in the range a1 .. a2 - 1 inclusive. Return false in case the range
     88  * is only partially suppressed or not suppressed at all.
     89  */
     90 Bool DRD_(is_suppressed)(const Addr a1, const Addr a2)
     91 {
     92    return DRD_(bm_has)(s_suppressed, a1, a2, eStore);
     93 }
     94 
     95 /**
     96  * Return true if data race detection suppression has been requested for any
     97  * of the bytes in the range a1 .. a2 - 1 inclusive. Return false in case none
     98  * of the bytes in the specified range is suppressed.
     99  */
    100 Bool DRD_(is_any_suppressed)(const Addr a1, const Addr a2)
    101 {
    102    return DRD_(bm_has_any_store)(s_suppressed, a1, a2);
    103 }
    104 
    105 void DRD_(mark_hbvar)(const Addr a1)
    106 {
    107    DRD_(bm_access_range_load)(s_suppressed, a1, a1 + 1);
    108 }
    109 
    110 Bool DRD_(range_contains_suppression_or_hbvar)(const Addr a1, const Addr a2)
    111 {
    112    return DRD_(bm_has_any_access)(s_suppressed, a1, a2);
    113 }
    114 
    115 /**
    116  * Start tracing memory accesses in the range [a1,a2). If persistent == True,
    117  * keep tracing even after memory deallocation and reallocation.
    118  */
    119 void DRD_(start_tracing_address_range)(const Addr a1, const Addr a2,
    120                                        const Bool persistent)
    121 {
    122    tl_assert(a1 <= a2);
    123 
    124    if (s_trace_suppression)
    125       VG_(message)(Vg_DebugMsg, "start_tracing(0x%lx, %ld) %s\n",
    126                    a1, a2 - a1, persistent ? "persistent" : "non-persistent");
    127 
    128    DRD_(bm_access_range_load)(s_traced, a1, a2);
    129    if (persistent)
    130       DRD_(bm_access_range_store)(s_traced, a1, a2);
    131    if (!DRD_(g_any_address_traced) && a1 < a2)
    132       DRD_(g_any_address_traced) = True;
    133 }
    134 
    135 /**
    136  * Stop tracing memory accesses in the range [a1,a2).
    137  */
    138 void DRD_(stop_tracing_address_range)(const Addr a1, const Addr a2)
    139 {
    140    tl_assert(a1 <= a2);
    141 
    142    if (s_trace_suppression)
    143       VG_(message)(Vg_DebugMsg, "stop_tracing(0x%lx, %ld)\n",
    144                    a1, a2 - a1);
    145 
    146    if (DRD_(g_any_address_traced)) {
    147       DRD_(bm_clear)(s_traced, a1, a2);
    148       DRD_(g_any_address_traced) = DRD_(bm_has_any_load_g)(s_traced);
    149    }
    150 }
    151 
    152 Bool DRD_(is_any_traced)(const Addr a1, const Addr a2)
    153 {
    154    return DRD_(bm_has_any_access)(s_traced, a1, a2);
    155 }
    156 
    157 /**
    158  * Stop using the memory range [a1,a2). Stop tracing memory accesses to
    159  * non-persistent address ranges.
    160  */
    161 void DRD_(suppression_stop_using_mem)(const Addr a1, const Addr a2)
    162 {
    163    if (s_trace_suppression) {
    164       Addr b;
    165       for (b = a1; b < a2; b++) {
    166          if (DRD_(bm_has_1)(s_suppressed, b, eStore)) {
    167             VG_(message)(Vg_DebugMsg,
    168                          "stop_using_mem(0x%lx, %ld) finish suppression of"
    169                          " 0x%lx\n", a1, a2 - a1, b);
    170          }
    171       }
    172    }
    173    tl_assert(a1);
    174    tl_assert(a1 <= a2);
    175    DRD_(bm_clear)(s_suppressed, a1, a2);
    176    DRD_(bm_clear_load)(s_traced, a1, a2);
    177 }
    178