]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Merge exp-ptrcheck/ changes from branches/MESSAGING_TIDYUP r10464.
authorJulian Seward <jseward@acm.org>
Wed, 15 Jul 2009 14:50:22 +0000 (14:50 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 15 Jul 2009 14:50:22 +0000 (14:50 +0000)
See trunk r10465 commit message for details.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10469

12 files changed:
exp-ptrcheck/h_main.c
exp-ptrcheck/pc_common.c
exp-ptrcheck/pc_common.h
exp-ptrcheck/pc_main.c
exp-ptrcheck/sg_main.c
exp-ptrcheck/tests/Makefile.am
exp-ptrcheck/tests/hsg.c [new file with mode: 0644]
exp-ptrcheck/tests/hsg.stderr.exp [new file with mode: 0644]
exp-ptrcheck/tests/hsg.stdout.exp [new file with mode: 0644]
exp-ptrcheck/tests/hsg.vgtest [new file with mode: 0644]
exp-ptrcheck/tests/supp.c
exp-ptrcheck/tests/supp.stderr.exp

index e5b0284b60a0515950317f05c3fadda9cc625ab7..1cc27ea755d16f57f5ac372c1927f45d93e4bea8 100644 (file)
@@ -1023,7 +1023,8 @@ void set_mem ( Addr a, SizeT len, Seg* seg )
 
    if (len > 100 * 1000 * 1000)
       VG_(message)(Vg_UserMsg,
-                   "Warning: set address range state: large range %lu", len);
+                   "Warning: set address range state: large range %lu\n",
+                   len);
 
    a   = VG_ROUNDDN(a,       sizeof(UWord));
    end = VG_ROUNDUP(a + len, sizeof(UWord));
