|
From: <sv...@va...> - 2006-12-16 00:54:16
|
Author: njn
Date: 2006-12-16 00:54:12 +0000 (Sat, 16 Dec 2006)
New Revision: 6402
Log:
Completely overhauled the internals of Memcheck's error handling. All th=
e
different error kinds were reusing the same struct for storing their
details. Each one used some but not all the fields, and the AddrInfo was
similar, and it was very confusing.
So I changed MC_Error and AddrInfo to be tagged unions, like Vex's IRExpr=
and
IRStmt types. The resulting code is a little more verbose but much easie=
r
to understand. I also split up several error kinds, which also made thin=
gs
simpler. The user-visible behaviour is identical except for a couple of
very minor things that I've documented in the NEWS file for the 3.3.0
release.
Ideally I'd get rid of the Addr and Char* fields in the core Error type,
which are not always used, and do them similarly within tools. But that
would require changing the core/tool interface, so I'm leaving it for the
moment.
Modified:
trunk/NEWS
trunk/coregrind/m_errormgr.c
trunk/glibc-2.2.supp
trunk/glibc-2.3.supp
trunk/glibc-2.4.supp
trunk/glibc-2.5.supp
trunk/memcheck/docs/mc-manual.xml
trunk/memcheck/mc_include.h
trunk/memcheck/mc_leakcheck.c
trunk/memcheck/mc_main.c
trunk/memcheck/mc_malloc_wrappers.c
trunk/memcheck/mc_replace_strmem.c
trunk/memcheck/tests/supp_unknown.supp
trunk/xfree-3.supp
trunk/xfree-4.supp
Modified: trunk/NEWS
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/NEWS 2006-12-15 04:37:25 UTC (rev 6401)
+++ trunk/NEWS 2006-12-16 00:54:12 UTC (rev 6402)
@@ -1,4 +1,25 @@
+Release 3.2.0 (XX XXX 2007)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+3.2.0 is a feature release with ...
=20
+XXX:
+* Note in NEWS that behaviour of GET_VBITS and SET_BBITS have changed --
+ they no longer issue addressability errors if either array is partiall=
y
+ unaddressable, they just return 3. Also, SET_VBITS doesn't report
+ definedness errors if any of the V bits are undefined.
+
+Other user-visible changes:
+
+- A new suppression kind has been introduced: "Jump". This is for
+ suppressing jump-to-invalid-address errors. Previously you had to use=
an
+ "Addr1" suppression, which didn't make much sense.
+
+- The behaviour of Memcheck's client requests VALGRIND_GET_VBITS and
+ VALGRIND_SET_VBITS have changed slightly. They no longer issue
+ addressability errors -- if either array is partially unaddressable,
+ they just return 3 (as before). Also, SET_VBITS doesn't report
+ definedness errors if any of the V bits are undefined.
+
Release 3.2.1 (16 Sept 2006)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3.2.1 adds x86/amd64 support for all SSE3 instructions except monitor
Modified: trunk/coregrind/m_errormgr.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_errormgr.c 2006-12-15 04:37:25 UTC (rev 6401)
+++ trunk/coregrind/m_errormgr.c 2006-12-16 00:54:12 UTC (rev 6402)
@@ -101,9 +101,6 @@
/*--- Error type ---*/
/*------------------------------------------------------------*/
=20
-/* Note: it is imperative this doesn't overlap with (0..) at all, as too=
ls
- * effectively extend it by defining their own enums in the (0..) range.=
*/
-
/* Errors. Extensible (via the 'extra' field). Tools can use a normal
enum (with element values in the normal range (0..)) for 'ekind'.=20
Functions for getting/setting the tool-relevant fields are in
Modified: trunk/glibc-2.2.supp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/glibc-2.2.supp 2006-12-15 04:37:25 UTC (rev 6401)
+++ trunk/glibc-2.2.supp 2006-12-16 00:54:12 UTC (rev 6402)
@@ -16,7 +16,7 @@
#
# For Memcheck, the supp_kinds are:
#
-# Param Value1 Value2 Value4 Value8 Value16
+# Param Value1 Value2 Value4 Value8 Value16 Jump
# Free Addr1 Addr2 Addr4 Addr8 Addr16
# Cond (previously known as Value0)
#
Modified: trunk/glibc-2.3.supp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/glibc-2.3.supp 2006-12-15 04:37:25 UTC (rev 6401)
+++ trunk/glibc-2.3.supp 2006-12-16 00:54:12 UTC (rev 6402)
@@ -16,7 +16,7 @@
#
# For Memcheck, the supp_kinds are:
#
-# Param Value1 Value2 Value4 Value8 Value16
+# Param Value1 Value2 Value4 Value8 Value16 Jump
# Free Addr1 Addr2 Addr4 Addr8 Addr16
# Cond (previously known as Value0)
#
Modified: trunk/glibc-2.4.supp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/glibc-2.4.supp 2006-12-15 04:37:25 UTC (rev 6401)
+++ trunk/glibc-2.4.supp 2006-12-16 00:54:12 UTC (rev 6402)
@@ -16,7 +16,7 @@
#
# For Memcheck, the supp_kinds are:
#
-# Param Value1 Value2 Value4 Value8 Value16
+# Param Value1 Value2 Value4 Value8 Value16 Jump
# Free Addr1 Addr2 Addr4 Addr8 Addr16
# Cond (previously known as Value0)
#
Modified: trunk/glibc-2.5.supp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/glibc-2.5.supp 2006-12-15 04:37:25 UTC (rev 6401)
+++ trunk/glibc-2.5.supp 2006-12-16 00:54:12 UTC (rev 6402)
@@ -16,7 +16,7 @@
#
# For Memcheck, the supp_kinds are:
#
-# Param Value1 Value2 Value4 Value8 Value16
+# Param Value1 Value2 Value4 Value8 Value16 Jump
# Free Addr1 Addr2 Addr4 Addr8 Addr16
# Cond (previously known as Value0)
#
Modified: trunk/memcheck/docs/mc-manual.xml
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/docs/mc-manual.xml 2006-12-15 04:37:25 UTC (rev 6401)
+++ trunk/memcheck/docs/mc-manual.xml 2006-12-16 00:54:12 UTC (rev 6402)
@@ -635,6 +635,11 @@
</listitem>
=20
<listitem>
+ <para>Or: <varname>Jump</varname>, meaning an
+ jump to an unaddressable location error.</para>
+ </listitem>
+
+ <listitem>
<para>Or: <varname>Param</varname>, meaning an
invalid system call parameter error.</para>
</listitem>
Modified: trunk/memcheck/mc_include.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/mc_include.h 2006-12-15 04:37:25 UTC (rev 6401)
+++ trunk/memcheck/mc_include.h 2006-12-16 00:54:12 UTC (rev 6402)
@@ -56,7 +56,7 @@
struct _MC_Chunk {
struct _MC_Chunk* next;
Addr data; // ptr to actual block
- SizeT size : (sizeof(UWord)*8)-2; // size requested; 30 or =
62 bits
+ SizeT szB : (sizeof(UWord)*8)-2; // size requested; 30 or 6=
2 bits
MC_AllocKind allockind : 2; // which wrapper did the allocation
ExeContext* where; // where it was allocated
}
@@ -120,28 +120,6 @@
=20
=20
/*------------------------------------------------------------*/
-/*--- Errors and suppressions ---*/
-/*------------------------------------------------------------*/
-
-/* Extra info for overlap errors */
-typedef
- struct {
- Addr src;
- Addr dst;
- Int len; // -1 if unused
- }
- OverlapExtra;
-
-extern void MC_(record_free_error) ( ThreadId tid, Addr a );=20
-extern void MC_(record_illegal_mempool_error) ( ThreadId tid, Addr a );
-extern void MC_(record_freemismatch_error) ( ThreadId tid, Addr a,
- MC_Chunk* mc );
-extern Bool MC_(record_leak_error) ( ThreadId tid,=20
- void* leak_extra,
- ExeContext* where,
- Bool print_record );
-
-/*------------------------------------------------------------*/
/*--- Profiling of memory events ---*/
/*------------------------------------------------------------*/
=20
@@ -201,6 +179,21 @@
/*--- Leak checking ---*/
/*------------------------------------------------------------*/
=20
+/* A block is either=20
+ -- Proper-ly reached; a pointer to its start has been found
+ -- Interior-ly reached; only an interior pointer to it has been found
+ -- Unreached; so far, no pointers to any part of it have been found.=20
+ -- IndirectLeak; leaked, but referred to by another leaked block
+*/
+typedef=20
+ enum {=20
+ Unreached =3D0,=20
+ IndirectLeak =3D1,
+ Interior =3D2,=20
+ Proper =3D3
+ }
+ Reachedness;
+
/* For VALGRIND_COUNT_LEAKS client request */
extern SizeT MC_(bytes_leaked);
extern SizeT MC_(bytes_indirect);
@@ -208,9 +201,6 @@
extern SizeT MC_(bytes_reachable);
extern SizeT MC_(bytes_suppressed);
=20
-/* For leak checking */
-extern void MC_(pp_LeakError)(void* extra);
- =20
typedef
enum {
LC_Off,
@@ -219,13 +209,45 @@
}
LeakCheckMode;
=20
+/* A block record, used for generating err msgs. */
+typedef
+ struct _LossRecord {
+ struct _LossRecord* next;
+ /* Where these lost blocks were allocated. */
+ ExeContext* allocated_at;
+ /* Their reachability. */
+ Reachedness loss_mode;
+ /* Number of blocks and total # bytes involved. */
+ SizeT total_bytes;
+ SizeT indirect_bytes;
+ UInt num_blocks;
+ }
+ LossRecord;
+
extern void MC_(do_detect_memory_leaks) (
ThreadId tid, LeakCheckMode mode,
Bool (*is_within_valid_secondary) ( Addr ),
Bool (*is_valid_aligned_word) ( Addr )
);
=20
+extern void MC_(pp_LeakError)(UInt n_this_record, UInt n_total_records,
+ LossRecord* l);
+ =20
+
/*------------------------------------------------------------*/
+/*--- Errors and suppressions ---*/
+/*------------------------------------------------------------*/
+
+extern void MC_(record_free_error) ( ThreadId tid, Addr a );=20
+extern void MC_(record_illegal_mempool_error) ( ThreadId tid, Addr a );
+extern void MC_(record_freemismatch_error) ( ThreadId tid, MC_Chunk* =
mc );
+extern Bool MC_(record_leak_error) ( ThreadId tid,
+ UInt n_this_record,
+ UInt n_total_records,
+ LossRecord* lossRecord,
+ Bool print_record );
+
+/*------------------------------------------------------------*/
/*--- Command line options + defaults ---*/
/*------------------------------------------------------------*/
=20
Modified: trunk/memcheck/mc_leakcheck.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/mc_leakcheck.c 2006-12-15 04:37:25 UTC (rev 6401)
+++ trunk/memcheck/mc_leakcheck.c 2006-12-16 00:54:12 UTC (rev 6402)
@@ -109,21 +109,6 @@
/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
/*------------------------------------------------------------*/
=20
-/* A block is either=20
- -- Proper-ly reached; a pointer to its start has been found
- -- Interior-ly reached; only an interior pointer to it has been found
- -- Unreached; so far, no pointers to any part of it have been found.=20
- -- IndirectLeak; leaked, but referred to by another leaked block
-*/
-typedef=20
- enum {=20
- Unreached =3D0,=20
- IndirectLeak =3D1,
- Interior =3D2,=20
- Proper =3D3
- }
- Reachedness;
-
/* An entry in the mark stack */
typedef=20
struct {
@@ -133,30 +118,6 @@
}=20
MarkStack;
=20
-/* A block record, used for generating err msgs. */
-typedef
- struct _LossRecord {
- struct _LossRecord* next;
- /* Where these lost blocks were allocated. */
- ExeContext* allocated_at;
- /* Their reachability. */
- Reachedness loss_mode;
- /* Number of blocks and total # bytes involved. */
- SizeT total_bytes;
- SizeT indirect_bytes;
- UInt num_blocks;
- }
- LossRecord;
-
-/* The 'extra' struct for leak errors. */
-typedef=20
- struct {
- UInt n_this_record;
- UInt n_total_records;
- LossRecord* lossRecord;
- }
- LeakExtra;
-
/* Find the i such that ptr points at or inside the block described by
shadows[i]. Return -1 if none found. This assumes that shadows[]
has been sorted on the ->data field. */
@@ -175,7 +136,7 @@
for (i =3D 0; i < n_shadows; i++) {
PROF_EVENT(71, "find_shadow_for_OLD(loop)");
a_lo =3D shadows[i]->data;
- a_hi =3D ((Addr)shadows[i]->data) + shadows[i]->size;
+ a_hi =3D ((Addr)shadows[i]->data) + shadows[i]->szB;
if (a_lo <=3D ptr && ptr < a_hi)
return i;
}
@@ -201,14 +162,14 @@
=20
mid =3D (lo + hi) / 2;
a_mid_lo =3D shadows[mid]->data;
- a_mid_hi =3D shadows[mid]->data + shadows[mid]->size;
+ a_mid_hi =3D shadows[mid]->data + shadows[mid]->szB;
/* Extent of block 'mid' is [a_mid_lo .. a_mid_hi).
Special-case zero-sized blocks - treat them as if they had
size 1. Not doing so causes them to not cover any address
range at all and so will never be identified as the target of
any pointer, which causes them to be incorrectly reported as
definitely leaked. */
- if (shadows[mid]->size =3D=3D 0)
+ if (shadows[mid]->szB =3D=3D 0)
a_mid_hi++;
=20
if (ptr < a_mid_lo) {
@@ -243,84 +204,7 @@
static Bool (*lc_is_within_valid_secondary) (Addr addr);
static Bool (*lc_is_valid_aligned_word) (Addr addr);
=20
-static const HChar* str_lossmode ( Reachedness lossmode )
-{
- const HChar *loss =3D "?";
- switch (lossmode) {
- case Unreached: loss =3D "definitely lost"; break;
- case IndirectLeak: loss =3D "indirectly lost"; break;
- case Interior: loss =3D "possibly lost"; break;
- case Proper: loss =3D "still reachable"; break;
- }
- return loss;
-}
=20
-static const HChar* xml_kind ( Reachedness lossmode )
-{
- const HChar *loss =3D "?";
- switch (lossmode) {
- case Unreached: loss =3D "Leak_DefinitelyLost"; break;
- case IndirectLeak: loss =3D "Leak_IndirectlyLost"; break;
- case Interior: loss =3D "Leak_PossiblyLost"; break;
- case Proper: loss =3D "Leak_StillReachable"; break;
- }
- return loss;
-}
-
-
-/* Used for printing leak errors, avoids exposing the LossRecord type (w=
hich
- comes in as void*, requiring a cast. */
-void MC_(pp_LeakError)(void* vextra)
-{
- HChar* xpre =3D VG_(clo_xml) ? " <what>" : "";
- HChar* xpost =3D VG_(clo_xml) ? "</what>" : "";
-
- LeakExtra* extra =3D (LeakExtra*)vextra;
- LossRecord* l =3D extra->lossRecord;
- const Char *loss =3D str_lossmode(l->loss_mode);
-
- if (VG_(clo_xml)) {
- VG_(message)(Vg_UserMsg, " <kind>%t</kind>", xml_kind(l->loss_mod=
e));
- } else {
- VG_(message)(Vg_UserMsg, "");
- }
-
- if (l->indirect_bytes) {
- VG_(message)(Vg_UserMsg,=20
- "%s%,lu (%,lu direct, %,lu indirect) bytes in %,u blocks"
- " are %s in loss record %,u of %,u%s",
- xpre,
- l->total_bytes + l->indirect_bytes,=20
- l->total_bytes, l->indirect_bytes, l->num_blocks,
- loss, extra->n_this_record, extra->n_total_records,
- xpost
- );
- if (VG_(clo_xml)) {
- // Nb: don't put commas in these XML numbers=20
- VG_(message)(Vg_UserMsg, " <leakedbytes>%lu</leakedbytes>",=20
- l->total_bytes + l->indirect_bytes);
- VG_(message)(Vg_UserMsg, " <leakedblocks>%u</leakedblocks>",=20
- l->num_blocks);
- }
- } else {
- VG_(message)(
- Vg_UserMsg,=20
- "%s%,lu bytes in %,u blocks are %s in loss record %,u of %,u%s"=
,
- xpre,
- l->total_bytes, l->num_blocks,
- loss, extra->n_this_record, extra->n_total_records,
- xpost
- );
- if (VG_(clo_xml)) {
- VG_(message)(Vg_UserMsg, " <leakedbytes>%d</leakedbytes>",=20
- l->total_bytes);
- VG_(message)(Vg_UserMsg, " <leakedblocks>%d</leakedblocks>",=20
- l->num_blocks);
- }
- }
- VG_(pp_ExeContext)(l->allocated_at);
-}
-
SizeT MC_(bytes_leaked) =3D 0;
SizeT MC_(bytes_indirect) =3D 0;
SizeT MC_(bytes_dubious) =3D 0;
@@ -356,13 +240,13 @@
tl_assert(sh_no >=3D 0 && sh_no < lc_n_shadows);
tl_assert(ptr >=3D lc_shadows[sh_no]->data);
tl_assert(ptr < lc_shadows[sh_no]->data=20
- + lc_shadows[sh_no]->size
- + (lc_shadows[sh_no]->size=3D=3D0 ? 1 : 0));
+ + lc_shadows[sh_no]->szB
+ + (lc_shadows[sh_no]->szB=3D=3D0 ? 1 : 0));
=20
if (lc_markstack[sh_no].state =3D=3D Unreached) {
if (0)
VG_(printf)("pushing %p-%p\n", lc_shadows[sh_no]->data,=20
- lc_shadows[sh_no]->data + lc_shadows[sh_no]->size);
+ lc_shadows[sh_no]->data + lc_shadows[sh_no]->szB);
=20
tl_assert(lc_markstack[sh_no].next =3D=3D -1);
lc_markstack[sh_no].next =3D lc_markstack_top;
@@ -391,13 +275,13 @@
if (lc_markstack[sh_no].indirect)
VG_(printf)(" clique %d joining clique %d adding %d+%d bytes\n",=20
sh_no, clique,=20
- lc_shadows[sh_no]->size, lc_markstack[sh_no].indirect);
+ lc_shadows[sh_no]->szB, lc_markstack[sh_no].indirect);
else
VG_(printf)(" %d joining %d adding %d\n",=20
- sh_no, clique, lc_shadows[sh_no]->size);
+ sh_no, clique, lc_shadows[sh_no]->szB);
}
=20
- lc_markstack[clique].indirect +=3D lc_shadows[sh_no]->size;
+ lc_markstack[clique].indirect +=3D lc_shadows[sh_no]->szB;
lc_markstack[clique].indirect +=3D lc_markstack[sh_no].indirect;
lc_markstack[sh_no].indirect =3D 0; /* shouldn't matter */
}
@@ -503,7 +387,7 @@
tl_assert(top >=3D 0 && top < lc_n_shadows); =20
tl_assert(lc_markstack[top].state !=3D Unreached);
=20
- lc_scan_memory_WRK(lc_shadows[top]->data, lc_shadows[top]->size, c=
lique);
+ lc_scan_memory_WRK(lc_shadows[top]->data, lc_shadows[top]->szB, cl=
ique);
}
}
=20
@@ -520,7 +404,6 @@
LossRecord* errlist;
LossRecord* p;
Bool is_suppressed;
- LeakExtra leak_extra;
=20
/* Go through and group lost structures into cliques. For each
Unreached block, push it onto the mark stack, and find all the
@@ -530,8 +413,8 @@
pass), then the cliques are merged. */
for (i =3D 0; i < lc_n_shadows; i++) {
if (VG_DEBUG_CLIQUE)
- VG_(printf)("cliques: %d at %p -> %s\n",
- i, lc_shadows[i]->data, str_lossmode(lc_markstack[i].state));
+ VG_(printf)("cliques: %d at %p -> Loss state %d\n",
+ i, lc_shadows[i]->data, lc_markstack[i].state);
if (lc_markstack[i].state !=3D Unreached)
continue;
=20
@@ -578,14 +461,14 @@
}
if (p !=3D NULL) {
p->num_blocks ++;
- p->total_bytes +=3D lc_shadows[i]->size;
+ p->total_bytes +=3D lc_shadows[i]->szB;
p->indirect_bytes +=3D lc_markstack[i].indirect;
} else {
n_lossrecords ++;
p =3D VG_(malloc)(sizeof(LossRecord));
p->loss_mode =3D lc_markstack[i].state;
p->allocated_at =3D where;
- p->total_bytes =3D lc_shadows[i]->size;
+ p->total_bytes =3D lc_shadows[i]->szB;
p->indirect_bytes =3D lc_markstack[i].indirect;
p->num_blocks =3D 1;
p->next =3D errlist;
@@ -619,11 +502,8 @@
// Nb: because VG_(unique_error) does all the error processing
// immediately, and doesn't save the error, leakExtra can be
// stack-allocated.
- leak_extra.n_this_record =3D i+1;
- leak_extra.n_total_records =3D n_lossrecords;
- leak_extra.lossRecord =3D p_min;
is_suppressed =3D=20
- MC_(record_leak_error) ( tid, &leak_extra, p_min->allocated_at,
+ MC_(record_leak_error) ( tid, i+1, n_lossrecords, p_min,
print_record );
=20
if (is_suppressed) {
@@ -659,7 +539,7 @@
Int i;
=20
for(i =3D 0; i < lc_n_shadows; i++) {
- SizeT size =3D lc_shadows[i]->size;
+ SizeT size =3D lc_shadows[i]->szB;
=20
switch(lc_markstack[i].state) {
case Unreached:
@@ -745,8 +625,8 @@
}
=20
/* Possibly invalidate the malloc holding the end of this chunk=
. */
- if (mc->size > 1) {
- m =3D find_shadow_for(mc->data + (mc->size - 1), mallocs, n_=
mallocs);
+ if (mc->szB > 1) {
+ m =3D find_shadow_for(mc->data + (mc->szB - 1), mallocs, n_m=
allocs);
if (m !=3D -1 && malloc_chunk_holds_a_pool_chunk[m] =3D=3D F=
alse) {
tl_assert(*n_shadows > 0);
--(*n_shadows);
@@ -814,7 +694,7 @@
=20
/* Sanity check -- make sure they don't overlap */
for (i =3D 0; i < lc_n_shadows-1; i++) {
- tl_assert( lc_shadows[i]->data + lc_shadows[i]->size
+ tl_assert( lc_shadows[i]->data + lc_shadows[i]->szB
<=3D lc_shadows[i+1]->data );
}
=20
@@ -834,7 +714,7 @@
=20
lc_min_mallocd_addr =3D lc_shadows[0]->data;
lc_max_mallocd_addr =3D lc_shadows[lc_n_shadows-1]->data
- + lc_shadows[lc_n_shadows-1]->size;
+ + lc_shadows[lc_n_shadows-1]->szB;
=20
lc_markstack =3D VG_(malloc)( lc_n_shadows * sizeof(*lc_markstack) );
for (i =3D 0; i < lc_n_shadows; i++) {
Modified: trunk/memcheck/mc_main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/mc_main.c 2006-12-15 04:37:25 UTC (rev 6401)
+++ trunk/memcheck/mc_main.c 2006-12-16 00:54:12 UTC (rev 6402)
@@ -1138,9 +1138,10 @@
// Forward declarations
static void mc_record_address_error ( ThreadId tid, Addr a,
Int size, Bool isWrite );
-static void mc_record_core_mem_error ( ThreadId tid, Bool isUnaddr, Char=
* s );
-static void mc_record_param_error ( ThreadId tid, Addr a, Bool isReg,
- Bool isUnaddr, Char* msg );
+static void mc_record_core_mem_error ( ThreadId tid, Bool isAddrErr, Cha=
r* s );
+static void mc_record_regparam_error ( ThreadId tid, Char* msg );
+static void mc_record_memparam_error ( ThreadId tid, Addr a,
+ Bool isAddrErr, Char* msg );
static void mc_record_jump_error ( ThreadId tid, Addr a );
=20
static
@@ -1303,8 +1304,7 @@
tl_assert(nBits =3D=3D 64 || nBits =3D=3D 32 || nBits =3D=3D 16 || nB=
its =3D=3D 8);
=20
/* Dump vbytes in memory, iterating from least to most significant
- byte. At the same time establish addressibility of the
- location. */
+ byte. At the same time establish addressibility of the location. =
*/
for (i =3D 0; i < szB; i++) {
PROF_EVENT(36, "mc_STOREVn_slow(loop)");
ai =3D a + byte_offset_w(szB, bigendian, i);
@@ -2464,12 +2464,11 @@
if (!ok) {
switch (part) {
case Vg_CoreSysCall:
- mc_record_param_error ( tid, bad_addr, /*isReg*/False,
- /*isUnaddr*/True, s );
+ mc_record_memparam_error ( tid, bad_addr, /*isAddrErr*/True, s =
);
break;
=20
case Vg_CoreSignal:
- mc_record_core_mem_error( tid, /*isUnaddr*/True, s );
+ mc_record_core_mem_error( tid, /*isAddrErr*/True, s );
break;
=20
default:
@@ -2486,18 +2485,13 @@
MC_ReadResult res =3D is_mem_defined ( base, size, &bad_addr );
=20
if (MC_Ok !=3D res) {
- Bool isUnaddr =3D ( MC_AddrErr =3D=3D res ? True : False );
+ Bool isAddrErr =3D ( MC_AddrErr =3D=3D res ? True : False );
=20
switch (part) {
case Vg_CoreSysCall:
- mc_record_param_error ( tid, bad_addr, /*isReg*/False,
- isUnaddr, s );
+ mc_record_memparam_error ( tid, bad_addr, isAddrErr, s );
break;
=20
- case Vg_CoreClientReq: // Kludge: make this a CoreMemErr
- mc_record_core_mem_error( tid, isUnaddr, s );
- break;
-
/* If we're being asked to jump to a silly address, record an erro=
r=20
message before potentially crashing the entire system. */
case Vg_CoreTranslate:
@@ -2520,8 +2514,8 @@
tl_assert(part =3D=3D Vg_CoreSysCall);
res =3D mc_is_defined_asciiz ( (Addr)str, &bad_addr );
if (MC_Ok !=3D res) {
- Bool isUnaddr =3D ( MC_AddrErr =3D=3D res ? True : False );
- mc_record_param_error ( tid, bad_addr, /*isReg*/False, isUnaddr, s=
);
+ Bool isAddrErr =3D ( MC_AddrErr =3D=3D res ? True : False );
+ mc_record_memparam_error ( tid, bad_addr, isAddrErr, s );
}
}
=20
@@ -2609,104 +2603,188 @@
}
=20
if (bad)
- mc_record_param_error ( tid, 0, /*isReg*/True, /*isUnaddr*/False, =
s );
+ mc_record_regparam_error ( tid, s );
}
=20
=20
/*------------------------------------------------------------*/
-/*--- Error and suppression types ---*/
+/*--- Error types ---*/
/*------------------------------------------------------------*/
=20
+// Different kinds of blocks.
+typedef enum {
+ Block_Mallocd =3D 111,
+ Block_Freed,
+ Block_Mempool,
+ Block_MempoolChunk,
+ Block_UserG
+} BlockKind;
+
+/* ------------------ Addresses -------------------- */
+
/* The classification of a faulting address. */
typedef=20
enum {=20
- Undescribed, // as-yet unclassified
- Stack,=20
- Unknown, // classification yielded nothing useful
- Freed, Mallocd,=20
- UserG, // in a user-defined block
- Mempool, // in a mempool
- Register, // in a register; for Param errors only
+ Addr_Undescribed, // as-yet unclassified
+ Addr_Unknown, // classification yielded nothing useful
+ Addr_Stack, =20
+ Addr_Block,
}
- AddrKind;
+ AddrTag;
=20
-/* Records info about a faulting address. */
typedef
- struct { // Used by:
- AddrKind akind; // ALL
- SizeT blksize; // Freed, Mallocd
- OffT rwoffset; // Freed, Mallocd
- ExeContext* lastchange; // Freed, Mallocd
- ThreadId stack_tid; // Stack
- const Char *desc; // UserG
- Bool maybe_gcc; // True if just below %esp -- could be a g=
cc bug.
- }
+ struct _AddrInfo
AddrInfo;
=20
-typedef=20
- enum {=20
- ParamSupp, // Bad syscall params
- UserSupp, // Errors arising from client-request checks
- CoreMemSupp, // Memory errors in core (pthread ops, signal handl=
ing)
+struct _AddrInfo {
+ AddrTag tag;
+ union {
+ // As-yet unclassified.
+ struct { } Undescribed;
=20
- // Use of invalid values of given size (MemCheck only)
- Value0Supp, Value1Supp, Value2Supp, Value4Supp, Value8Supp, Value1=
6Supp,
+ // On a stack.
+ struct {
+ ThreadId tid; // Which thread's stack?
+ } Stack;
=20
- // Invalid read/write attempt at given size
- Addr1Supp, Addr2Supp, Addr4Supp, Addr8Supp, Addr16Supp,
+ // This covers heap blocks (normal and from mempools) and user-def=
ined
+ // blocks.
+ struct {
+ BlockKind block_kind;
+ Char* block_desc; // "block", "mempool" or user-define=
d
+ SizeT block_szB;
+ OffT rwoffset;
+ ExeContext* lastchange;
+ } Block;
=20
- FreeSupp, // Invalid or mismatching free
- OverlapSupp, // Overlapping blocks in memcpy(), strcpy(), etc
- LeakSupp, // Something to be suppressed in a leak check.
- MempoolSupp, // Memory pool suppression.
- }=20
- MC_SuppKind;
+ // Classification yielded nothing useful.
+ struct { } Unknown;
=20
+ } Addr;
+};
+
+/* ------------------ Errors ----------------------- */
+
/* What kind of error it is. */
typedef=20
- enum { ValueErr,
- CoreMemErr, // Error in core op (pthread, signals) or client=
req
- AddrErr,=20
- ParamErr, UserErr, /* behaves like an anonymous ParamErr */
- FreeErr, FreeMismatchErr,
- OverlapErr,
- LeakErr,
- IllegalMempoolErr,
+ enum {=20
+ Err_Value,
+ Err_Cond,
+ Err_CoreMem,
+ Err_Addr,=20
+ Err_Jump,=20
+ Err_RegParam,
+ Err_MemParam,
+ Err_User,
+ Err_Free,
+ Err_FreeMismatch,
+ Err_Overlap,
+ Err_Leak,
+ Err_IllegalMempool,
}
- MC_ErrorKind;
+ MC_ErrorTag;
=20
-/* What kind of memory access is involved in the error? */
-typedef
- enum { ReadAxs, WriteAxs, ExecAxs }
- AxsKind;
=20
-/* Extra context for memory errors */
-typedef
- struct { // Used by:
- AxsKind axskind; // AddrErr
- Int size; // AddrErr, ValueErr
- AddrInfo addrinfo; // {Addr,Free,FreeMismatch,Param,User}Err
- Bool isUnaddr; // {CoreMem,Param,User}Err
- }
- MC_Error;
+typedef struct _MC_Error MC_Error;
=20
+struct _MC_Error {
+ // Nb: we don't need the tag here, as it's stored in the Error type! =
Yuk.
+ //MC_ErrorTag tag;
+
+ union {
+ // Use of an undefined value:
+ // - as a pointer in a load or store
+ // - as a jump target
+ struct {
+ SizeT szB; // size of value in bytes
+ } Value;
+
+ // Use of an undefined value in a conditional branch or move.
+ struct {
+ } Cond;
+
+ // Addressability error in core (signal-handling) operation.
+ // It would be good to get rid of this error kind, merge it with
+ // another one somehow.
+ struct {
+ } CoreMem;
+
+ // Use of an unaddressable memory location in a load or store.
+ struct {
+ Bool isWrite; // read or write?
+ SizeT szB; // not used for exec (jump) errors
+ Bool maybe_gcc; // True if just below %esp -- could be a g=
cc bug
+ AddrInfo ai;
+ } Addr;
+
+ // Jump to an unaddressable memory location.
+ struct {
+ AddrInfo ai;
+ } Jump;
+
+ // System call register input contains undefined bytes.
+ struct {
+ } RegParam;
+
+ // System call memory input contains undefined/unaddressable bytes
+ struct {
+ Bool isAddrErr; // Addressability or definedness error?
+ AddrInfo ai;
+ } MemParam;
+
+ // Problem found from a client request like CHECK_MEM_IS_ADDRESSAB=
LE.
+ struct {
+ Bool isAddrErr; // Addressability or definedness error?
+ AddrInfo ai;
+ } User;
+
+ // Program tried to free() something that's not a heap block (this
+ // covers double-frees). */
+ struct {
+ AddrInfo ai;
+ } Free;
+
+ // Program allocates heap block with one function
+ // (malloc/new/new[]/custom) and deallocates with not the matching=
one.
+ struct {
+ AddrInfo ai;
+ } FreeMismatch;
+
+ // Call to strcpy, memcpy, etc, with overlapping blocks.
+ struct {
+ Addr src; // Source block
+ Addr dst; // Destination block
+ Int szB; // Size in bytes; 0 if unused.
+ } Overlap;
+
+ // A memory leak.
+ struct {
+ UInt n_this_record;
+ UInt n_total_records;
+ LossRecord* lossRecord;
+ } Leak;
+
+ // A memory pool error.
+ struct {
+ AddrInfo ai;
+ } IllegalMempool;
+
+ } Err;
+};
+
+
/*------------------------------------------------------------*/
/*--- Printing errors ---*/
/*------------------------------------------------------------*/
=20
-static void mc_pp_AddrInfo ( Addr a, AddrInfo* ai )
+static void mc_pp_AddrInfo ( Addr a, AddrInfo* ai, Bool maybe_gcc )
{
HChar* xpre =3D VG_(clo_xml) ? " <auxwhat>" : " ";
HChar* xpost =3D VG_(clo_xml) ? "</auxwhat>" : "";
=20
- switch (ai->akind) {
- case Stack:=20
- VG_(message)(Vg_UserMsg,=20
- "%sAddress 0x%llx is on thread %d's stack%s",=20
- xpre, (ULong)a, ai->stack_tid, xpost);
- break;
- case Unknown:
- if (ai->maybe_gcc) {
+ switch (ai->tag) {
+ case Addr_Unknown:
+ if (maybe_gcc) {
VG_(message)(Vg_UserMsg,=20
"%sAddress 0x%llx is just below the stack ptr. "
"To suppress, use: --workaround-gcc296-bugs=3Dyes%s",
@@ -2719,200 +2797,246 @@
xpre, (ULong)a, xpost);
}
break;
- case Freed: case Mallocd: case UserG: case Mempool: {
+
+ case Addr_Stack:=20
+ VG_(message)(Vg_UserMsg,=20
+ "%sAddress 0x%llx is on thread %d's stack%s",=20
+ xpre, (ULong)a, ai->Addr.Stack.tid, xpost);
+ break;
+
+ case Addr_Block: {
+ SizeT block_szB =3D ai->Addr.Block.block_szB;
+ OffT rwoffset =3D ai->Addr.Block.rwoffset;
SizeT delta;
const Char* relative;
- const Char* kind;
- if (ai->akind =3D=3D Mempool) {
- kind =3D "mempool";
- } else {
- kind =3D "block";
- }
- if (ai->desc !=3D NULL)
- kind =3D ai->desc;
=20
- if (ai->rwoffset < 0) {
- delta =3D (SizeT)(- ai->rwoffset);
+ if (rwoffset < 0) {
+ delta =3D (SizeT)(-rwoffset);
relative =3D "before";
- } else if (ai->rwoffset >=3D ai->blksize) {
- delta =3D ai->rwoffset - ai->blksize;
+ } else if (rwoffset >=3D block_szB) {
+ delta =3D rwoffset - block_szB;
relative =3D "after";
} else {
- delta =3D ai->rwoffset;
+ delta =3D rwoffset;
relative =3D "inside";
}
VG_(message)(Vg_UserMsg,=20
"%sAddress 0x%lx is %,lu bytes %s a %s of size %,lu %s%s",
xpre,
- a, delta, relative, kind,
- ai->blksize,
- ai->akind=3D=3DMallocd ? "alloc'd"=20
- : ai->akind=3D=3DFreed ? "free'd"=20
- : "client-defined",
+ a, delta, relative, ai->Addr.Block.block_desc,
+ block_szB,
+ ai->Addr.Block.block_kind=3D=3DBlock_Mallocd ? "alloc'd"=20
+ : ai->Addr.Block.block_kind=3D=3DBlock_Freed ? "free'd"=20
+ : "client-defined",
xpost);
- VG_(pp_ExeContext)(ai->lastchange);
+ VG_(pp_ExeContext)(ai->Addr.Block.lastchange);
break;
}
- case Register:
- // print nothing
- tl_assert(0 =3D=3D a);
- break;
+
default:
VG_(tool_panic)("mc_pp_AddrInfo");
}
}
=20
-static void mc_pp_Error ( Error* err )
+static const HChar* str_leak_lossmode ( Reachedness lossmode )
{
- MC_Error* err_extra =3D VG_(get_error_extra)(err);
+ const HChar *loss =3D "?";
+ switch (lossmode) {
+ case Unreached: loss =3D "definitely lost"; break;
+ case IndirectLeak: loss =3D "indirectly lost"; break;
+ case Interior: loss =3D "possibly lost"; break;
+ case Proper: loss =3D "still reachable"; break;
+ }
+ return loss;
+}
=20
+static const HChar* xml_leak_kind ( Reachedness lossmode )
+{
+ const HChar *loss =3D "?";
+ switch (lossmode) {
+ case Unreached: loss =3D "Leak_DefinitelyLost"; break;
+ case IndirectLeak: loss =3D "Leak_IndirectlyLost"; break;
+ case Interior: loss =3D "Leak_PossiblyLost"; break;
+ case Proper: loss =3D "Leak_StillReachable"; break;
+ }
+ return loss;
+}
+
+static void mc_pp_msg( Char* xml_name, Error* err, const HChar* format, =
... )
+{
HChar* xpre =3D VG_(clo_xml) ? " <what>" : "";
HChar* xpost =3D VG_(clo_xml) ? "</what>" : "";
+ Char buf[256];
+ va_list vargs;
=20
+ if (VG_(clo_xml))
+ VG_(message)(Vg_UserMsg, " <kind>%s</kind>", xml_name);
+ // Stick xpre and xpost on the front and back of the format string.
+ VG_(snprintf)(buf, 256, "%s%s%s", xpre, format, xpost);
+ va_start(vargs, format);
+ VG_(vmessage) ( Vg_UserMsg, buf, vargs );
+ va_end(vargs);
+ VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+}
+
+static void mc_pp_Error ( Error* err )
+{
+ MC_Error* extra =3D VG_(get_error_extra)(err);
+
switch (VG_(get_error_kind)(err)) {
- case CoreMemErr: {
- Char* s =3D ( err_extra->isUnaddr ? "unaddressable" : "uninitia=
lised" );
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>CoreMemError</kind>");
- /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
- VG_(message)(Vg_UserMsg, "%s%s contains %s byte(s)%s",=20
- xpre, VG_(get_error_string)(err), s, xpost);
-
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+ case Err_CoreMem: {
+ /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
+ /* As of 2006-Dec-14, it's caused by unaddressable bytes in a
+ signal handler frame. --njn */
+ mc_pp_msg("CoreMemError", err,
+ "%s contains unaddressable byte(s)",=20
+ VG_(get_error_string)(err));
break;
- =20
}=20
=20
- case ValueErr:
- if (err_extra->size =3D=3D 0) {
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>UninitCondition</kind>"=
);
- VG_(message)(Vg_UserMsg, "%sConditional jump or move depends=
"
- " on uninitialised value(s)%s",=20
- xpre, xpost);
- } else {
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>UninitValue</kind>");
- VG_(message)(Vg_UserMsg,
- "%sUse of uninitialised value of size %d%s",
- xpre, err_extra->size, xpost);
- }
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+ case Err_Value:
+ mc_pp_msg("UninitValue", err,
+ "Use of uninitialised value of size %d",
+ extra->Err.Value.szB);
break;
=20
- case ParamErr: {
- Bool isReg =3D ( Register =3D=3D err_extra->addrinfo.akind );
- Char* s1 =3D ( isReg ? "contains" : "points to" );
- Char* s2 =3D ( err_extra->isUnaddr ? "unaddressable" : "uniniti=
alised" );
- if (isReg) tl_assert(!err_extra->isUnaddr);
+ case Err_Cond:
+ mc_pp_msg("UninitCondition", err,
+ "Conditional jump or move depends"
+ " on uninitialised value(s)");
+ break;
=20
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>SyscallParam</kind>");
- VG_(message)(Vg_UserMsg, "%sSyscall param %s %s %s byte(s)%s",
- xpre, VG_(get_error_string)(err), s1, s2, xpost);
+ case Err_RegParam:
+ mc_pp_msg("SyscallParam", err,
+ "Syscall param %s contains uninitialised byte(s)",
+ VG_(get_error_string)(err));
+ break;
=20
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
- mc_pp_AddrInfo(VG_(get_error_address)(err), &err_extra->addrinf=
o);
+ case Err_MemParam:
+ mc_pp_msg("SyscallParam", err,
+ "Syscall param %s points to %s byte(s)",
+ VG_(get_error_string)(err),
+ ( extra->Err.MemParam.isAddrErr=20
+ ? "unaddressable" : "uninitialised" ));
+ mc_pp_AddrInfo(VG_(get_error_address)(err),
+ &extra->Err.MemParam.ai, False);
break;
- }
- case UserErr: {
- Char* s =3D ( err_extra->isUnaddr ? "Unaddressable" : "Uninitia=
lised" );
=20
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>ClientCheck</kind>");
- VG_(message)(Vg_UserMsg,=20
- "%s%s byte(s) found during client check request%s",=20
- xpre, s, xpost);
+ case Err_User:
+ mc_pp_msg("ClientCheck", err,
+ "%s byte(s) found during client check request",=20
+ ( extra->Err.User.isAddrErr
+ ? "Unaddressable" : "Uninitialised" ));
+ mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.User.ai=
,
+ False);
+ break;
=20
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
- mc_pp_AddrInfo(VG_(get_error_address)(err), &err_extra->addrinf=
o);
+ case Err_Free:
+ mc_pp_msg("InvalidFree", err,
+ "Invalid free() / delete / delete[]");
+ mc_pp_AddrInfo(VG_(get_error_address)(err),
+ &extra->Err.Free.ai, False);
break;
- }
- case FreeErr:
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>InvalidFree</kind>");
- VG_(message)(Vg_UserMsg,=20
- "%sInvalid free() / delete / delete[]%s",
- xpre, xpost);
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
- mc_pp_AddrInfo(VG_(get_error_address)(err), &err_extra->addrinf=
o);
- break;
=20
- case FreeMismatchErr:
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>MismatchedFree</kind>");
- VG_(message)(Vg_UserMsg,=20
- "%sMismatched free() / delete / delete []%s",
- xpre, xpost);
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
- mc_pp_AddrInfo(VG_(get_error_address)(err), &err_extra->addrinf=
o);
+ case Err_FreeMismatch:
+ mc_pp_msg("MismatchedFree", err,
+ "Mismatched free() / delete / delete []");
+ mc_pp_AddrInfo(VG_(get_error_address)(err),
+ &extra->Err.FreeMismatch.ai, False);
break;
=20
- case AddrErr:
- switch (err_extra->axskind) {
- case ReadAxs:
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>InvalidRead</kind>")=
;
- VG_(message)(Vg_UserMsg,
- "%sInvalid read of size %d%s",=20
- xpre, err_extra->size, xpost );=20
- break;
- case WriteAxs:
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>InvalidWrite</kind>"=
);
- VG_(message)(Vg_UserMsg,=20
- "%sInvalid write of size %d%s",=20
- xpre, err_extra->size, xpost );=20
- break;
- case ExecAxs:
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>InvalidJump</kind>")=
;
- VG_(message)(Vg_UserMsg,=20
- "%sJump to the invalid address "
- "stated on the next line%s",
- xpre, xpost);
- break;
- default:=20
- VG_(tool_panic)("mc_pp_Error(axskind)");
+ case Err_Addr:
+ if (extra->Err.Addr.isWrite) {
+ mc_pp_msg("InvalidWrite", err,
+ "Invalid write of size %d",=20
+ extra->Err.Addr.szB);=20
+ } else {
+ mc_pp_msg("InvalidRead", err,
+ "Invalid read of size %d",=20
+ extra->Err.Addr.szB);=20
}
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
- mc_pp_AddrInfo(VG_(get_error_address)(err), &err_extra->addrinf=
o);
+ mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.Addr.ai=
,
+ extra->Err.Addr.maybe_gcc);
break;
=20
- case OverlapErr: {
- OverlapExtra* ov_extra =3D (OverlapExtra*)VG_(get_error_extra)(=
err);
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>Overlap</kind>");
- if (ov_extra->len =3D=3D -1)
- VG_(message)(Vg_UserMsg,
- "%sSource and destination overlap in %s(%p, %p)=
%s",
- xpre,
- VG_(get_error_string)(err),
- ov_extra->dst, ov_extra->src,
- xpost);
+ case Err_Jump:
+ mc_pp_msg("InvalidJump", err,
+ "Jump to the invalid address stated on the next line"=
);
+ mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.Jump.ai=
,
+ False);
+ break;
+
+ case Err_Overlap:
+ if (extra->Err.Overlap.szB =3D=3D 0)
+ mc_pp_msg("Overlap", err,
+ "Source and destination overlap in %s(%p, %p)",
+ VG_(get_error_string)(err),
+ extra->Err.Overlap.dst, extra->Err.Overlap.src);
else
- VG_(message)(Vg_UserMsg,
- "%sSource and destination overlap in %s(%p, %p,=
%d)%s",
- xpre,
- VG_(get_error_string)(err),
- ov_extra->dst, ov_extra->src, ov_extra->len,
- xpost);
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
+ mc_pp_msg("Overlap", err,
+ "Source and destination overlap in %s(%p, %p, %d)"=
,
+ VG_(get_error_string)(err),
+ extra->Err.Overlap.dst, extra->Err.Overlap.src,
+ extra->Err.Overlap.szB);
break;
- }
- case LeakErr: {
- MC_(pp_LeakError)(err_extra);
+
+ case Err_IllegalMempool:
+ mc_pp_msg("InvalidMemPool", err,
+ "Illegal memory pool address");
+ mc_pp_AddrInfo(VG_(get_error_address)(err),
+ &extra->Err.IllegalMempool.ai, False);
break;
- }
=20
- case IllegalMempoolErr:
- if (VG_(clo_xml))
- VG_(message)(Vg_UserMsg, " <kind>InvalidMemPool</kind>");
- VG_(message)(Vg_UserMsg, "%sIllegal memory pool address%s",
- xpre, xpost);
- VG_(pp_ExeContext)( VG_(get_error_where)(err) );
- mc_pp_AddrInfo(VG_(get_error_address)(err), &err_extra->addrinf=
o);
+ case Err_Leak: {
+ HChar* xpre =3D VG_(clo_xml) ? " <what>" : "";
+ HChar* xpost =3D VG_(clo_xml) ? "</what>" : "";
+ UInt n_this_record =3D extra->Err.Leak.n_this_record;
+ UInt n_total_records =3D extra->Err.Leak.n_total_records=
;
+ LossRecord* l =3D extra->Err.Leak.lossRecord;
+
+ if (VG_(clo_xml)) {
+ VG_(message)(Vg_UserMsg, " <kind>%t</kind>",
+ xml_leak_kind(l->loss_mode));
+ } else {
+ VG_(message)(Vg_UserMsg, "");
+ }
+
+ if (l->indirect_bytes) {
+ VG_(message)(Vg_UserMsg,=20
+ "%s%,lu (%,lu direct, %,lu indirect) bytes in %,u blocks"
+ " are %s in loss record %,u of %,u%s",
+ xpre,
+ l->total_bytes + l->indirect_bytes,=20
+ l->total_bytes, l->indirect_bytes, l->num_blocks,
+ str_leak_lossmode(l->loss_mode), n_this_record, n_total_r=
ecords,
+ xpost
+ );
+ if (VG_(clo_xml)) {
+ // Nb: don't put commas in these XML numbers=20
+ VG_(message)(Vg_UserMsg, " <leakedbytes>%lu</leakedbytes=
>",=20
+ l->total_bytes + l->indirect_byt=
es);
+ VG_(message)(Vg_UserMsg, " <leakedblocks>%u</leakedblock=
s>",=20
+ l->num_blocks);
+ }
+ } else {
+ VG_(message)(
+ Vg_UserMsg,=20
+ "%s%,lu bytes in %,u blocks are %s in loss record %,u of =
%,u%s",
+ xpre,
+ l->total_bytes, l->num_blocks,
+ str_leak_lossmode(l->loss_mode), n_this_record, n_total_r=
ecords,
+ xpost
+ );
+ if (VG_(clo_xml)) {
+ VG_(message)(Vg_UserMsg, " <leakedbytes>%d</leakedbytes>=
",=20
+ l->total_bytes);
+ VG_(message)(Vg_UserMsg, " <leakedblocks>%d</leakedblock=
s>",=20
+ l->num_blocks);
+ }
+ }
+ VG_(pp_ExeContext)(l->allocated_at);
break;
+ }
=20
default:=20
VG_(printf)("Error:\n unknown Memcheck error code %d\n",
@@ -2939,25 +3063,12 @@
return False;
}
=20
-static void mc_clear_MC_Error ( MC_Error* err_extra )
-{
- err_extra->axskind =3D ReadAxs;
- err_extra->size =3D 0;
- err_extra->isUnaddr =3D True;
- err_extra->addrinfo.akind =3D Unknown;
- err_extra->addrinfo.blksize =3D 0;
- err_extra->addrinfo.rwoffset =3D 0;
- err_extra->addrinfo.lastchange =3D NULL;
- err_extra->addrinfo.stack_tid =3D VG_INVALID_THREADID;
- err_extra->addrinfo.maybe_gcc =3D False;
- err_extra->addrinfo.desc =3D NULL;
-}
+/* --- Called from generated and non-generated code --- */
=20
-/* This one called from generated code and non-generated code. */
-static void mc_record_address_error ( ThreadId tid, Addr a, Int size,
+static void mc_record_address_error ( ThreadId tid, Addr a, Int szB,
Bool isWrite )
{
- MC_Error err_extra;
+ MC_Error extra;
Bool just_below_esp;
=20
if (in_ignored_range(a))=20
@@ -2970,14 +3081,14 @@
best we can do is to 'act normal' and mark the A bits in the
normal way as noaccess, but then hide any reads from that page
that get reported here. */
- if ((!isWrite) && a >=3D 0 && a < 4096 && a+size <=3D 4096)=20
+ if ((!isWrite) && a >=3D 0 && a < 4096 && a+szB <=3D 4096)=20
return;
=20
/* Appalling AIX hack. It suppresses reads done by glink
fragments. Getting rid of this would require figuring out
somehow where the referenced data areas are (and their
sizes). */
- if ((!isWrite) && size =3D=3D sizeof(Word)) {=20
+ if ((!isWrite) && szB =3D=3D sizeof(Word)) {=20
UInt i1, i2;
UInt* pc =3D (UInt*)VG_(get_IP)(tid);
if (sizeof(Word) =3D=3D 4) {
@@ -2999,225 +3110,191 @@
if (MC_(clo_workaround_gcc296_bugs) && just_below_esp)
return;
=20
- mc_clear_MC_Error( &err_extra );
- err_extra.axskind =3D isWrite ? WriteAxs : ReadAxs;
- err_extra.size =3D size;
- err_extra.addrinfo.akind =3D Undescribed;
- err_extra.addrinfo.maybe_gcc =3D just_below_esp;
- VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
+ extra.Err.Addr.isWrite =3D isWrite;
+ extra.Err.Addr.szB =3D szB;
+ extra.Err.Addr.maybe_gcc =3D just_below_esp;
+ extra.Err.Addr.ai.tag =3D Addr_Undescribed;
+ VG_(maybe_record_error)( tid, Err_Addr, a, /*s*/NULL, &extra );
}
=20
-/* These ones are called from non-generated code */
+static void mc_record_value_error ( ThreadId tid, Int szB )
+{
+ MC_Error extra;
+ tl_assert(MC_(clo_undef_value_errors));
+ extra.Err.Value.szB =3D szB;
+ VG_(maybe_record_error)( tid, Err_Value, /*addr*/0, /*s*/NULL, &extra=
);
+}
=20
+static void mc_record_cond_error ( ThreadId tid )
+{
+ tl_assert(MC_(clo_undef_value_errors));
+ VG_(maybe_record_error)( tid, Err_Cond, /*addr*/0, /*s*/NULL, /*extra=
*/NULL);
+}
+
+/* --- Called from non-generated code --- */
+
/* This is for memory errors in pthread functions, as opposed to pthread=
API
errors which are found by the core. */
-static void mc_record_core_mem_error ( ThreadId tid, Bool isUnaddr, Char=
* msg )
+static void mc_record_core_mem_error ( ThreadId tid, Bool isAddrErr, Cha=
r* msg )
{
- MC_Error err_extra;
+ VG_(maybe_record_error)( tid, Err_CoreMem, /*addr*/0, msg, /*extra*/N=
ULL );
+}
=20
- mc_clear_MC_Error( &err_extra );
- err_extra.isUnaddr =3D isUnaddr;
- VG_(maybe_record_error)( tid, CoreMemErr, /*addr*/0, msg, &err_extra =
);
+static void mc_record_regparam_error ( ThreadId tid, Char* msg )
+{
+ tl_assert(VG_INVALID_THREADID !=3D tid);
+ VG_(maybe_record_error)( tid, Err_RegParam, /*addr*/0, msg, /*extra*/=
NULL );
}
=20
-// Three kinds of param errors:
-// - register arg contains undefined bytes
-// - memory arg is unaddressable
-// - memory arg contains undefined bytes
-// 'isReg' and 'isUnaddr' dictate which of these it is.
-static void mc_record_param_error ( ThreadId tid, Addr a, Bool isReg,
- Bool isUnaddr, Char* msg )
+static void mc_record_memparam_error ( ThreadId tid, Addr a,=20
+ Bool isAddrErr, Char* msg )
{
- MC_Error err_extra;
-
- if (!isUnaddr) tl_assert(MC_(clo_undef_value_errors));
+ MC_Error extra;
tl_assert(VG_INVALID_THREADID !=3D tid);
- if (isUnaddr) tl_assert(!isReg); // unaddressable register is impo=
ssible
- mc_clear_MC_Error( &err_extra );
- err_extra.addrinfo.akind =3D ( isReg ? Register : Undescribed );
- err_extra.isUnaddr =3D isUnaddr;
- VG_(maybe_record_error)( tid, ParamErr, a, msg, &err_extra );
+ if (!isAddrErr)=20
+ tl_assert(MC_(clo_undef_value_errors));
+ extra.Err.MemParam.isAddrErr =3D isAddrErr;
+ extra.Err.MemParam.ai.tag =3D Addr_Undescribed;
+ VG_(maybe_record_error)( tid, Err_MemParam, a, msg, &extra );
}
=20
static void mc_record_jump_error ( ThreadId tid, Addr a )
{
- MC_Error err_extra;
-
+ MC_Error extra;
tl_assert(VG_INVALID_THREADID !=3D tid);
- mc_clear_MC_Error( &err_extra );
- err_extra.axskind =3D ExecAxs;
- err_extra.size =3D 1; // size only used for suppressions
- err_extra.addrinfo.akind =3D Undescribed;
- VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
+ extra.Err.Jump.ai.tag =3D Addr_Undescribed;
+ VG_(maybe_record_error)( tid, Err_Jump, a, /*s*/NULL, &extra );
}
=20
void MC_(record_free_error) ( ThreadId tid, Addr a )=20
{
- MC_Error err_extra;
-
+ MC_Error extra;
tl_assert(VG_INVALID_THREADID !=3D tid);
- mc_clear_MC_Error( &err_extra );
- err_extra.addrinfo.akind =3D Undescribed;
- VG_(maybe_record_error)( tid, FreeErr, a, /*s*/NULL, &err_extra );
+ extra.Err.Free.ai.tag =3D Addr_Undescribed;
+ VG_(maybe_record_error)( tid, Err_Free, a, /*s*/NULL, &extra );
}
=20
-void MC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )=20
+void MC_(record_freemismatch_error) ( ThreadId tid, MC_Chunk* mc )
{
- MC_Error err_extra;
-
+ MC_Error extra;
+ AddrInfo* ai =3D &extra.Err.FreeMismatch.ai;
tl_assert(VG_INVALID_THREADID !=3D tid);
- mc_clear_MC_Error( &err_extra );
- err_extra.addrinfo.akind =3D Undescribed;
- VG_(maybe_record_error)( tid, IllegalMempoolErr, a, /*s*/NULL, &err_e=
xtra );
+ ai->tag =3D Addr_Block;
+ ai->Addr.Block.block_kind =3D Block_Mallocd; // Nb: Not 'Block_Freed=
'
+ ai->Addr.Block.block_desc =3D "block";
+ ai->Addr.Block.block_szB =3D mc->szB;
+ ai->Addr.Block.rwoffset =3D 0;
+ ai->Addr.Block.lastchange =3D mc->where;
+ VG_(maybe_record_error)( tid, Err_FreeMismatch, mc->data, /*s*/NULL,
+ &extra );
}
=20
-void MC_(record_freemismatch_error) ( ThreadId tid, Addr a, MC_Chunk* mc=
)
+void MC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )=20
{
- MC_Error err_extra;
- AddrInfo* ai;
-
+ MC_Error extra;
tl_assert(VG_INVALID_THREADID !=3D tid);
- mc_clear_MC_Error( &err_extra );
- ai =3D &err_extra.addrinfo;
- ai->akind =3D Mallocd; // Nb: not 'Freed'
- ai->blksize =3D mc->size;
- ai->rwoffset =3D (Int)a - (Int)mc->data;
- ai->lastchange =3D mc->where;
- VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_ext=
ra );
+ extra.Err.IllegalMempool.ai.tag =3D Addr_Undescribed;
+ VG_(maybe_record_error)( tid, Err_IllegalMempool, a, /*s*/NULL, &extr=
a );
}
=20
-static void mc_record_overlap_error ( ThreadId tid,=20
- Char* function, OverlapExtra* ov_e=
xtra )
+static void mc_record_overlap_error ( ThreadId tid, Char* function,
+ Addr src, Addr dst, SizeT szB )
{
+ MC_Error extra;
+ tl_assert(VG_INVALID_THREADID !=3D tid);
+ extra.Err.Overlap.src =3D src;
+ extra.Err.Overlap.dst =3D dst;
+ extra.Err.Overlap.szB =3D szB;
VG_(maybe_record_error)(=20
- tid, OverlapErr, /*addr*/0, /*s*/function, ov_extra );
+ tid, Err_Overlap, /*addr*/0, /*s*/function, &extra );
}
=20
-Bool MC_(record_leak_error) ( ThreadId tid, /*LeakExtra*/void* leak_extr=
a,
- ExeContext* where, Bool print_record )
+Bool MC_(record_leak_error) ( ThreadId tid, UInt n_this_record,
+ UInt n_total_records, LossRecord* lossReco=
rd,
+ Bool print_record )
{
+ MC_Error extra;
+ extra.Err.Leak.n_this_record =3D n_this_record;
+ extra.Err.Leak.n_total_records =3D n_total_records;
+ extra.Err.Leak.lossRecord =3D lossRecord;
return
- VG_(unique_error) ( tid, LeakErr, /*Addr*/0, /*s*/NULL,
- /*extra*/leak_extra, where, print_record,
+ VG_(unique_error) ( tid, Err_Leak, /*Addr*/0, /*s*/NULL, &extra,
+ lossRecord->allocated_at, print_record,
/*allow_GDB_attach*/False, /*count_error*/False )=
;
}
=20
-
-/* Creates a copy of the 'extra' part, updates the copy with address inf=
o if
- necessary, and returns the copy. */
-/* This one called from generated code and non-generated code. */
-static void mc_record_value_error ( ThreadId tid, Int size )
+static void mc_record_user_error ( ThreadId tid, Addr a, Bool isAddrErr =
)
{
- MC_Error err_extra;
+ MC_Error extra;
=20
- tl_assert(MC_(clo_undef_value_errors));
- mc_clear_MC_Error( &err_extra );
- err_extra.size =3D size;
- err_extra.isUnaddr =3D False;
- VG_(maybe_record_error)( tid, ValueErr, /*addr*/0, /*s*/NULL, &err_ex=
tra );
-}
-
-/* This called from non-generated code */
-
-static void mc_record_user_error ( ThreadId tid, Addr a, Bool isWrite,
- Bool isUnaddr )
-{
- MC_Error err_extra;
-
tl_assert(VG_INVALID_THREADID !=3D tid);
- mc_clear_MC_Error( &err_extra );
- err_extra.addrinfo.akind =3D Undescribed;
- err_extra.isUnaddr =3D isUnaddr;
- VG_(maybe_record_error)( tid, UserErr, a, /*s*/NULL, &err_extra );
+ extra.Err.User.isAddrErr =3D isAddrErr;
+ extra.Err.User.ai.tag =3D Addr_Undescribed;
+ VG_(maybe_record_error)( tid, Err_User, a, /*s*/NULL, &extra );
}
=20
-__attribute__ ((unused))
-static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
-{
- if (ai1->akind !=3D Undescribed=20
- && ai2->akind !=3D Undescribed
- && ai1->akind !=3D ai2->akind)=20
- return False;
- if (ai1->akind =3D=3D...
[truncated message content] |