diff options
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/parse_valgrind_suppressions.sh | 60 | ||||
-rw-r--r-- | scripts/valgrind.supp | 245 | ||||
-rwxr-xr-x | scripts/valgrindmerge | 65 |
3 files changed, 370 insertions, 0 deletions
diff --git a/scripts/parse_valgrind_suppressions.sh b/scripts/parse_valgrind_suppressions.sh new file mode 100755 index 00000000..d9cc697a --- /dev/null +++ b/scripts/parse_valgrind_suppressions.sh @@ -0,0 +1,60 @@ +#! /usr/bin/awk -f +# A script to extract the actual suppression info from the output of (for example) valgrind --leak-check=full --show-reachable=yes --error-limit=no --gen-suppressions=all ./minimal +# The desired bits are between ^{ and ^} (including the braces themselves). +# The combined output should either be appended to /usr/lib/valgrind/default.supp, or placed in a .supp of its own +# If the latter, either tell valgrind about it each time with --suppressions=<filename>, or add that line to ~/.valgrindrc + +# NB This script uses the |& operator, which I believe is gawk-specific. In case of failure, check that you're using gawk rather than some other awk + +# The script looks for suppressions. When it finds one it stores it temporarily in an array, +# and also feeds it line by line to the external app 'md5sum' which generates a unique checksum for it. +# The checksum is used as an index in a different array. If an item with that index already exists the suppression must be a duplicate and is discarded. + +# Source: <https://wiki.wxwidgets.org/Parse_valgrind_suppressions.sh> +# See: <https://wiki.wxwidgets.org/Valgrind_Suppression_File_Howto> + +BEGIN { suppression=0; md5sum = "md5sum" } + # If the line begins with '{', it's the start of a supression; so set the var and initialise things + /^{/ { + suppression=1; i=0; next + } + # If the line begins with '}' its the end of a suppression + /^}/ { + if (suppression) + { suppression=0; + close(md5sum, "to") # We've finished sending data to md5sum, so close that part of the pipe + ProcessInput() # Do the slightly-complicated stuff in functions + delete supparray # We don't want subsequent suppressions to append to it! + } + } + # Otherwise, it's a normal line. If we're inside a supression, store it, and pipe it to md5sum. Otherwise it's cruft, so ignore it + { if (suppression) + { + supparray[++i] = $0 + print |& md5sum + } + } + + + function ProcessInput() + { + # Pipe the result from md5sum, then close it + md5sum |& getline result + close(md5sum) + # gawk can't cope with enormous ints like $result would be, so stringify it first by prefixing a definite string + resultstring = "prefix"result + + if (! (resultstring in chksum_array) ) + { chksum_array[resultstring] = 0; # This checksum hasn't been seen before, so add it to the array + OutputSuppression() # and output the contents of the suppression + } + } + + function OutputSuppression() + { + # A suppression is surrounded by '{' and '}'. Its data was stored line by line in the array + print "{" + for (n=1; n <= i; ++n) + { print supparray[n] } + print "}" + } diff --git a/scripts/valgrind.supp b/scripts/valgrind.supp new file mode 100644 index 00000000..1973e69d --- /dev/null +++ b/scripts/valgrind.supp @@ -0,0 +1,245 @@ +# +# All file and line numbers from debug build using commit 60e6f5f67c5bc2a8fb26e8f2ef76c169c5b78813 +# +# See <https://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.suppfiles> +# See <https://wiki.wxwidgets.org/Valgrind_Suppression_File_Howto> +# + +# direct_bt::LFRingbuffer::* utilizes SC-DRF atomic acquire (read) and release (write) +# not detected by helgrind. See uni test test_mm_sc_drf (passed). +# +# ==1175024== ---Thread-Announcement------------------------------------------ +# ==1175024== Thread #2 was created +# ==1175024== by 0x49434C1: direct_bt::DBTManager::DBTManager(direct_bt::BTMode) (DBTManager.cpp:333) +# ==1175024== Thread #2: Bug in libpthread: write lock granted on mutex/rwlock which is currently wr-held by a different thread +# ==1175024== by 0x13283A: _ZN9direct_bt12LFRingbufferISt10shared_ptrINS_9MgmtEventEELDnEE7putImplERKS3_bbi (LFRingbuffer.hpp:240) +# (see below: cpp_unique_lock_cond_wait_002) +{ + dbt_lfringbuffer_lock_and_wait_001 + Helgrind:Misc + fun:mutex_lock_WRK + ... + fun:*direct_bt*LFRingbuffer*putImpl* + ... + obj:*libdirect_bt.so* +} + +# direct_bt::LFRingbuffer::* utilizes SC-DRF atomic acquire (read) and release (write) +# not detected by helgrind. See uni test test_mm_sc_drf (passed). +# +# ==1175024== Thread #1 is the program's root thread +# ==1175024== Thread #2 unlocked lock at 0x13F628 currently held by thread #1 +# ==1175024== by 0x132913: _ZN9direct_bt12LFRingbufferISt10shared_ptrINS_9MgmtEventEELDnEE7putImplERKS3_bbi (LFRingbuffer.hpp:240) +# { +# 240 std::unique_lock<std::mutex> lockRead(syncRead); // SC-DRF w/ getImpl via same lock +# size++; +# writePos = localWritePos; // SC-DRF release atomic writePos +# cvRead.notify_all(); // notify waiting getter +# } + +# ==1175024== Lock at 0x13F628 was first observed +# ==1175024== by 0x131EDC: _ZN9direct_bt12LFRingbufferISt10shared_ptrINS_9MgmtEventEELDnEE7getImplEbbi (LFRingbuffer.hpp:181) +# if( blocking ) { +# 181 std::unique_lock<std::mutex> lockRead(syncRead); // SC-DRF w/ putImpl via same lock +# while( localReadPos == writePos ) { +# .. +# cvRead.wait(lockRead); or cvRead.wait_until(lockRead, ..); +# } +# } +{ + dbt_lfringbuffer_lock_and_wait_002 + Helgrind:UnlockForeign + fun:mutex_unlock_WRK + ... + fun:*direct_bt*LFRingbuffer*putImpl* + ... + obj:*libdirect_bt.so* +} + +# +# direct_bt::LFRingbuffer::* utilizes SC-DRF atomic acquire (read) and release (write) +# not detected by helgrind. See uni test test_mm_sc_drf (passed). +# +# ==1175024== Possible data race during read of size 8 at 0x4F490E8 by thread #1 +# ==1175024== Locks held: 3, at addresses 0x13F480 0x13F650 0x13F7B0 +# ==1175024== at 0x131D90: std::__shared_ptr<direct_bt::MgmtEvent, (__gnu_cxx::_Lock_policy)2>::__shared_ptr(std::__shared_ptr<direct_bt::MgmtEvent, (__gnu_cxx::_Lock_policy)2> const&) (shared_ptr_base.h:1181) +# ==1175024== by 0x131DDA: std::shared_ptr<direct_bt::MgmtEvent>::shared_ptr(std::shared_ptr<direct_bt::MgmtEvent> const&) (shared_ptr.h:149) +# ==1175024== by 0x1320B0: _ZN9direct_bt12LFRingbufferISt10shared_ptrINS_9MgmtEventEELDnEE7getImplEbbi (LFRingbuffer.hpp:198) +# +# ==1175024== This conflicts with a previous write of size 8 by thread #2 +# ==1175024== Locks held: 1, at address 0x13F6A0 +# ==1175024== at 0x130E6D: std::__shared_ptr<direct_bt::MgmtEvent, (__gnu_cxx::_Lock_policy)2>::operator=(std::__shared_ptr<direct_bt::MgmtEvent, (__gnu_cxx::_Lock_policy)2> const&) (shared_ptr_base.h:1182) +# ==1175024== by 0x130EB4: std::shared_ptr<direct_bt::MgmtEvent>::operator=(std::shared_ptr<direct_bt::MgmtEvent> const&) (shared_ptr.h:358) +# ==1175024== by 0x13281D: _ZN9direct_bt12LFRingbufferISt10shared_ptrINS_9MgmtEventEELDnEE7putImplERKS3_bbi (LFRingbuffer.hpp:237) +{ + dbt_lfringbuffer_sc_drf_atomic_001 + Helgrind:Race + ... + fun:*direct_bt*LFRingbuffer*getImpl* + ... + obj:*libdirect_bt.so* +} + +# +# DBTManager +# +# ==1175024== Possible data race during read of size 8 at 0x4F49690 by thread #1 +# ==1175024== Locks held: 2, at addresses 0x13F480 0x13F7B0 +# ==1175024== at 0x494261F: direct_bt::DBTManager::sendWithReply(direct_bt::MgmtCommand&) (DBTManager.cpp:205) +# ==1175024== by 0x494359D: direct_bt::DBTManager::DBTManager(direct_bt::BTMode) (DBTManager.cpp:350) +# +# ==1175024== Address 0x4f49690 is 0 bytes inside a block of size 48 alloc'd +# ==1175024== at 0x4839E3F: operator new(unsigned long) (vg_replace_malloc.c:342) +# ==1175024== by 0x493C244: direct_bt::MgmtEvent::getSpecialized(unsigned char const*, int) (MgmtTypes.cpp:243) +{ + dbt_lfringbuffer_sc_drf_atomic_011 + Helgrind:Race + ... + fun:*direct_bt*DBTManager*sendWithReply* + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_012 + Helgrind:Race + ... + fun:_ZN9direct_bt10DBTManagerC1ENS_6BTModeE + ... +# obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_013 + Helgrind:Race + ... + fun:_ZN9direct_bt9MgmtEventD1Ev + ... + obj:*libdirect_bt.so* +} + +# +# GATTHandler +# +{ + dbt_lfringbuffer_sc_drf_atomic_021 + Helgrind:Race + ... + fun:*direct_bt*GATTHandler*sendWithReply* + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_022 + Helgrind:Race + ... + fun:_ZN9direct_bt11GATTHandlerC1ERKSt10shared_ptrINS_9DBTDeviceEE + ... +# obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_023 + Helgrind:Race + ... +# fun:*direct_bt*GATTHandler*discoverPrimaryServices* +# fun:*direct_bt*GATTHandler*discoverCharacteristics* + fun:*direct_bt*GATTHandler*discoverCompletePrimaryServices* + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_024 + Helgrind:Race + ... + fun:_ZN9direct_bt9AttPDUMsgD1Ev + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_025 + Helgrind:Race + ... + fun:*direct_bt*GATTHandler*readValue* + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_026 + Helgrind:Race + ... + fun:*direct_bt*GATTHandler*writeValue* + ... + obj:*libdirect_bt.so* +} + + +# +# HCIHandler +# +{ + dbt_lfringbuffer_sc_drf_atomic_031 + Helgrind:Race + ... + fun:*direct_bt*HCIHandler*getNextReply* + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_032 + Helgrind:Race + ... + fun:*direct_bt*HCIHandler*sendWithCmdCompleteReply* + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_033 + Helgrind:Race + ... + fun:_ZN9direct_bt10HCIHandlerC1ENS_6BTModeEt + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_034 + Helgrind:Race + ... + fun:_ZN9direct_bt9HCIPacketD1Ev + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_035 + Helgrind:Race + ... + fun:_ZNSt10shared_ptrIN9direct_bt8HCIEventEED1Ev + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_036 + Helgrind:Race + ... + fun:*direct_bt*HCIHandler*processCommandComplete* + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_037 + Helgrind:Race + ... + fun:*direct_bt*HCIHandler*processCommandStatus* + ... + obj:*libdirect_bt.so* +} +{ + dbt_lfringbuffer_sc_drf_atomic_038 + Helgrind:Race + ... + fun:*direct_bt*HCIEvent*le_set_scan_param* + ... + obj:*libdirect_bt.so* +} + +# +# +# + diff --git a/scripts/valgrindmerge b/scripts/valgrindmerge new file mode 100755 index 00000000..f9b11e28 --- /dev/null +++ b/scripts/valgrindmerge @@ -0,0 +1,65 @@ +#!/usr/bin/perl + +# Copyright 2016 Timothe Litt litt at acm _ddot_ org +# +# May be freely used and copied providing this notice is retained +# No warranty, use at your own risk +# + +# valgrind foo 3>&1 1>&2 2>&3 | grindmerge -f input >newrules + +# Source: <https://wiki.wxwidgets.org/Parse_valgrind_suppressions.sh> +# See: <https://wiki.wxwidgets.org/Valgrind_Suppression_File_Howto> + +use warnings; +use strict; + +use Digest::MD5 qw/md5_hex/; + +my %known; +my $dups = 0; + +sub parse { + my $in = shift; + + while( <$in> ) { + next unless( /^\{/ ); + + my $block = $_; + while( <$in> ) { + if( /^\}/ ) { + $block .= "}\n"; + last; + } + $block .= $_; + } + last unless( defined $block ); + if( $block !~ /\}\n/ ) { + print STDERR ("Unterminated suppression at line $.\n" ); + last; + } + my $key = $block; + $key =~ s/(\A{[^\n]*\n)\s*[^\n]*\n/$1/; + my $sum = md5_hex( $key ); + $dups++ if( exists $known{$sum} ); + $known{$sum} = $block; + } +} + +if( @ARGV >= 2 && $ARGV[0] eq '-f' ) { + if( open( my $db, '<', $ARGV[1] ) ) { + parse( $db ); + close( $db ); + } else { + print STDERR ("Open failed for $ARGV[1]: $!\n"); + exit 1; + } + print STDERR ("Read " . keys( %known ) . " suppressions from $ARGV[1]\n" ); +} + +parse( \*STDIN ); + +print $known{$_} foreach ( sort keys %known ); + +print STDERR ("Squashed $dups duplicate suppressions\n") + |