@@ -2061,7 +2062,7 @@ void h_post_reg_write_clientcall(ThreadId tid, PtrdiffT guest_state_offset,
    else if (f == (Addr)h_replace_free
             || f == (Addr)h_replace___builtin_delete
             || f == (Addr)h_replace___builtin_vec_delete
-   //            || f == (Addr)VG_(cli_block_size)
+         // || f == (Addr)VG_(cli_block_size)
             || f == (Addr)VG_(message))
    {
       // Probably best to set the (non-existent!) return value to
@@ -5308,25 +5309,25 @@ void h_fini ( Int exitcode )
 {
    if (VG_(clo_verbosity) >= 2) {
       VG_(message)(Vg_DebugMsg,
-                   "  h_:  %'10llu client allocs, %'10llu client frees", 
+                   "  h_:  %'10llu client allocs, %'10llu client frees\n", 
                    stats__client_mallocs, stats__client_frees);
       VG_(message)(Vg_DebugMsg,
-                   "  h_:  %'10llu Segs allocd,   %'10llu Segs recycled", 
+                   "  h_:  %'10llu Segs allocd,   %'10llu Segs recycled\n", 
                    stats__segs_allocd, stats__segs_recycled);
    }
 
 #if 0
    if (h_clo_lossage_check) {
-      VG_(message)(Vg_UserMsg, "");
-      VG_(message)(Vg_UserMsg, "%12lld total memory references",
+      VG_(message)(Vg_UserMsg, "\n");
+      VG_(message)(Vg_UserMsg, "%12lld total memory references\n",
                                stats__tot_mem_refs);
-      VG_(message)(Vg_UserMsg, "%12lld   of which are in a known segment",
+      VG_(message)(Vg_UserMsg, "%12lld   of which are in a known segment\n",
                                stats__refs_in_a_seg);
-      VG_(message)(Vg_UserMsg, "%12lld   of which are 'lost' w.r.t the seg",
+      VG_(message)(Vg_UserMsg, "%12lld   of which are 'lost' w.r.t the seg\n",
                                stats__refs_lost_seg);
-      VG_(message)(Vg_UserMsg, "");
+      VG_(message)(Vg_UserMsg, "\n");
       show_lossage();
-      VG_(message)(Vg_UserMsg, "");
+      VG_(message)(Vg_UserMsg, "\n");
    } else {
       tl_assert( 0 == VG_(OSetGen_Size)(lossage) );
    }
index 90f9098c5b6499726de8f790cb4be35d5350f571..3d75748d3c125c21523d9d29886d16586d3c64b2 100644 (file)
@@ -38,6 +38,7 @@
 #include "pub_tool_basics.h"
 #include "pub_tool_libcbase.h"
 #include "pub_tool_libcprint.h"
+#include "pub_tool_xarray.h"
 #include "pub_tool_mallocfree.h"
 #include "pub_tool_libcassert.h"
 #include "pub_tool_options.h"
@@ -96,7 +97,7 @@ void pc_print_debug_usage(void)
 
 //////////////////////////////////////////////////////////////
 //                                                          //
-// Error management                                         //
+// Error management -- storage                              //
 //                                                          //
 //////////////////////////////////////////////////////////////
 
@@ -133,8 +134,8 @@ typedef
             Addr     addr;
             SSizeT   sszB;  /* -ve is write, +ve is read */
             Seg*     vseg;
-            Char     descr1[96];
-            Char     descr2[96];
+            XArray*  descr1; /* XArray* of HChar */
+            XArray*  descr2; /* XArray* of HChar */
             Char     datasym[96];
             PtrdiffT datasymoff;
          } Heap;
@@ -250,6 +251,47 @@ Bool pc_eq_Error ( VgRes res, Error* e1, Error* e2 )
 }
 
 
+//////////////////////////////////////////////////////////////
+//                                                          //
+// Error management -- printing                             //
+//                                                          //
+//////////////////////////////////////////////////////////////
+
+/* This is the "this error is due to be printed shortly; so have a
+   look at it any print any preamble you want" function.  Which, in
+   Ptrcheck, we don't use.  Hence a no-op.
+*/
+void pc_before_pp_Error ( Error* err ) {
+}
+
+/* Do a printf-style operation on either the XML or normal output
+   channel, depending on the setting of VG_(clo_xml).
+*/
+static void emit_WRK ( HChar* format, va_list vargs )
+{
+   if (VG_(clo_xml)) {
+      VG_(vprintf_xml)(format, vargs);
+   } else {
+      VG_(vmessage)(Vg_UserMsg, format, vargs);
+   }
+}
+static void emit ( HChar* format, ... ) PRINTF_CHECK(1, 2);
+static void emit ( HChar* format, ... )
+{
+   va_list vargs;
+   va_start(vargs, format);
+   emit_WRK(format, vargs);
+   va_end(vargs);
+}
+static void emiN ( HChar* format, ... ) /* With NO FORMAT CHECK */
+{
+   va_list vargs;
+   va_start(vargs, format);
+   emit_WRK(format, vargs);
+   va_end(vargs);
+}
+
+
 static Char* readwrite(SSizeT sszB)
 {
    return ( sszB < 0 ? "write" : "read" );
@@ -261,6 +303,8 @@ static Word Word__abs ( Word w ) {
 
 void pc_pp_Error ( Error* err )
 {
+   const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
+
    XError *xe = (XError*)VG_(get_error_extra)(err);
    tl_assert(xe);
 
@@ -268,15 +312,34 @@ void pc_pp_Error ( Error* err )
 
    //----------------------------------------------------------
    case XE_SorG:
-      tl_assert(xe);
-      VG_(message)(Vg_UserMsg, "Invalid %s of size %ld", 
-                               xe->XE.SorG.sszB < 0 ? "write" : "read",
-                               Word__abs(xe->XE.SorG.sszB) );
-      VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-      VG_(message)(Vg_UserMsg, " Address %#lx expected vs actual:",
-                               xe->XE.SorG.addr);
-      VG_(message)(Vg_UserMsg, " Expected: %s", &xe->XE.SorG.expect[0] );
-      VG_(message)(Vg_UserMsg, " Actual:   %s", &xe->XE.SorG.actual[0] );
+
+      if (xml) {
+
+         emit( "  <kind>SorG</kind>\n");
+         emit( "  <what>Invalid %s of size %ld</what>\n",
+               xe->XE.SorG.sszB < 0 ? "write" : "read",
+               Word__abs(xe->XE.SorG.sszB) );
+         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+         emit( "  <auxwhat>Address %#lx expected vs actual:</auxwhat>\n",
+               xe->XE.SorG.addr );
+         emiN( "  <auxwhat>Expected: %t</auxwhat>\n",
+               &xe->XE.SorG.expect[0] );
+         emiN( "  <auxwhat>Actual:   %t</auxwhat>\n", 
+               &xe->XE.SorG.actual[0] );
+
+      } else {
+
+         emit( "Invalid %s of size %ld\n", 
+               xe->XE.SorG.sszB < 0 ? "write" : "read",
+               Word__abs(xe->XE.SorG.sszB) );
+         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+         emit( " Address %#lx expected vs actual:\n", xe->XE.SorG.addr );
+         emit( " Expected: %s\n", &xe->XE.SorG.expect[0] );
+         emit( " Actual:   %s\n", &xe->XE.SorG.actual[0] );
+
+      }
       break;
 
    //----------------------------------------------------------
@@ -289,12 +352,29 @@ void pc_pp_Error ( Error* err )
 
       if (NONPTR == vseg) {
          // Access via a non-pointer
-         VG_(message)(Vg_UserMsg, "Invalid %s of size %ld",
-                                   readwrite(xe->XE.Heap.sszB),
-                                   Word__abs(xe->XE.Heap.sszB));
-         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
-         VG_(message)(Vg_UserMsg,
-                      " Address %#lx is not derived from any known block", a);
+
+         if (xml) {
+
+            emit( "  <kind>Heap</kind>\n");
+            emit( "  <what>Invalid %s of size %ld</what>\n",
+                  readwrite(xe->XE.Heap.sszB),
+                  Word__abs(xe->XE.Heap.sszB) );
+            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+            emit( "  <auxwhat>Address %#lx is not derived from "
+                  "any known block</auxwhat>\n", a );
+
+         } else {
+
+            emit( "Invalid %s of size %ld\n",
+                  readwrite(xe->XE.Heap.sszB),
+                  Word__abs(xe->XE.Heap.sszB) );
+            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+            emit( " Address %#lx is not derived from "
+                  "any known block\n", a );
+
+         }
 
       } else {
          // Access via a pointer, but outside its range.
@@ -308,30 +388,77 @@ void pc_pp_Error ( Error* err )
                        ? "Doubly-invalid" : "Invalid" );
          legit = ( Seg__is_freed(vseg) ? "once-" : "" );
 
-         VG_(message)(Vg_UserMsg, "%s %s of size %ld", how_invalid,
-                                  readwrite(xe->XE.Heap.sszB),
-                                  Word__abs(xe->XE.Heap.sszB));
-         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+         if (xml) {
+
+            emit( "  <kind>Heap</kind>\n");
+            emit( "  <what>%s %s of size %ld</what>\n",
+                  how_invalid,
+                  readwrite(xe->XE.Heap.sszB),
+                  Word__abs(xe->XE.Heap.sszB) );
+            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+            emit( "  <auxwhat>Address %#lx is %lu bytes %s "
+                     "the accessing pointer's</auxwhat>\n",
+                  a, miss_size, place );
+            emit( "  <auxwhat>%slegitimate range, "
+                     "a block of size %lu %s</auxwhat>\n",
+                  legit, Seg__size(vseg),
+                  Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
+            VG_(pp_ExeContext)(Seg__where(vseg));
+
+         } else {
+
+            emit( "%s %s of size %ld\n",
+                  how_invalid,
+                  readwrite(xe->XE.Heap.sszB),
+                  Word__abs(xe->XE.Heap.sszB) );
+            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+            emit( " Address %#lx is %lu bytes %s the accessing pointer's\n",
+                  a, miss_size, place );
+            emit( " %slegitimate range, a block of size %lu %s\n",
+                  legit, Seg__size(vseg),
+                  Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
+            VG_(pp_ExeContext)(Seg__where(vseg));
+
+         }
+      }
+
+      /* If we have a better description of the address, show it.
+         Note that in XML mode, it will already by nicely wrapped up
+         in tags, either <auxwhat> or <xauxwhat>, so we can just emit
+         it verbatim. */
+      if (xml) {
+
+         if (xe->XE.Heap.descr1)
+            emiN( "  %t\n",
+                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
+         if (xe->XE.Heap.descr2)
+            emiN( "  %t\n",
+                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) );
+         if (xe->XE.Heap.datasym[0] != 0)
+            emiN( "  <auxwhat>Address 0x%llx is %llu bytes "
+                  "inside data symbol \"%t\"</auxwhat>\n",
+                  (ULong)xe->XE.Heap.addr,
+                  (ULong)xe->XE.Heap.datasymoff,
+                  xe->XE.Heap.datasym );
+
+      } else {
+
+         if (xe->XE.Heap.descr1)
+            emit( " %s\n",
+                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
+         if (xe->XE.Heap.descr2)
+            emit( " %s\n",
+                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) ); 
+         if (xe->XE.Heap.datasym[0] != 0)
+            emit( " Address 0x%llx is %llu bytes "
+                  "inside data symbol \"%s\"\n",
+                  (ULong)xe->XE.Heap.addr,
+                  (ULong)xe->XE.Heap.datasymoff,
+                  xe->XE.Heap.datasym );
 
-         VG_(message)(Vg_UserMsg,
-                      " Address %#lx is %lu bytes %s the accessing pointer's",
-                      a, miss_size, place);
-         VG_(message)(Vg_UserMsg,
-                      " %slegitimate range, a block of size %lu %s",
-                      legit, Seg__size(vseg),
-                      Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
-         VG_(pp_ExeContext)(Seg__where(vseg));
       }
-      if (xe->XE.Heap.descr1[0] != 0)
-         VG_(message)(Vg_UserMsg, " %s", xe->XE.Heap.descr1);
-      if (xe->XE.Heap.descr2[0] != 0)
-         VG_(message)(Vg_UserMsg, " %s", xe->XE.Heap.descr2);
-      if (xe->XE.Heap.datasym[0] != 0)
-         VG_(message)(Vg_UserMsg, " Address 0x%llx is %llu bytes "
-                      "inside data symbol \"%s\"",
-                      (ULong)xe->XE.Heap.addr,
-                      (ULong)xe->XE.Heap.datasymoff,
-                      xe->XE.Heap.datasym);
       break;
    }
 
@@ -344,32 +471,69 @@ void pc_pp_Error ( Error* err )
       tl_assert(BOTTOM != seg1);
       tl_assert(BOTTOM != seg2 && UNKNOWN != seg2);
 
-      VG_(message)(Vg_UserMsg, "Invalid arguments to %s", xe->XE.Arith.opname);
-      VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+      if (xml) {
 
-      if (seg1 != seg2) {
-         if (NONPTR == seg1) {
-            VG_(message)(Vg_UserMsg, " First arg not a pointer");
-         } else if (UNKNOWN == seg1) {
-            VG_(message)(Vg_UserMsg, " First arg may be a pointer");
+         emit( "  <kind>Arith</kind>\n");
+         emit( "  <what>Invalid arguments to %s</what>\n",
+               xe->XE.Arith.opname );
+         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+         if (seg1 != seg2) {
+            if (NONPTR == seg1) {
+               emit( "  <auxwhat>First arg not a pointer</auxwhat>\n" );
+            } else if (UNKNOWN == seg1) {
+               emit( "  <auxwhat>First arg may be a pointer</auxwhat>\n" );
+            } else {
+               emit( "  <auxwhat>First arg derived from address %#lx of "
+                     "%lu-byte block alloc'd</auxwhat>\n",
+                     Seg__addr(seg1), Seg__size(seg1) );
+               VG_(pp_ExeContext)(Seg__where(seg1));
+            }
+            which = "Second arg";
          } else {
-            VG_(message)(Vg_UserMsg, " First arg derived from address %#lx of "
-                                     "%lu-byte block alloc'd",
-                                     Seg__addr(seg1), Seg__size(seg1) );
-            VG_(pp_ExeContext)(Seg__where(seg1));
+            which = "Both args";
          }
-         which = "Second arg";
-      } else {
-         which = "Both args";
-      }
-      if (NONPTR == seg2) {
-         VG_(message)(Vg_UserMsg, " %s not a pointer", which);
+         if (NONPTR == seg2) {
+            emit( "  <auxwhat>%s not a pointer</auxwhat>\n", which );
+         } else {
+            emit( "  <auxwhat>%s derived from address %#lx of "
+                  "%lu-byte block alloc'd</auxwhat>\n",
+                  which, Seg__addr(seg2), Seg__size(seg2) );
+            VG_(pp_ExeContext)(Seg__where(seg2));
+         }
+
       } else {
-         VG_(message)(Vg_UserMsg, " %s derived from address %#lx of "
-                                  "%lu-byte block alloc'd",
-                      which, Seg__addr(seg2), Seg__size(seg2) );
-         VG_(pp_ExeContext)(Seg__where(seg2));
+
+         emit( "Invalid arguments to %s\n",
+               xe->XE.Arith.opname );
+         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+         if (seg1 != seg2) {
+            if (NONPTR == seg1) {
+               emit( " First arg not a pointer\n" );
+            } else if (UNKNOWN == seg1) {
+               emit( " First arg may be a pointer\n" );
+            } else {
+               emit( " First arg derived from address %#lx of "
+                     "%lu-byte block alloc'd\n",
+                     Seg__addr(seg1), Seg__size(seg1) );
+               VG_(pp_ExeContext)(Seg__where(seg1));
+            }
+            which = "Second arg";
+         } else {
+            which = "Both args";
+         }
+         if (NONPTR == seg2) {
+            emit( " %s not a pointer\n", which );
+         } else {
+            emit( " %s derived from address %#lx of "
+                  "%lu-byte block alloc'd\n",
+                  which, Seg__addr(seg2), Seg__size(seg2) );
+            VG_(pp_ExeContext)(Seg__where(seg2));
+         }
+
       }
+
       break;
    }
 
@@ -392,40 +556,88 @@ void pc_pp_Error ( Error* err )
          // freed block
          tl_assert(is_known_segment(seglo));
          tl_assert(Seg__is_freed(seglo)); // XXX what if it's now recycled?
-         VG_(message)(Vg_UserMsg, "%s%s contains unaddressable byte(s)",
-                                  what, s);
-         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
 
-         VG_(message)(Vg_UserMsg, " Address %#lx is %ld bytes inside a "
-                                  "%ld-byte block free'd",
-                                  lo, lo-Seg__addr(seglo),
-                                  Seg__size(seglo) );
-         VG_(pp_ExeContext)(Seg__where(seglo));
+         if (xml) {
 
-      } else {
-         // mismatch
-         VG_(message)(Vg_UserMsg, "%s%s is non-contiguous", what, s);
-         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+            emit( "  <kind>SysParam</kind>\n");
+            emit( "  <what>%s%s contains unaddressable byte(s)</what>\n",
+                  what, s );
+            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+            emit( "  <auxwhat>Address %#lx is %ld bytes inside a "
+                  "%ld-byte block free'd</auxwhat>\n",
+                  lo, lo-Seg__addr(seglo), Seg__size(seglo) );
+            VG_(pp_ExeContext)(Seg__where(seglo));
 
-         if (UNKNOWN == seglo) {
-            VG_(message)(Vg_UserMsg, " First byte is not inside a known block");
          } else {
-            VG_(message)(Vg_UserMsg, " First byte (%#lx) is %ld bytes inside a "
-                                     "%ld-byte block alloc'd",
-                                     lo, lo-Seg__addr(seglo), 
-                                     Seg__size(seglo) );
+
+            emit( " %s%s contains unaddressable byte(s)\n",
+                  what, s );
+            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+            emit( " Address %#lx is %ld bytes inside a "
+                  "%ld-byte block free'd\n",
+                  lo, lo-Seg__addr(seglo), Seg__size(seglo) );
             VG_(pp_ExeContext)(Seg__where(seglo));
+
          }
 
-         if (UNKNOWN == seghi) {
-            VG_(message)(Vg_UserMsg, " Last byte is not inside a known block");
+      } else {
+         // mismatch
+
+         if (xml) {
+
+            emit( "  <kind>SysParam</kind>\n");
+            emit( "  <what>%s%s is non-contiguous</what>\n",
+                  what, s );
+            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+            if (UNKNOWN == seglo) {
+               emit( "  <auxwhat>First byte is "
+                        "not inside a known block</auxwhat>\n" );
+            } else {
+               emit( "  <auxwhat>First byte (%#lx) is %ld bytes inside a "
+                     "%ld-byte block alloc'd</auxwhat>\n",
+                     lo, lo-Seg__addr(seglo), Seg__size(seglo) );
+               VG_(pp_ExeContext)(Seg__where(seglo));
+            }
+   
+            if (UNKNOWN == seghi) {
+               emit( "  <auxwhat>Last byte is "
+                        "not inside a known block</auxwhat>\n" );
+            } else {
+               emit( "  <auxwhat>Last byte (%#lx) is %ld bytes inside a "
+                     "%ld-byte block alloc'd</auxwhat>\n",
+                     hi, hi-Seg__addr(seghi), Seg__size(seghi) );
+               VG_(pp_ExeContext)(Seg__where(seghi));
+            }
+
          } else {
-            VG_(message)(Vg_UserMsg, " Last byte (%#lx) is %ld bytes inside a "
-                                     "%ld-byte block alloc'd",
-                                     hi, hi-Seg__addr(seghi),
-                                     Seg__size(seghi) );
-            VG_(pp_ExeContext)(Seg__where(seghi));
+
+            emit( "%s%s is non-contiguous\n",
+                  what, s );
+            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+   
+            if (UNKNOWN == seglo) {
+               emit( " First byte is not inside a known block\n" );
+            } else {
+               emit( " First byte (%#lx) is %ld bytes inside a "
+                     "%ld-byte block alloc'd\n",
+                     lo, lo-Seg__addr(seglo), Seg__size(seglo) );
+               VG_(pp_ExeContext)(Seg__where(seglo));
+            }
+   
+            if (UNKNOWN == seghi) {
+               emit( " Last byte is not inside a known block\n" );
+            } else {
+               emit( " Last byte (%#lx) is %ld bytes inside a "
+                     "%ld-byte block alloc'd\n",
+                     hi, hi-Seg__addr(seghi), Seg__size(seghi) );
+               VG_(pp_ExeContext)(Seg__where(seghi));
+            }
+
          }
+
       }
       break;
    }
@@ -442,38 +654,71 @@ UInt pc_update_Error_extra ( Error* err )
    tl_assert(xe);
    switch (xe->tag) {
       case XE_SorG:
-         return sizeof(XError);
+         break;
       case XE_Heap: {
-         tl_assert(sizeof(xe->XE.Heap.descr1) == sizeof(xe->XE.Heap.descr2));
-         tl_assert(sizeof(xe->XE.Heap.descr1) > 0);
+         Bool have_descr;
+
          tl_assert(sizeof(xe->XE.Heap.datasym) > 0);
-         VG_(memset)(&xe->XE.Heap.descr1, 0, sizeof(xe->XE.Heap.descr1));
-         VG_(memset)(&xe->XE.Heap.descr2, 0, sizeof(xe->XE.Heap.descr2));
+         xe->XE.Heap.datasymoff = 0;
+         xe->XE.Heap.datasym[0] = 0;
+
+         tl_assert(!xe->XE.Heap.descr1);
+         tl_assert(!xe->XE.Heap.descr2);
+
+         xe->XE.Heap.descr1
+            = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
+                          VG_(free), sizeof(HChar) );
+         xe->XE.Heap.descr2
+            = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
+                          VG_(free), sizeof(HChar) );
+
          VG_(memset)(&xe->XE.Heap.datasym, 0, sizeof(xe->XE.Heap.datasym));
          xe->XE.Heap.datasymoff = 0;
-         if (VG_(get_data_description)( &xe->XE.Heap.descr1[0],
-                                        &xe->XE.Heap.descr2[0],
-                                        sizeof(xe->XE.Heap.descr1)-1,
-                                        xe->XE.Heap.addr )) {
-            tl_assert(xe->XE.Heap.descr1[sizeof(xe->XE.Heap.descr1)-1] == 0);
-            tl_assert(xe->XE.Heap.descr1[sizeof(xe->XE.Heap.descr2)-1] == 0);
+
+         have_descr
+            = VG_(get_data_description)( xe->XE.Heap.descr1,
+                                         xe->XE.Heap.descr2,
+                                         xe->XE.Heap.addr );
+
+         /* If there's nothing in descr1/2, free it.  Why is it safe to
+            to VG_(indexXA) at zero here?  Because
+            VG_(get_data_description) guarantees to zero terminate
+            descr1/2 regardless of the outcome of the call.  So there's
+            always at least one element in each XA after the call.
+         */
+         if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Heap.descr1, 0 ))
+             || !have_descr) {
+            VG_(deleteXA)( xe->XE.Heap.descr1 );
+            xe->XE.Heap.descr1 = NULL;
          }
-         else
-         if (VG_(get_datasym_and_offset)( xe->XE.Heap.addr,
-                                          &xe->XE.Heap.datasym[0],
-                                          sizeof(xe->XE.Heap.datasym)-1,
-                                          &xe->XE.Heap.datasymoff )) {
-            tl_assert(xe->XE.Heap.datasym[sizeof(xe->XE.Heap.datasym)-1] == 0);
+         if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Heap.descr2, 0 ))
+             || !have_descr) {
+            VG_(deleteXA)( xe->XE.Heap.descr2 );
+            xe->XE.Heap.descr2 = NULL;
+         }
+
+         /* If Dwarf3 info produced nothing useful, see at least if
+            we can fish something useful out of the ELF symbol info. */
+         if (!have_descr) {
+            if (VG_(get_datasym_and_offset)(
+                   xe->XE.Heap.addr, &xe->XE.Heap.datasym[0],
+                   sizeof(xe->XE.Heap.datasym)-1,
+                   &xe->XE.Heap.datasymoff )
+               ) {
+               tl_assert(xe->XE.Heap.datasym[sizeof(xe->XE.Heap.datasym)-1] 
+                         == 0);
+            }
          }
-         return sizeof(XError);
+         break;
       }
       case XE_Arith:
-         return sizeof(XError);
+         break;
       case XE_SysParam:
-         return sizeof(XError);
+         break;
       default:
          VG_(tool_panic)("update_extra");
    }
+   return sizeof(XError);
 }
 
 Bool pc_is_recognised_suppression ( Char* name, Supp *su )
index 023307f4b0a58024fa22d898e79ff6a8223c0fda..9c440d1672de335ec2c8346b802c9e1a6e5ed667 100644 (file)
@@ -47,8 +47,9 @@ void h_record_arith_error( Seg* seg1, Seg* seg2, HChar* opname );
 void h_record_sysparam_error( ThreadId tid, CorePart part, Char* s,
                               Addr lo, Addr hi, Seg* seglo, Seg* seghi );
 
-Bool pc_eq_Error ( VgRes res, Error* e1, Error* e2 );
-void pc_pp_Error ( Error* err );
+Bool pc_eq_Error           ( VgRes res, Error* e1, Error* e2 );
+void pc_before_pp_Error    ( Error* err );
+void pc_pp_Error           ( Error* err );
 UInt pc_update_Error_extra ( Error* err );
 Bool pc_is_recognised_suppression ( Char* name, Supp *su );
 Bool pc_read_extra_suppression_info ( Int fd, Char* buf, 
index 6f44bbfd3c7d313e7eb463966ee9684ee8828df8..436dba0136fe75acf80ff71043d928f43b1c2ef9 100644 (file)
@@ -130,11 +130,14 @@ static void pc_post_clo_init ( void )
 #  elif defined(VGA_ppc32) || defined(VGA_ppc64)
    if (VG_(clo_verbosity) >= 1 && sg_clo_enable_sg_checks) {
       VG_(message)(Vg_UserMsg, 
-         "WARNING: exp-ptrcheck on ppc32/ppc64 platforms: stack and global array");
+         "WARNING: exp-ptrcheck on ppc32/ppc64 platforms: "
+         "stack and global array\n");
       VG_(message)(Vg_UserMsg, 
-         "WARNING: checking is not currently supported.  Only heap checking is");
+         "WARNING: checking is not currently supported.  "
+         "Only heap checking is\n");
       VG_(message)(Vg_UserMsg, 
-         "WARNING: supported.  Disabling s/g checks (like --enable-sg-checks=no).");
+         "WARNING: supported.  Disabling s/g checks "
+         "(like --enable-sg-checks=no).\n");
    }
    sg_clo_enable_sg_checks = False;
 #  else
