Incorporate horrible hack to workaround problem of emitting bogus

uninit-value errors on code with inlined strlen() et al from gcc-3.1
and above.

MERGE TO STABLE


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1213
This commit is contained in:
Julian Seward 2002-10-13 00:57:26 +00:00
parent e5494a7f05
commit 9ea62d1526
4 changed files with 67 additions and 2 deletions

View File

@ -583,6 +583,20 @@ follows:
in g++-3.0.4.
</li><br><p>
<li><code>--avoid-strlen-errors=yes</code> [default]<br>
<code>--avoid-strlen-errors=no</code> <p>When enabled, valgrind
inspects each basic block it instruments for some tell-tale
literals (0xFEFEFEFF, 0x80808080, 0x00008080) which suggest
that this block is part of an inlined strlen() function. In
many cases such functions cause spurious uninitialised-value
errors to be reported -- their code is too clever for the
instrumentation scheme. This horrible hack works around the
problem, at the expense of hiding any genuine
uninitialised-value errors which might appear ine such blocks.
It is enabled by default because it is needed to get sensible
behaviour on code compiled by gcc-3.1 and above.
</li><br><p>
<li><code>--error-limit=yes</code> [default]<br>
<code>--error-limit=no</code> <p>When enabled, valgrind stops
reporting errors after 30000 in total, or 300 different ones,

View File

@ -145,6 +145,10 @@ extern Bool SK_(clo_check_addrVs);
/* DEBUG: clean up instrumented code? default: YES */
extern Bool SK_(clo_cleanup);
/* When instrumenting, omit some checks if tell-tale literals for
inlined strlen() are visible in the basic block. default: YES */
extern Bool SK_(clo_avoid_strlen_errors);
/*------------------------------------------------------------*/
/*--- Functions ---*/

View File

@ -57,6 +57,8 @@ Bool SK_(clo_show_reachable) = False;
Bool SK_(clo_workaround_gcc296_bugs) = False;
Bool SK_(clo_check_addrVs) = True;
Bool SK_(clo_cleanup) = True;
Bool SK_(clo_avoid_strlen_errors) = True;
/*------------------------------------------------------------*/
/*--- Profiling events ---*/
@ -2318,6 +2320,11 @@ Bool SK_(process_cmd_line_option)(Char* arg)
else if (STREQ(arg, "--cleanup=no"))
SK_(clo_cleanup) = False;
else if (STREQ(arg, "--avoid-strlen-errors=yes"))
SK_(clo_avoid_strlen_errors) = True;
else if (STREQ(arg, "--avoid-strlen-errors=no"))
SK_(clo_avoid_strlen_errors) = False;
else
return False;
@ -2340,7 +2347,8 @@ Char* SK_(usage)(void)
" --check-addrVs=no|yes experimental lighterweight checking? [yes]\n"
" yes == Valgrind's original behaviour\n"
"\n"
" --cleanup=no|yes improve after instrumentation? [yes]\n";
" --cleanup=no|yes improve after instrumentation? [yes]\n"
" --avoid-strlen-errors=no|yes suppress errs from inlined strlen [yes]\n";
}

View File

@ -498,9 +498,43 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
Int i, j;
UInstr* u_in;
Int qs, qd, qt, qtt;
Bool bogusLiterals;
cb = VG_(alloc_UCodeBlock)();
cb->nextTemp = cb_in->nextTemp;
/* Scan the block to look for bogus literals. These are magic
numbers which particularly appear in hand-optimised / inlined
implementations of strlen() et al which cause so much trouble
(spurious reports of uninit-var uses). Purpose of this horrible
hack is to disable some checks any such literals are present in
this basic block. */
bogusLiterals = False;
if (SK_(clo_avoid_strlen_errors)) {
for (i = 0; i < cb_in->used; i++) {
u_in = &cb_in->instrs[i];
switch (u_in->opcode) {
case ADD: case SUB: case MOV:
if (u_in->size == 4 && u_in->tag1 == Literal)
goto literal;
break;
case LEA1:
sk_assert(u_in->size == 4);
goto literal;
default:
break;
}
continue;
literal:
if (u_in->lit32 == 0xFEFEFEFF ||
u_in->lit32 == 0x80808080 ||
u_in->lit32 == 0x00008080) {
bogusLiterals = True;
break;
}
}
}
for (i = 0; i < cb_in->used; i++) {
qs = qd = qt = qtt = INVALID_TEMPREG;
u_in = &cb_in->instrs[i];
@ -1003,7 +1037,12 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
if (u_in->cond != CondAlways) {
sk_assert(u_in->flags_r != FlagsEmpty);
qt = create_GETVF(cb, 0);
uInstr1(cb, TESTV, 0, TempReg, qt);
if (/* HACK */ bogusLiterals) {
if (0)
VG_(printf)("ignore TESTV due to bogus literal\n");
} else {
uInstr1(cb, TESTV, 0, TempReg, qt);
}
/* qt should never be referred to again. Nevertheless
... */
uInstr1(cb, SETV, 0, TempReg, qt);