|
From: <sv...@va...> - 2005-09-26 10:05:45
|
Author: sewardj
Date: 2005-09-26 11:05:38 +0100 (Mon, 26 Sep 2005)
New Revision: 4782
Log:
Make the leak checker work properly again: don't use client heap
sections as sources of roots. This requires aspacem to keep track of
which anonymous client mappings 'belong' to m_mallocfree.
Modified:
branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c
branches/ASPACEM/coregrind/m_mallocfree.c
branches/ASPACEM/include/pub_tool_aspacemgr.h
branches/ASPACEM/memcheck/mac_leakcheck.c
Modified: branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.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
--- branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c 2005-09-26 01:55:1=
4 UTC (rev 4781)
+++ branches/ASPACEM/coregrind/m_aspacemgr/aspacemgr.c 2005-09-26 10:05:3=
8 UTC (rev 4782)
@@ -512,47 +512,50 @@
case SkAnonC: case SkAnonV:
VG_(debugLog)(
logLevel, "aspacem",
- "%3d: %s %010llx-%010llx %s %c%c%c%c\n",
+ "%3d: %s %010llx-%010llx %s %c%c%c%c%c\n",
segNo, show_SegKind(seg->kind),
(ULong)seg->start, (ULong)seg->end, len_buf,
seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',=20
- seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-'=20
+ seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',
+ seg->isCH ? 'H' : '-'
);
break;
=20
case SkFileC: case SkFileV:
VG_(debugLog)(
logLevel, "aspacem",
- "%3d: %s %010llx-%010llx %s %c%c%c%c d=3D0x%03llx "
+ "%3d: %s %010llx-%010llx %s %c%c%c%c%c d=3D0x%03llx "
"i=3D%-7lld o=3D%-7lld (%d)\n",
segNo, show_SegKind(seg->kind),
(ULong)seg->start, (ULong)seg->end, len_buf,
seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',=20
seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',=20
+ seg->isCH ? 'H' : '-',
(ULong)seg->dev, (ULong)seg->ino, (Long)seg->offset, seg->fn=
Idx
);
break;
=20
- case SkResvn:
- VG_(debugLog)(
- logLevel, "aspacem",
- "%3d: %s %010llx-%010llx %s %c%c%c%c %s\n",
- segNo, show_SegKind(seg->kind),
- (ULong)seg->start, (ULong)seg->end, len_buf,
- seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',=20
- seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',=20
- show_ShrinkMode(seg->smode)
- );
- break;
+ case SkResvn:
+ VG_(debugLog)(
+ logLevel, "aspacem",
+ "%3d: %s %010llx-%010llx %s %c%c%c%c%c %s\n",
+ segNo, show_SegKind(seg->kind),
+ (ULong)seg->start, (ULong)seg->end, len_buf,
+ seg->hasR ? 'r' : '-', seg->hasW ? 'w' : '-',=20
+ seg->hasX ? 'x' : '-', seg->hasT ? 'T' : '-',=20
+ seg->isCH ? 'H' : '-',
+ show_ShrinkMode(seg->smode)
+ );
+ break;
=20
- default:
- VG_(debugLog)(
- logLevel, "aspacem",
- "%3d: ???? UNKNOWN SEGMENT KIND\n",=20
- segNo=20
- );
- break;
- }
+ default:
+ VG_(debugLog)(
+ logLevel, "aspacem",
+ "%3d: ???? UNKNOWN SEGMENT KIND\n",=20
+ segNo=20
+ );
+ break;
+ }
}
=20
/* Print out the segment array (debugging only!). */
@@ -668,21 +671,25 @@
return=20
s->smode =3D=3D SmFixed
&& s->dev =3D=3D 0 && s->ino =3D=3D 0 && s->offset =3D=3D 0 =
&& s->fnIdx =3D=3D -1=20
- && !s->hasR && !s->hasW && !s->hasX && !s->hasT;
+ && !s->hasR && !s->hasW && !s->hasX && !s->hasT
+ && !s->isCH;
=20
case SkAnonC: case SkAnonV:
return=20
s->smode =3D=3D SmFixed=20
- && s->dev =3D=3D 0 && s->ino =3D=3D 0 && s->offset =3D=3D 0 =
&& s->fnIdx =3D=3D -1;
+ && s->dev =3D=3D 0 && s->ino =3D=3D 0 && s->offset =3D=3D 0 =
&& s->fnIdx =3D=3D -1
+ && (s->kind=3D=3DSkAnonC ? True : !s->isCH);
=20
case SkFileC: case SkFileV:
return=20
- s->smode =3D=3D SmFixed;
+ s->smode =3D=3D SmFixed
+ && !s->isCH;
=20
case SkResvn:=20
return=20
s->dev =3D=3D 0 && s->ino =3D=3D 0 && s->offset =3D=3D 0 && =
s->fnIdx =3D=3D -1=20
- && !s->hasR && !s->hasW && !s->hasX && !s->hasT;
+ && !s->hasR && !s->hasW && !s->hasX && !s->hasT
+ && !s->isCH;
=20
default:
return False;
@@ -713,8 +720,8 @@
return True;
=20
case SkAnonC: case SkAnonV:
- if (s1->hasR =3D=3D s2->hasR=20
- && s1->hasW =3D=3D s2->hasW && s1->hasX =3D=3D s2->hasX) {
+ if (s1->hasR =3D=3D s2->hasR && s1->hasW =3D=3D s2->hasW=20
+ && s1->hasX =3D=3D s2->hasX && s1->isCH =3D=3D s2->isCH) {
s1->end =3D s2->end;
s1->hasT |=3D s2->hasT;
return True;
@@ -1345,7 +1352,7 @@
seg->ino =3D 0;
seg->offset =3D 0;
seg->fnIdx =3D -1;
- seg->hasR =3D seg->hasW =3D seg->hasX =3D seg->hasT =3D False;
+ seg->hasR =3D seg->hasW =3D seg->hasX =3D seg->hasT =3D seg->isCH =3D=
False;
seg->mark =3D False;
}
=20
Modified: branches/ASPACEM/coregrind/m_mallocfree.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
--- branches/ASPACEM/coregrind/m_mallocfree.c 2005-09-26 01:55:14 UTC (re=
v 4781)
+++ branches/ASPACEM/coregrind/m_mallocfree.c 2005-09-26 10:05:38 UTC (re=
v 4782)
@@ -537,6 +537,7 @@
{
Superblock* sb;
SysRes sres;
+ NSegment* seg;
=20
// Take into account admin bytes in the Superblock.
cszB +=3D sizeof(Superblock);
@@ -551,6 +552,12 @@
if (sres.isError)
return 0;
sb =3D (Superblock*)sres.val;
+ // Mark this segment as containing client heap. The leak
+ // checker needs to be able to identify such segments so as not
+ // to use them as sources of roots during leak checks.
+ seg =3D VG_(am_find_nsegment)( (Addr)sb );
+ vg_assert(seg && seg->kind =3D=3D SkAnonC);
+ seg->isCH =3D True;
} else {
// non-client allocation -- abort if it fails
sres =3D VG_(am_mmap_anon_float_valgrind)( cszB );
Modified: branches/ASPACEM/include/pub_tool_aspacemgr.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
--- branches/ASPACEM/include/pub_tool_aspacemgr.h 2005-09-26 01:55:14 UTC=
(rev 4781)
+++ branches/ASPACEM/include/pub_tool_aspacemgr.h 2005-09-26 10:05:38 UTC=
(rev 4782)
@@ -101,7 +101,9 @@
Bool hasW;
Bool hasX;
Bool hasT; // True --> translations have (or MAY have)
- /* Admin */ // been taken from this segment
+ // been taken from this segment
+ Bool isCH; // True --> is client heap (SkAnonC ONLY)
+ /* Admin */
Bool mark;
}
NSegment;
Modified: branches/ASPACEM/memcheck/mac_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
--- branches/ASPACEM/memcheck/mac_leakcheck.c 2005-09-26 01:55:14 UTC (re=
v 4781)
+++ branches/ASPACEM/memcheck/mac_leakcheck.c 2005-09-26 10:05:38 UTC (re=
v 4782)
@@ -117,19 +117,23 @@
-- Unreached; so far, no pointers to any part of it have been found.=20
-- IndirectLeak; leaked, but referred to by another leaked block
*/
-typedef enum {=20
- Unreached,=20
- IndirectLeak,
- Interior,=20
- Proper
- } Reachedness;
+typedef=20
+ enum {=20
+ Unreached,=20
+ IndirectLeak,
+ Interior,=20
+ Proper
+ }
+ Reachedness;
=20
/* An entry in the mark stack */
-typedef struct {
- Int next:30; /* Index of next in mark stack */
- UInt state:2; /* Reachedness */
- SizeT indirect; /* if Unreached, how much is unreachable from here *=
/
-} MarkStack;
+typedef=20
+ struct {
+ Int next:30; /* Index of next in mark stack */
+ UInt state:2; /* Reachedness */
+ SizeT indirect; /* if Unreached, how much is unreachable from here=
*/
+ }=20
+ MarkStack;
=20
/* A block record, used for generating err msgs. */
typedef
@@ -147,11 +151,13 @@
LossRecord;
=20
/* The 'extra' struct for leak errors. */
-typedef struct {
- UInt n_this_record;
- UInt n_total_records;
- LossRecord* lossRecord;
-} LeakExtra;
+typedef=20
+ struct {
+ UInt n_this_record;
+ UInt n_total_records;
+ LossRecord* lossRecord;
+ }
+ LeakExtra;
=20
/* 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[]
@@ -324,7 +330,7 @@
/* If ptr is pointing to a heap-allocated block which hasn't been seen
before, push it onto the mark stack. Clique is the index of the
clique leader; -1 if none. */
-static void _lc_markstack_push(Addr ptr, Int clique)
+static void lc_markstack_push_WRK(Addr ptr, Int clique)
{
Int sh_no;
=20
@@ -353,6 +359,8 @@
lc_markstack_top =3D sh_no;
}
=20
+ tl_assert(clique >=3D -1 && clique < lc_n_shadows);
+
if (clique !=3D -1) {
if (0)
VG_(printf)("mopup: %d: %p is %d\n",=20
@@ -394,7 +402,7 @@
=20
static void lc_markstack_push(Addr ptr)
{
- _lc_markstack_push(ptr, -1);
+ lc_markstack_push_WRK(ptr, -1);
}
=20
/* Return the top of the mark stack, if any. */
@@ -416,7 +424,7 @@
=20
If clique !=3D -1, it means we're gathering leaked memory into
cliques, and clique is the index of the current clique leader. */
-static void _lc_scan_memory(Addr start, SizeT len, Int clique)
+static void lc_scan_memory_WRK(Addr start, SizeT len, Int clique)
{
Addr ptr =3D VG_ROUNDUP(start, sizeof(Addr));
Addr end =3D VG_ROUNDDN(start+len, sizeof(Addr));
@@ -427,7 +435,7 @@
VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &sigmask);
VG_(set_fault_catcher)(scan_all_valid_memory_catcher);
=20
- lc_scanned +=3D end-ptr;
+ // lc_scanned +=3D end-ptr;
=20
if (!VG_(am_is_valid_for_client)(ptr, sizeof(Addr), VKI_PROT_READ))
ptr =3D VG_PGROUNDUP(ptr+1); /* first page bad */
@@ -449,8 +457,9 @@
=20
if (__builtin_setjmp(memscan_jmpbuf) =3D=3D 0) {
if ((*lc_is_valid_aligned_word)(ptr)) {
+ lc_scanned +=3D sizeof(Addr);
addr =3D *(Addr *)ptr;
- _lc_markstack_push(addr, clique);
+ lc_markstack_push_WRK(addr, clique);
} else if (0 && VG_DEBUG_LEAKCHECK)
VG_(printf)("%p not valid\n", ptr);
ptr +=3D sizeof(Addr);
@@ -470,7 +479,7 @@
=20
static void lc_scan_memory(Addr start, SizeT len)
{
- _lc_scan_memory(start, len, -1);
+ lc_scan_memory_WRK(start, len, -1);
}
=20
/* Process the mark stack until empty. If mopup is true, then we're
@@ -484,7 +493,7 @@
tl_assert(top >=3D 0 && top < lc_n_shadows); =20
tl_assert(lc_markstack[top].state !=3D Unreached);
=20
- _lc_scan_memory(lc_shadows[top]->data, lc_shadows[top]->size, cliq=
ue);
+ lc_scan_memory_WRK(lc_shadows[top]->data, lc_shadows[top]->size, c=
lique);
}
}
=20
@@ -521,7 +530,7 @@
if (VG_DEBUG_CLIQUE)
VG_(printf)("%d: gathering clique %p\n", i, lc_shadows[i]->data);
=20
- _lc_markstack_push(lc_shadows[i]->data, i);
+ lc_markstack_push_WRK(lc_shadows[i]->data, i);
=20
lc_do_leakcheck(i);
=20
@@ -726,14 +735,22 @@
=20
lc_scanned =3D 0;
=20
- /* Do the scan of memory, pushing any pointers onto the mark stack.
- Here, we iterate over the segment array, handing any RW client
- sections to lc_scan_memory. */
+ /* Push roots onto the mark stack. Roots are:
+ - the integer registers of all threads
+ - all mappings belonging to the client, including stacks
+ - .. but excluding any client heap segments.
+ Client heap segments are excluded because we wish to differentiate
+ client heap blocks which are referenced only from inside the heap
+ from those outside. This facilitates the indirect vs direct loss
+ categorisation, which [if the users ever manage to understand it]
+ is really useful for detecting lost cycles.
+ */
{ NSegment* seg;
Addr* seg_starts;
Int n_seg_starts;
seg_starts =3D get_seg_starts( &n_seg_starts );
tl_assert(seg_starts && n_seg_starts > 0);
+ /* VG_(am_show_nsegments)( 0,"leakcheck"); */
for (i =3D 0; i < n_seg_starts; i++) {
seg =3D VG_(am_find_nsegment)( seg_starts[i] );
tl_assert(seg);
@@ -741,6 +758,10 @@
continue;
if (!(seg->hasR && seg->hasW))
continue;
+ if (seg->isCH)
+ continue;
+ if (0)
+ VG_(printf)("ACCEPT %2d %p %p\n", i, seg->start, seg->end);
lc_scan_memory(seg->start, seg->end+1 - seg->start);
}
}
|