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 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/memcheck/docs/manual.html b/memcheck/docs/manual.html
index c2122f3..2847607 100644
--- a/memcheck/docs/manual.html
+++ b/memcheck/docs/manual.html
@@ -583,6 +583,20 @@
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,
diff --git a/memcheck/mc_include.h b/memcheck/mc_include.h
index e25dedb..2f9c905 100644
--- a/memcheck/mc_include.h
+++ b/memcheck/mc_include.h
@@ -145,6 +145,10 @@
/* 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 ---*/
diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c
index ef9dfc4..c2398db 100644
--- a/memcheck/mc_main.c
+++ b/memcheck/mc_main.c
@@ -57,6 +57,8 @@
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 @@
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 @@
" --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";
}
diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c
index 88f34ab..f81bde3 100644
--- a/memcheck/mc_translate.c
+++ b/memcheck/mc_translate.c
@@ -498,9 +498,43 @@
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 @@
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);