]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Incorporate horrible hack to workaround problem of emitting bogus
authorJulian Seward <jseward@acm.org>
Sun, 13 Oct 2002 00:57:26 +0000 (00:57 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 13 Oct 2002 00:57:26 +0000 (00:57 +0000)
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

memcheck/docs/manual.html
memcheck/mc_include.h
memcheck/mc_main.c
memcheck/mc_translate.c

index c2122f37f80924b452a681ad91debaf5aa658126..2847607d1dbfdcadba974181bfb2bcda16d43077 100644 (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,
index e25dedba56778340578c7e78872fc27766b141f8..2f9c905c2c431c734bd0128198e7cbbc32ee750b 100644 (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                                            ---*/
index ef9dfc49a72de224db5e450e57e4c66431988656..c2398db05f6302164c0188fefef5b6515338cc69 100644 (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";
 }
 
 
index 88f34ab59a0b2349578b890688f5ef7f35052136..f81bde39d1178223f4c8a450b28965682cf2982f 100644 (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);