@@ -179,6 +182,7 @@ static void pc_pre_clo_init(void)
 
    VG_(needs_core_errors)       ();
    VG_(needs_tool_errors)       (pc_eq_Error,
+                                 pc_before_pp_Error,
                                  pc_pp_Error,
                                  True,/*show TIDs for errors*/
                                  pc_update_Error_extra,
@@ -188,6 +192,8 @@ static void pc_pre_clo_init(void)
                                  pc_get_error_name,
                                  pc_print_extra_suppression_info);
 
+   VG_(needs_xml_output)        ();
+
    VG_(needs_syscall_wrapper)( h_pre_syscall,
                                h_post_syscall );
 
index 85d8078ea114654417e3b7a811a18725707f7fe8..27ed7820782acd0a9cda76f7c7860293693dab31 100644 (file)
@@ -223,16 +223,16 @@ static Word StackBlocks__cmp ( XArray* fb1s, XArray* fb2s )
 static void pp_StackBlocks ( XArray* sbs )
 {
    Word i, n = VG_(sizeXA)( sbs );
-   VG_(message)(Vg_DebugMsg, "<<< STACKBLOCKS" );
+   VG_(message)(Vg_DebugMsg, "<<< STACKBLOCKS\n" );
    for (i = 0; i < n; i++) {
       StackBlock* sb = (StackBlock*)VG_(indexXA)( sbs, i );
       VG_(message)(Vg_DebugMsg,
-         "   StackBlock{ off %ld szB %lu spRel:%c isVec:%c \"%s\" }",
+         "   StackBlock{ off %ld szB %lu spRel:%c isVec:%c \"%s\" }\n",
          sb->base, sb->szB, sb->spRel ? 'Y' : 'N',
          sb->isVec ? 'Y' : 'N', &sb->name[0] 
       );
    }
-   VG_(message)(Vg_DebugMsg, ">>> STACKBLOCKS" );
+   VG_(message)(Vg_DebugMsg, ">>> STACKBLOCKS\n" );
 }
 
 
