Merge exp-ptrcheck/ changes from branches/MESSAGING_TIDYUP r10464.

See trunk r10465 commit message for details.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10469
This commit is contained in:
Julian Seward 2009-07-15 14:50:22 +00:00
parent d6407ffc63
commit 97c1ddae79
12 changed files with 689 additions and 146 deletions

View 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) );
}

View 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";
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 {
which = "Both args";
}
if (NONPTR == seg2) {
VG_(message)(Vg_UserMsg, " %s not a pointer", which);
} 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) {
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));
} else {
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));
}
} else {
// mismatch
VG_(message)(Vg_UserMsg, "%s%s is non-contiguous", what, s);
VG_(pp_ExeContext)( VG_(get_error_where)(err) );
if (UNKNOWN == seglo) {
VG_(message)(Vg_UserMsg, " First byte is not inside a known block");
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, " First byte (%#lx) is %ld bytes inside a "
"%ld-byte block alloc'd",
lo, lo-Seg__addr(seglo),
Seg__size(seglo) );
VG_(pp_ExeContext)(Seg__where(seglo));
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));
}
}
if (UNKNOWN == seghi) {
VG_(message)(Vg_UserMsg, " Last byte is not inside a known block");
} 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));
}
}
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;
}
return sizeof(XError);
/* 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);
}
}
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 )

View 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,

View 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 );

View 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);
}
}

View 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 \

48
exp-ptrcheck/tests/hsg.c Normal file
View File

@ -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;
}

View File

@ -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>

View File

@ -0,0 +1 @@
boringly as expected

View File

@ -0,0 +1,3 @@
prog: hsg
vgopts: --xml=yes --xml-fd=2 --log-file=/dev/null
stderr_filter: ../../memcheck/tests/filter_xml

View 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;
}

View 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)