New memcheck command line option: --expensive-definedness-check

Pertains to BZ #340392


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15594
This commit is contained in:
Florian Krohm 2015-08-27 17:50:47 +00:00
parent 6a85ef75ec
commit 2c79dd79f5
8 changed files with 87 additions and 18 deletions

View File

@ -970,6 +970,24 @@ is <option>--errors-for-leak-kinds=definite,possible</option>
</listitem>
</varlistentry>
<varlistentry id="opt.expensive-definedness-check" xreflabel="--expensive-definedness-check">
<term>
<option><![CDATA[--expensive-definedness-check=<yes|no> [default: no] ]]></option>
</term>
<listitem>
<para>Controls whether Memcheck should employ more precise but also more
expensive (time consuming) algorithms when checking the definedness of a
value. The default setting is not to do that and it is usually
sufficient. However, for highly optimised code valgrind may sometimes
incorrectly complain.
Invoking valgrind with <option>--expensive-definedness-check==yes</option>
helps but comes at a performance cost. Runtime degradation of
25% have been observed but the extra cost depends a lot on the
application at hand.
</para>
</listitem>
</varlistentry>
<varlistentry id="opt.keep-stacktraces" xreflabel="--keep-stacktraces">
<term>
<option><![CDATA[--keep-stacktraces=alloc|free|alloc-and-free|alloc-then-free|none [default: alloc-then-free] ]]></option>

View File

@ -695,6 +695,9 @@ extern Int MC_(clo_mc_level);
/* Should we show mismatched frees? Default: YES */
extern Bool MC_(clo_show_mismatched_frees);
/* Should we use expensive definedness checking for add/sub and compare
operations? Default: NO */
extern Bool MC_(clo_expensive_definedness_check);
/*------------------------------------------------------------*/
/*--- Instrumentation ---*/

View File

@ -5711,6 +5711,7 @@ Int MC_(clo_free_fill) = -1;
KeepStacktraces MC_(clo_keep_stacktraces) = KS_alloc_then_free;
Int MC_(clo_mc_level) = 2;
Bool MC_(clo_show_mismatched_frees) = True;
Bool MC_(clo_expensive_definedness_check) = False;
static const HChar * MC_(parse_leak_heuristics_tokens) =
"-,stdstring,length64,newarray,multipleinheritance";
@ -5857,6 +5858,8 @@ static Bool mc_process_cmd_line_options(const HChar* arg)
else if VG_BOOL_CLO(arg, "--show-mismatched-frees",
MC_(clo_show_mismatched_frees)) {}
else if VG_BOOL_CLO(arg, "--expensive-definedness-check",
MC_(clo_expensive_definedness_check)) {}
else
return VG_(replacement_malloc_process_cmd_line_option)(arg);

View File

@ -6313,29 +6313,35 @@ IRSB* MC_(instrument) ( VgCallbackClosure* closure,
}
tl_assert( VG_(sizeXA)( mce.tmpMap ) == sb_in->tyenv->types_used );
/* Make a preliminary inspection of the statements, to see if there
are any dodgy-looking literals. If there are, we generate
extra-detailed (hence extra-expensive) instrumentation in
places. Scan the whole bb even if dodgyness is found earlier,
so that the flatness assertion is applied to all stmts. */
Bool bogus = False;
if (MC_(clo_expensive_definedness_check)) {
/* For expensive definedness checking skip looking for bogus
literals. */
mce.bogusLiterals = True;
} else {
/* Make a preliminary inspection of the statements, to see if there
are any dodgy-looking literals. If there are, we generate
extra-detailed (hence extra-expensive) instrumentation in
places. Scan the whole bb even if dodgyness is found earlier,
so that the flatness assertion is applied to all stmts. */
Bool bogus = False;
for (i = 0; i < sb_in->stmts_used; i++) {
st = sb_in->stmts[i];
tl_assert(st);
tl_assert(isFlatIRStmt(st));
for (i = 0; i < sb_in->stmts_used; i++) {
st = sb_in->stmts[i];
tl_assert(st);
tl_assert(isFlatIRStmt(st));
if (!bogus) {
bogus = checkForBogusLiterals(st);
if (0 && bogus) {
VG_(printf)("bogus: ");
ppIRStmt(st);
VG_(printf)("\n");
if (!bogus) {
bogus = checkForBogusLiterals(st);
if (0 && bogus) {
VG_(printf)("bogus: ");
ppIRStmt(st);
VG_(printf)("\n");
}
if (bogus) break;
}
if (bogus) break;
}
mce.bogusLiterals = bogus;
}
mce.bogusLiterals = bogus;
/* Copy verbatim any IR preamble preceding the first IMark */

View File

@ -84,6 +84,7 @@ EXTRA_DIST = \
buflen_check.stderr.exp-kfail \
bug155125.stderr.exp bug155125.vgtest \
bug287260.stderr.exp bug287260.vgtest \
bug340392.stderr.exp bug340392.vgtest \
calloc-overflow.stderr.exp calloc-overflow.vgtest\
client-msg.stderr.exp client-msg.vgtest \
client-msg-as-xml.stderr.exp client-msg-as-xml.vgtest \
@ -308,6 +309,7 @@ check_PROGRAMS = \
buflen_check \
bug155125 \
bug287260 \
bug340392 \
calloc-overflow \
client-msg \
clientperm \
@ -418,6 +420,7 @@ leak_cpp_interior_SOURCES = leak_cpp_interior.cpp
demangle_SOURCES = demangle.cpp
bug340392_CFLAGS = $(AM_CFLAGS) -O3
dw4_CFLAGS = $(AM_CFLAGS) -gdwarf-4 -fdebug-types-section
descr_belowsp_LDADD = -lpthread

View File

@ -0,0 +1,26 @@
#include <stdlib.h>
typedef struct {
unsigned char c;
int i;
void *foo;
} S;
S *make_s (void);
int
main (int argc, char **argv)
{
S *s = make_s ();
if (s->c == 0 && s->i == 1 && s->foo == getenv ("BLAH"))
abort();
return 0;
}
S *
make_s (void)
{
S *res = malloc (sizeof (S));
res->c = 1;
return res;
}

View File

View File

@ -0,0 +1,10 @@
# When run without --expensive-definedness-check valgrind
# produces:
#
# ==10953== Conditional jump or move depends on uninitialised value(s)
# ==10953== at 0x4004F8: main (bug340392.c:15)
#
# Making sure we don't get the message.
#
prog: bug340392
vgopts: -q --expensive-definedness-check=yes