@@ -345,12 +345,12 @@ static XArray* /* of StackBlock */
           if (moans > 0 && !VG_(clo_xml)) {
              moans--;
              VG_(message)(Vg_UserMsg, "Warning: bogus DWARF3 info: "
-                                      "overlapping stack blocks");
+                                      "overlapping stack blocks\n");
              if (VG_(clo_verbosity) >= 2)
                 pp_StackBlocks(orig);
              if (moans == 0)
                 VG_(message)(Vg_UserMsg, "Further instances of this "
-                                         "message will not be shown" );
+                                         "message will not be shown\n" );
           }
           VG_(dropTailXA)( orig, VG_(sizeXA)( orig ));
           break;
@@ -740,7 +740,7 @@ static void add_block_to_GlobalTree (
    if (already_present && moans > 0 && !VG_(clo_xml)) {
       moans--;
       VG_(message)(Vg_UserMsg, "Warning: bogus DWARF3 info: "
-                               "overlapping global blocks");
+                               "overlapping global blocks\n");
       if (VG_(clo_verbosity) >= 2) {
          GlobalTree__pp( gitree,
                          "add_block_to_GlobalTree: non-exact duplicate" );
@@ -750,7 +750,7 @@ static void add_block_to_GlobalTree (
       }
       if (moans == 0)
          VG_(message)(Vg_UserMsg, "Further instances of this "
-                                  "message will not be shown" );
+                                  "message will not be shown\n" );
    }
    /* tl_assert(!already_present); */
 }
@@ -1830,7 +1830,7 @@ void shadowStack_new_frame ( ThreadId tid,
          if (0 && (sb || gb))
             VG_(message)(Vg_DebugMsg, 
                          "exp-sgcheck: new max tree sizes: "
-                         "StackTree %ld, GlobalTree %ld",
+                         "StackTree %ld, GlobalTree %ld\n",
                          stats__max_sitree_size, stats__max_gitree_size );
       }
    } else {
@@ -2454,32 +2454,32 @@ void sg_fini(Int exitcode)
 {
    if (VG_(clo_verbosity) >= 2) {
       VG_(message)(Vg_DebugMsg,
-         " sg_:  %'llu total accesses, of which:", stats__total_accesses);
+         " sg_:  %'llu total accesses, of which:\n", stats__total_accesses);
       VG_(message)(Vg_DebugMsg,
-         " sg_:     stack0: %'12llu classify",
+         " sg_:     stack0: %'12llu classify\n",
          stats__classify_Stack0);
       VG_(message)(Vg_DebugMsg,
-         " sg_:     stackN: %'12llu classify",
+         " sg_:     stackN: %'12llu classify\n",
          stats__classify_StackN);
       VG_(message)(Vg_DebugMsg,
-         " sg_:     global: %'12llu classify",
+         " sg_:     global: %'12llu classify\n",
          stats__classify_Global);
       VG_(message)(Vg_DebugMsg,
-         " sg_:    unknown: %'12llu classify",
+         " sg_:    unknown: %'12llu classify\n",
          stats__classify_Unknown);
       VG_(message)(Vg_DebugMsg,
-         " sg_:  %'llu Invars preened, of which %'llu changed",
+         " sg_:  %'llu Invars preened, of which %'llu changed\n",
          stats__Invars_preened, stats__Invars_changed);
       VG_(message)(Vg_DebugMsg,
-         " sg_:   t_i_b_MT: %'12llu", stats__t_i_b_empty);
+         " sg_:   t_i_b_MT: %'12llu\n", stats__t_i_b_empty);
       VG_(message)(Vg_DebugMsg, 
-         " sg_:     qcache: %'llu searches, %'llu probes, %'llu misses",
+         " sg_:     qcache: %'llu searches, %'llu probes, %'llu misses\n",
          stats__qcache_queries, stats__qcache_probes, stats__qcache_misses);
       VG_(message)(Vg_DebugMsg, 
-         " sg_:  htab-fast: %'llu hits",
+         " sg_:  htab-fast: %'llu hits\n",
          stats__htab_fast);
       VG_(message)(Vg_DebugMsg, 
-         " sg_:  htab-slow: %'llu searches, %'llu probes, %'llu resizes",
+         " sg_:  htab-slow: %'llu searches, %'llu probes, %'llu resizes\n",
          stats__htab_searches, stats__htab_probes, stats__htab_resizes);
    }
 }
index 8a127899ffa04f394c8125d33857deb6d5f64dd2..02c7d5690029549b901a5763ab96e77ab086cf32 100644 (file)
@@ -23,6 +23,7 @@ EXTRA_DIST = \
        hackedbz2.stderr.exp-glibc28-amd64 \
        hp_bounds.vgtest hp_bounds.stderr.exp \
        hp_dangle.vgtest hp_dangle.stderr.exp \
+       hsg.vgtest hsg.stdout.exp hsg.stderr.exp \
        idiv.vgtest-disabled idiv.stderr.exp \
        imul.vgtest-disabled imul.stderr.exp \
        justify.vgtest justify.stderr.exp \
@@ -61,7 +62,7 @@ EXTRA_DIST = \
 check_PROGRAMS = \
        add and arith bad_percentify base cmp fp \
        globalerr hackedbz2 \
-       hp_bounds hp_dangle idiv imul \
+       hp_bounds hp_dangle hsg idiv imul \
        justify mm not neg or partial \
        preen_invars preen_invars_so.so \
        pth_create pth_specific realloc \
diff --git a/exp-ptrcheck/tests/hsg.c b/exp-ptrcheck/tests/hsg.c
new file mode 100644 (file)
index 0000000..7f497b4
--- /dev/null
@@ -0,0 +1,48 @@
+
+/* A simple test to demonstrate heap, stack, and global overrun
+   detection. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+short ga[100];
+
+__attribute__((noinline))
+int addup_wrongly ( short* arr )
+{
+   int sum = 0, i;
+   for (i = 0; i <= 100; i++)
+      sum += (int)arr[i];
+   return sum;
+}
+
+__attribute__((noinline))
+int do_other_stuff ( void )
+{
+   short la[100];
+   return 123 + addup_wrongly(la);
+}
+
+__attribute__((noinline))
+int do_stupid_malloc_stuff ( void )
+{
+   int sum = 0;
+   unsigned char* duh = malloc(100 * sizeof(char));
+   sum += duh[-1];
+   free(duh);
+   sum += duh[50];
+   return sum;
+}
+
+int main ( void )
+{
+   long s = addup_wrongly(ga);
+   s += do_other_stuff();
+   s += do_stupid_malloc_stuff();
+   if (s == 123456789) {
+      fprintf(stdout, "well, i never!\n");
+   } else {
+      fprintf(stdout, "boringly as expected\n");
+   }
+   return 0;
+}
diff --git a/exp-ptrcheck/tests/hsg.stderr.exp b/exp-ptrcheck/tests/hsg.stderr.exp
new file mode 100644 (file)
index 0000000..50180be
--- /dev/null
@@ -0,0 +1,231 @@
+<?xml version="1.0"?>
+
+<valgrindoutput>
+
+<protocolversion>4</protocolversion>
+<protocoltool>exp-ptrcheck</protocoltool>
+
+<preamble>
+  <line>...</line>
+  <line>...</line>
+  <line>...</line>
+  <line>...</line>
+  <line>...</line>
+  <line>...</line>
+  <line>...</line>
+</preamble>
+
+<pid>...</pid>
+<ppid>...</ppid>
+<tool>exp-ptrcheck</tool>
+
+<args>
+  <vargv>...</vargv>
+  <argv>
+    <exe>./hsg</exe>
+  </argv>
+</args>
+
+<status>
+  <state>RUNNING</state>
+  <time>...</time>
+</status>
+
+<error>
+  <unique>0x........</unique>
+  <tid>...</tid>
+  <kind>SorG</kind>
+  <what>Invalid read of size 2</what>
+  <stack>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>addup_wrongly</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>main</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+  </stack>
+  <auxwhat>Address 0x........ expected vs actual:</auxwhat>
+  <auxwhat>Expected: global array "ga" in object with soname "NONE"</auxwhat>
+  <auxwhat>Actual:   unknown</auxwhat>
+</error>
+
+<error>
+  <unique>0x........</unique>
+  <tid>...</tid>
+  <kind>SorG</kind>
+  <what>Invalid read of size 2</what>
+  <stack>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>addup_wrongly</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>do_other_stuff</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>main</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+  </stack>
+  <auxwhat>Address 0x........ expected vs actual:</auxwhat>
+  <auxwhat>Expected: stack array "la" in frame 1 back from here</auxwhat>
+  <auxwhat>Actual:   unknown</auxwhat>
+</error>
+
+<error>
+  <unique>0x........</unique>
+  <tid>...</tid>
+  <kind>Heap</kind>
+  <what>Invalid read of size 1</what>
+  <stack>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>do_stupid_malloc_stuff</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>main</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+  </stack>
+  <auxwhat>Address 0x........ is 1 bytes before the accessing pointer's</auxwhat>
+  <auxwhat>legitimate range, a block of size 100 alloc'd</auxwhat>
+  <stack>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>malloc</fn>
+      <dir>...</dir>
+      <file>vg_replace_malloc.c</file>
+      <line>...</line>
+    </frame>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>do_stupid_malloc_stuff</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>main</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+  </stack>
+</error>
+
+<error>
+  <unique>0x........</unique>
+  <tid>...</tid>
+  <kind>Heap</kind>
+  <what>Invalid read of size 1</what>
+  <stack>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>do_stupid_malloc_stuff</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>main</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+  </stack>
+  <auxwhat>Address 0x........ is 50 bytes inside the accessing pointer's</auxwhat>
+  <auxwhat>once-legitimate range, a block of size 100 free'd</auxwhat>
+  <stack>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>free</fn>
+      <dir>...</dir>
+      <file>vg_replace_malloc.c</file>
+      <line>...</line>
+    </frame>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>do_stupid_malloc_stuff</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+    <frame>
+      <ip>0x........</ip>
+      <obj>...</obj>
+      <fn>main</fn>
+      <dir>...</dir>
+      <file>hsg.c</file>
+      <line>...</line>
+    </frame>
+  </stack>
+</error>
+
+<status>
+  <state>FINISHED</state>
+  <time>...</time>
+</status>
+
+<errorcounts>
+  <pair>
+    <count>...</count>
+    <unique>0x........</unique>
+  </pair>
+  <pair>
+    <count>...</count>
+    <unique>0x........</unique>
+  </pair>
+  <pair>
+    <count>...</count>
+    <unique>0x........</unique>
+  </pair>
+  <pair>
+    <count>...</count>
+    <unique>0x........</unique>
+  </pair>
+</errorcounts>
+
+<suppcounts>...</suppcounts>
+
+</valgrindoutput>
+
diff --git a/exp-ptrcheck/tests/hsg.stdout.exp b/exp-ptrcheck/tests/hsg.stdout.exp
new file mode 100644 (file)
index 0000000..e5b8e6d
--- /dev/null
@@ -0,0 +1 @@
+boringly as expected
diff --git a/exp-ptrcheck/tests/hsg.vgtest b/exp-ptrcheck/tests/hsg.vgtest
new file mode 100644 (file)
index 0000000..663a523
--- /dev/null
@@ -0,0 +1,3 @@
+prog: hsg
+vgopts: --xml=yes --xml-fd=2 --log-file=/dev/null
+stderr_filter: ../../memcheck/tests/filter_xml
index 9d211b95083f076a7d51ffb9c9dab5a1071425d5..97f77883706aa0b1b54870860ab8afc5b9221b7e 100644 (file)
@@ -8,12 +8,12 @@
 
 int main(void)
 {
-   int   i = 11;
+   int   i = 11; int fd = open("/dev/null", O_WRONLY);
    char* buf = malloc(sizeof(char) * 6);
    char  c = buf[-1];                  // LoadStoreErr
    char* x = buf + (long)buf;          // ArithErr
    char* y = (char*)((long)buf * i);   // AsmErr
-   write(-1, buf+3, 5);                // SysParamErr
-
+   write(fd, buf+3, 5);                // SysParamErr
+   close(fd);
    return x-y+c;
 }
index ef8f81138f4e80b46a617afd940c0fd436de3221..5d219e3991c3d43defe575fa93ce5732c2c02da7 100644 (file)
@@ -1,4 +1,10 @@
 
-Warning: invalid file descriptor -1 in syscall write()
+Syscall param write(buf) is non-contiguous
+   at 0x........: write (in /...libc...)
+   by 0x........: main (supp.c:16)
+ First byte (0x........) is 3 bytes inside a 6-byte block alloc'd
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   by 0x........: main (supp.c:12)
+ Last byte is not inside a known block
 
-ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)