Index: valgrind/include/tool.h.base
===================================================================
--- valgrind.orig/include/tool.h.base	2005-02-22 23:17:37.000000000 -0800
+++ valgrind/include/tool.h.base	2005-02-23 11:27:46.000000000 -0800
@@ -515,6 +515,15 @@ extern void VG_(set_fault_catcher)(void 
 */
 extern void VG_(init_shadow_range)(Addr p, UInt sz, Bool call_init);
 
+/* Calls into the core used by leak-checking */
+
+/* Calls "add_rootrange" with each range of memory which looks like a
+   plausible source of root pointers. */
+extern void VG_(find_root_memory)(void (*add_rootrange)(Addr addr, SizeT sz));
+
+/* Calls "mark_addr" with register values (which may or may not be pointers) */
+extern void VG_(mark_from_registers)(void (*mark_addr)(Addr addr));
+
 /* ------------------------------------------------------------------ */
 /* signal.h.
 
Index: valgrind/coregrind/x86/state.c
===================================================================
--- valgrind.orig/coregrind/x86/state.c	2005-02-22 23:17:37.000000000 -0800
+++ valgrind/coregrind/x86/state.c	2005-02-23 11:27:46.000000000 -0800
@@ -159,6 +159,21 @@ void VGA_(thread_initial_stack)(ThreadId
    VG_TRACK ( post_mem_write, esp, 2 * sizeof(UWord) );
 }
 
+void VGA_(mark_from_registers)(ThreadId tid, void (*marker)(Addr))
+{
+   ThreadState *tst = VG_(get_ThreadState)(tid);
+   arch_thread_t *arch = &tst->arch;
+
+   /* XXX ask tool about validity? */
+   (*marker)(arch->m_eax);
+   (*marker)(arch->m_ebx);
+   (*marker)(arch->m_ecx);
+   (*marker)(arch->m_edx);
+   (*marker)(arch->m_esi);
+   (*marker)(arch->m_edi);
+   (*marker)(arch->m_esp);
+   (*marker)(arch->m_ebp);
+}
 
 /*------------------------------------------------------------*/
 /*--- Symtab stuff                                         ---*/
Index: valgrind/coregrind/core.h
===================================================================
--- valgrind.orig/coregrind/core.h	2005-02-22 23:17:37.000000000 -0800
+++ valgrind/coregrind/core.h	2005-02-23 11:27:46.000000000 -0800
@@ -1776,6 +1776,9 @@ extern void VGA_(fill_elffpregs_from_tst
 extern void VGA_(fill_elffpxregs_from_tst) ( vki_elf_fpxregset_t* xfpu,
                                              const arch_thread_t* arch );
 
+// Used by leakcheck
+extern void VGA_(mark_from_registers)(ThreadId tid, void (*marker)(Addr));
+
 // Signal stuff
 extern void VGA_(push_signal_frame) ( ThreadId tid, Addr sp_top_of_frame,
                                       const vki_siginfo_t *siginfo,
Index: valgrind/coregrind/vg_memory.c
===================================================================
--- valgrind.orig/coregrind/vg_memory.c	2005-02-22 23:17:37.000000000 -0800
+++ valgrind/coregrind/vg_memory.c	2005-02-23 11:27:47.000000000 -0800
@@ -833,6 +833,25 @@ void VG_(client_free)(Addr addr)
    VG_(munmap)((void *)s->addr, s->len);
 }
 
+/* We'll call any RW mmaped memory segment, within the client address
+   range, which isn't SF_CORE, a root. */
+void VG_(find_root_memory)(void (*add_rootrange)(Addr a, SizeT sz))
+{
+   Segment *s;
+
+   for(s = VG_(first_segment)(); s != NULL; s = VG_(next_segment)(s)) {
+      if (s->flags & (SF_SHARED|SF_MMAP|SF_VALGRIND|SF_CORE) != SF_MMAP)
+	 continue;
+      if (s->prot & (VKI_PROT_READ|VKI_PROT_WRITE) != (VKI_PROT_READ|VKI_PROT_WRITE))
+	 continue;
+      if (!VG_(is_client_addr)(s->addr) ||
+	  !VG_(is_client_addr)(s->addr+s->len))
+	 continue;
+
+      (*add_rootrange)(s->addr, s->len);
+   }
+}
+
 /*--------------------------------------------------------------------*/
 /*--- Querying memory layout                                       ---*/
 /*--------------------------------------------------------------------*/
Index: valgrind/memcheck/mac_leakcheck.c
===================================================================
--- valgrind.orig/memcheck/mac_leakcheck.c	2005-02-22 23:17:37.000000000 -0800
+++ valgrind/memcheck/mac_leakcheck.c	2005-02-23 14:22:42.000000000 -0800
@@ -36,6 +36,11 @@
 /* Define to debug the memory-leak-detector. */
 /* #define VG_DEBUG_LEAKCHECK */
 
+#define ROUNDDN(p, a)	((Addr)(p) & ~((a)-1))
+#define ROUNDUP(p, a)	ROUNDDN((p)+(a)-1, (a))
+#define PGROUNDDN(p)	ROUNDDN(p, VKI_PAGE_SIZE)
+#define PGROUNDUP(p)	ROUNDUP(p, VKI_PAGE_SIZE)
+
 /*------------------------------------------------------------*/
 /*--- Low-level address-space scanning, for the leak       ---*/
 /*--- detector.                                            ---*/
@@ -54,106 +59,6 @@ void vg_scan_all_valid_memory_catcher ( 
       __builtin_longjmp(memscan_jmpbuf, 1);
 }
 
-/* Safely (avoiding SIGSEGV / SIGBUS) scan the entire valid address
-   space and pass the addresses and values of all addressible,
-   defined, aligned words to notify_word.  This is the basis for the
-   leak detector.  Returns the number of calls made to notify_word.
-
-   Addresses are validated 3 ways.  First we enquire whether (addr >>
-   16) denotes a 64k chunk in use, by asking is_valid_64k_chunk().  If
-   so, we decide for ourselves whether each x86-level (4 K) page in
-   the chunk is safe to inspect.  If yes, we enquire with
-   is_valid_address() whether or not each of the 1024 word-locations
-   on the page is valid.  Only if so are that address and its contents
-   passed to notify_word.
-
-   This is all to avoid duplication of this machinery between
-   Memcheck and Addrcheck.  
-*/
-static
-UInt vg_scan_all_valid_memory ( Bool is_valid_64k_chunk ( UInt ),
-                                Bool is_valid_address ( Addr ),
-                                void (*notify_word)( Addr, UInt ) )
-{
-   /* All volatile, because some gccs seem paranoid about longjmp(). */
-   volatile Bool anyValid;
-   volatile Addr pageBase, addr;
-   volatile UInt numPages, page, primaryMapNo;
-   volatile UInt page_first_word, nWordsNotified;
-   vki_sigset_t sigmask;
-
-   VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &sigmask);
-   VG_(set_fault_catcher)(vg_scan_all_valid_memory_catcher);
-
-   numPages = 1 << (32-VKI_PAGE_SHIFT);
-   sk_assert(numPages == 1048576);
-   sk_assert(4096 == (1 << VKI_PAGE_SHIFT));
-
-   nWordsNotified = 0;
-
-   for (page = 0; page < numPages; page++) {
-
-      /* Base address of this 4k page. */
-      pageBase = page << VKI_PAGE_SHIFT;
-
-      /* Skip if this page is in an unused 64k chunk. */
-      primaryMapNo = pageBase >> 16;
-      if (!is_valid_64k_chunk(primaryMapNo))
-         continue;
-
-      /* Next, establish whether or not we want to consider any
-         locations on this page.  We need to do so before actually
-         prodding it, because prodding it when in fact it is not
-         needed can cause a page fault which under some rare
-         circumstances can cause the kernel to extend the stack
-         segment all the way down to here, which is seriously bad.
-         Hence: */
-      anyValid = False;
-      for (addr = pageBase; addr < pageBase+VKI_PAGE_SIZE; addr += 4) {
-         if (is_valid_address(addr)) {
-            anyValid = True;
-            break;
-         }
-      }
-
-      if (!anyValid)
-         continue;  /* nothing interesting here .. move to the next page */
-
-      /* Ok, we have to prod cautiously at the page and see if it
-         explodes or not. */
-      if (VG_(is_addressable)(pageBase, sizeof(UInt), VKI_PROT_READ) && 
-	  __builtin_setjmp(memscan_jmpbuf) == 0) {
-         page_first_word = * (volatile UInt*)pageBase;
-         /* we get here if we didn't get a fault */
-         /* Scan the page */
-         for (addr = pageBase; addr < pageBase+VKI_PAGE_SIZE; addr += sizeof(void *)) {
-            if (is_valid_address(addr)) {
-               nWordsNotified++;
-               notify_word ( addr, *(UInt*)addr );
-	    }
-         }
-      } else {
-         /* We get here if reading the first word of the page caused a
-            fault, which in turn caused the signal handler to longjmp.
-            Ignore this page. */
-
-	 /* We need to restore the signal mask, because we were
-	    longjmped out of a signal handler. */
-	 VG_(sigprocmask)(VKI_SIG_SETMASK, &sigmask, NULL);
-         if (0)
-         VG_(printf)(
-            "vg_scan_all_valid_memory_sighandler: ignoring page at %p\n",
-            (void*)pageBase 
-         );
-      }
-   }
-
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &sigmask, NULL);
-   VG_(set_fault_catcher)(NULL);
-
-   return nWordsNotified;
-}
-
 /*------------------------------------------------------------*/
 /*--- Detecting leaked (unreachable) malloc'd blocks.      ---*/
 /*------------------------------------------------------------*/
@@ -162,10 +67,21 @@ UInt vg_scan_all_valid_memory ( Bool is_
    -- 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. 
+   -- IndirectLeak; leaked, but referred to by another leaked block
 */
-typedef 
-   enum { Unreached, Interior, Proper } 
-   Reachedness;
+typedef enum { 
+   Unreached, 
+   IndirectLeak,
+   Interior, 
+   Proper
+ } Reachedness;
+
+/* 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;
 
 /* A block record, used for generating err msgs. */
 typedef
@@ -177,6 +93,7 @@ typedef
       Reachedness  loss_mode;
       /* Number of blocks and total # bytes involved. */
       UInt         total_bytes;
+      UInt	   indirect_bytes;
       UInt         num_blocks;
    }
    LossRecord;
@@ -251,79 +168,38 @@ Int find_shadow_for ( Addr        ptr, 
 /* Globals, for the following callback used by VG_(detect_memory_leaks). */
 static MAC_Chunk**  lc_shadows;
 static Int          lc_n_shadows;
-static Reachedness* lc_reachedness;
+static MarkStack*   lc_markstack;
+static Int	    lc_markstack_top;
 static Addr         lc_min_mallocd_addr;
 static Addr         lc_max_mallocd_addr;
 
-static 
-void vg_detect_memory_leaks_notify_addr ( Addr a, UInt word_at_a )
-{
-   Int  sh_no;
-   Addr ptr;
-
-   /* Rule out some known causes of bogus pointers.  Mostly these do
-      not cause much trouble because only a few false pointers can
-      ever lurk in these places.  This mainly stops it reporting that
-      blocks are still reachable in stupid test programs like this
-
-         int main (void) { char* a = malloc(100); return 0; }
-
-      which people seem inordinately fond of writing, for some reason.  
-
-      Note that this is a complete kludge.  It would be better to
-      ignore any addresses corresponding to valgrind.so's .bss and
-      .data segments, but I cannot think of a reliable way to identify
-      where the .bss segment has been put.  If you can, drop me a
-      line.  
-   */
-   if (!VG_(is_client_addr)(a))
-      return;
-
-   /* OK, let's get on and do something Useful for a change. */
-
-   ptr = (Addr)word_at_a;
-   if (0)
-      VG_(printf)("notify %p -> %x; min=%p max=%p\n", a, word_at_a, 
-		  lc_min_mallocd_addr, lc_max_mallocd_addr);
-   if (ptr >= lc_min_mallocd_addr && ptr <= lc_max_mallocd_addr) {
-      /* Might be legitimate; we'll have to investigate further. */
-      sh_no = find_shadow_for ( ptr, lc_shadows, lc_n_shadows );
-      if (0) VG_(printf)("find_shadow_for(%p) -> %d\n", ptr, sh_no);
-      if (sh_no != -1) {
-         /* Found a block at/into which ptr points. */
-         sk_assert(sh_no >= 0 && sh_no < lc_n_shadows);
-         sk_assert(ptr <= lc_shadows[sh_no]->data + lc_shadows[sh_no]->size);
-         /* Decide whether Proper-ly or Interior-ly reached. */
-         if (ptr == lc_shadows[sh_no]->data) {
-            if (0) VG_(printf)("pointer at %p to %p\n", a, word_at_a );
-            lc_reachedness[sh_no] = Proper;
-         } else {
-            if (lc_reachedness[sh_no] == Unreached)
-               lc_reachedness[sh_no] = Interior;
-         }
-      }
-   }
-}
+static Bool	  (*lc_is_valid_chunk)  (UInt chunk);
+static Bool	  (*lc_is_valid_address)(Addr addr);
 
 /* Used for printing leak errors, avoids exposing the LossRecord type (which
    comes in as void*, requiring a cast. */
 void MAC_(pp_LeakError)(void* vl, UInt n_this_record, UInt n_total_records)
 {
    LossRecord* l = (LossRecord*)vl;
+   const Char *loss = "?";
+
+   switch(l->loss_mode) {
+   case Unreached:	loss = "definitely lost"; break;
+   case IndirectLeak:	loss = "indirectly lost"; break;
+   case Interior:	loss = "possibly lost"; break;
+   case Proper:		loss = "still reachable"; break;
+   }
 
    VG_(message)(Vg_UserMsg, "");
    VG_(message)(Vg_UserMsg, 
-                "%d bytes in %d blocks are %s in loss record %d of %d",
-                l->total_bytes, l->num_blocks,
-                l->loss_mode==Unreached ?    "definitely lost"
-                 : (l->loss_mode==Interior ? "possibly lost"
-                                           : "still reachable"),
-                n_this_record, n_total_records
-   );
+                "%d+%d bytes in %d blocks are %s in loss record %d of %d",
+                l->total_bytes, l->indirect_bytes, l->num_blocks,
+		loss, n_this_record, n_total_records);
    VG_(pp_ExeContext)(l->allocated_at);
 }
 
 Int MAC_(bytes_leaked)     = 0;
+Int MAC_(bytes_indirect)   = 0;
 Int MAC_(bytes_dubious)    = 0;
 Int MAC_(bytes_reachable)  = 0;
 Int MAC_(bytes_suppressed) = 0;
@@ -335,6 +211,136 @@ static Int lc_compar(void* n1, void* n2)
    return (mc1->data < mc2->data ? -1 : 1);
 }
 
+/* If ptr is pointing to a heap-allocated block which hasn't been seen
+   before, push it onto the mark stack. */
+static void _lc_markstack_push(Addr ptr, Bool mopup)
+{
+   Int sh_no = find_shadow_for(ptr, lc_shadows, lc_n_shadows);
+
+   if (sh_no == -1)
+      return;
+
+   sk_assert(sh_no >= 0 && sh_no < lc_n_shadows);
+   sk_assert(ptr <= lc_shadows[sh_no]->data + lc_shadows[sh_no]->size);
+
+   if (lc_markstack[sh_no].state == Unreached) {
+      if (0)
+	 VG_(printf)("pushing %p-%p\n", lc_shadows[sh_no]->data, 
+		     lc_shadows[sh_no]->data + lc_shadows[sh_no]->size);
+
+      sk_assert(lc_markstack[sh_no].next == -1);
+      lc_markstack[sh_no].next = lc_markstack_top;
+      lc_markstack_top = sh_no;
+   }
+
+   if (mopup) {
+      if (0)
+	 VG_(printf)("mopup: %d: %p is %d\n", 
+		     sh_no, lc_shadows[sh_no]->data, lc_markstack[sh_no].state);
+
+      if (lc_markstack[sh_no].state == Unreached)
+	 lc_markstack[sh_no].state = IndirectLeak;
+   } else if (ptr == lc_shadows[sh_no]->data) {
+      lc_markstack[sh_no].state = Proper;
+   } else {
+      if (lc_markstack[sh_no].state == Unreached)
+	 lc_markstack[sh_no].state = Interior;
+   }
+}
+
+static void lc_markstack_push(Addr ptr)
+{
+   _lc_markstack_push(ptr, False);
+}
+
+/* Return the top of the mark stack, if any. */
+static Int lc_markstack_pop(void)
+{
+   Int ret = lc_markstack_top;
+
+   if (ret != -1) {
+      lc_markstack_top = lc_markstack[ret].next;
+      lc_markstack[ret].next = -1;
+   }
+
+   return ret;
+}
+
+/* Scan a block of memory between [start, start+len).  This range may
+   be bogus, inaccessable, or otherwise strange; we deal with it. */
+static void _lc_scan_memory(Addr start, SizeT len, Bool mopup)
+{
+   Addr ptr = ROUNDUP(start, sizeof(Addr));
+   Addr end = ROUNDDN(start+len, sizeof(Addr));
+   vki_sigset_t sigmask;
+
+   VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &sigmask);
+   VG_(set_fault_catcher)(vg_scan_all_valid_memory_catcher);
+
+   if (!VG_(is_client_addr)(ptr) ||
+       !VG_(is_addressable)(ptr, sizeof(Addr), VKI_PROT_READ))
+      ptr = PGROUNDUP(ptr+1);	/* first page bad */
+
+   while(ptr < end) {
+      Addr addr;
+
+      /* Skip invalid chunks */
+      if (!(*lc_is_valid_chunk)(PM_IDX(ptr))) {
+	 ptr = ROUNDUP(ptr+1, SECONDARY_SIZE);
+	 continue;
+      }
+
+      /* Look to see if this page seems reasonble */
+      if ((ptr % VKI_PAGE_SIZE) == 0) {
+	 if (!VG_(is_client_addr)(ptr) ||
+	     !VG_(is_addressable)(ptr, sizeof(Addr), VKI_PROT_READ))
+	    ptr += VKI_PAGE_SIZE; /* bad page - skip it */
+      }
+
+      if (__builtin_setjmp(memscan_jmpbuf) == 0) {
+	 if ((*lc_is_valid_address)(ptr)) {
+	    addr = *(Addr *)ptr;
+	    _lc_markstack_push(addr, mopup);
+	 }
+	 ptr += sizeof(Addr);
+      } else {
+	 /* We need to restore the signal mask, because we were
+	    longjmped out of a signal handler. */
+	 VG_(sigprocmask)(VKI_SIG_SETMASK, &sigmask, NULL);
+
+	 ptr = PGROUNDUP(ptr);	/* bad page - skip it */
+      }
+   }
+
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &sigmask, NULL);
+   VG_(set_fault_catcher)(NULL);
+}
+
+static void lc_scan_memory(Addr start, SizeT len)
+{
+   _lc_scan_memory(start, len, False);
+}
+
+/* Process the mark stack until empty.  If mopup is true, then we're
+   actually gathering leaked blocks, so they should be marked
+   IndirectLeak. */
+static SizeT lc_do_leakcheck(Bool mopup)
+{
+   Int scanned = 0;
+   Int top;
+
+   while((top = lc_markstack_pop()) != -1) {
+      sk_assert(top >= 0 && top < lc_n_shadows);      
+      sk_assert(lc_markstack[top].state != Unreached);
+
+      scanned += lc_shadows[top]->size;
+
+      _lc_scan_memory(lc_shadows[top]->data, lc_shadows[top]->size, mopup);
+   }
+
+   return scanned;
+}
+
 /* Top level entry point to leak detector.  Call here, passing in
    suitable address-validating functions (see comment at top of
    vg_scan_all_valid_memory above).  All this is to avoid duplication
@@ -351,6 +357,7 @@ void MAC_(do_detect_memory_leaks) (
 {
    Int    i;
    Int    blocks_leaked;
+   Int    blocks_indirect;
    Int    blocks_dubious;
    Int    blocks_reachable;
    Int    blocks_suppressed;
@@ -397,31 +404,60 @@ void MAC_(do_detect_memory_leaks) (
    lc_max_mallocd_addr = lc_shadows[lc_n_shadows-1]->data
                          + lc_shadows[lc_n_shadows-1]->size;
 
-   lc_reachedness = VG_(malloc)( lc_n_shadows * sizeof(Reachedness) );
-   for (i = 0; i < lc_n_shadows; i++)
-      lc_reachedness[i] = Unreached;
-
-   /* Do the scan of memory. */
-   bytes_notified
-       = sizeof(UWord)
-         * vg_scan_all_valid_memory (
-              is_valid_64k_chunk,
-              is_valid_address,
-              &vg_detect_memory_leaks_notify_addr
-           );
+   lc_markstack = VG_(malloc)( lc_n_shadows * sizeof(*lc_markstack) );
+   for (i = 0; i < lc_n_shadows; i++) {
+      lc_markstack[i].next = -1;
+      lc_markstack[i].state = Unreached;
+      lc_markstack[i].indirect = 0;
+   }
+   lc_markstack_top = -1;
+
+   lc_is_valid_chunk   = is_valid_64k_chunk;
+   lc_is_valid_address = is_valid_address;
+
+   /* Do the scan of memory, pushing any pointers onto the mark stack */
+   VG_(find_root_memory)(lc_scan_memory);
+
+   /* Push registers onto mark stack */
+   VG_(mark_from_registers)(lc_markstack_push);
+
+   /* Keep walking the heap until everything is found */
+   bytes_notified = lc_do_leakcheck(False);
 
    if (VG_(clo_verbosity) > 0)
       VG_(message)(Vg_UserMsg, "checked %d bytes.", bytes_notified);
 
+   /* Go through and find the heads of lost data-structures; we don't
+      want to report every single lost block individually. */
+   for (i = 0; i < lc_n_shadows; i++) {
+      SizeT indirect = 0;
+
+      if (lc_markstack[i].state != Unreached)
+	 continue;
+
+      sk_assert(lc_markstack_top == -1);
+
+      VG_(printf)("%d: mopping up from %p\n", i, lc_shadows[i]->data);
+
+      _lc_markstack_push(lc_shadows[i]->data, True);
+
+      indirect = lc_do_leakcheck(True);
+
+      sk_assert(lc_markstack_top == -1);
+      sk_assert(lc_markstack[i].state == IndirectLeak);
+
+      lc_markstack[i].state = Unreached; /* return to unreached state */
+      lc_markstack[i].indirect = indirect;
+   }
+      
    /* Common up the lost blocks so we can print sensible error messages. */
    n_lossrecords = 0;
    errlist       = NULL;
    for (i = 0; i < lc_n_shadows; i++) {
-     
       ExeContext* where = lc_shadows[i]->where;
-      
+
       for (p = errlist; p != NULL; p = p->next) {
-         if (p->loss_mode == lc_reachedness[i]
+         if (p->loss_mode == lc_markstack[i].state
              && VG_(eq_ExeContext) ( MAC_(clo_leak_resolution),
                                      p->allocated_at, 
                                      where) ) {
@@ -431,12 +467,14 @@ void MAC_(do_detect_memory_leaks) (
       if (p != NULL) {
          p->num_blocks  ++;
          p->total_bytes += lc_shadows[i]->size;
+	 p->indirect_bytes += lc_markstack[i].indirect;
       } else {
          n_lossrecords ++;
          p = VG_(malloc)(sizeof(LossRecord));
-         p->loss_mode    = lc_reachedness[i];
+         p->loss_mode    = lc_markstack[i].state;
          p->allocated_at = where;
          p->total_bytes  = lc_shadows[i]->size;
+	 p->indirect_bytes = lc_markstack[i].indirect;
          p->num_blocks   = 1;
          p->next         = errlist;
          errlist         = p;
@@ -445,6 +483,7 @@ void MAC_(do_detect_memory_leaks) (
 
    /* Print out the commoned-up blocks and collect summary stats. */
    blocks_leaked     = MAC_(bytes_leaked)     = 0;
+   blocks_indirect   = MAC_(bytes_indirect)   = 0;
    blocks_dubious    = MAC_(bytes_dubious)    = 0;
    blocks_reachable  = MAC_(bytes_reachable)  = 0;
    blocks_suppressed = MAC_(bytes_suppressed) = 0;
@@ -482,6 +521,10 @@ void MAC_(do_detect_memory_leaks) (
          blocks_leaked      += p_min->num_blocks;
          MAC_(bytes_leaked) += p_min->total_bytes;
 
+      } else if (IndirectLeak  == p_min->loss_mode) {
+         blocks_indirect    += p_min->num_blocks;
+         MAC_(bytes_indirect)+= p_min->total_bytes;
+
       } else if (Interior    == p_min->loss_mode) {
          blocks_dubious      += p_min->num_blocks;
          MAC_(bytes_dubious) += p_min->total_bytes;
@@ -501,6 +544,8 @@ void MAC_(do_detect_memory_leaks) (
       VG_(message)(Vg_UserMsg, "LEAK SUMMARY:");
       VG_(message)(Vg_UserMsg, "   definitely lost: %d bytes in %d blocks.", 
                                MAC_(bytes_leaked), blocks_leaked );
+      VG_(message)(Vg_UserMsg, "   indirectly lost: %d bytes in %d blocks.", 
+                               MAC_(bytes_indirect), blocks_indirect );
       VG_(message)(Vg_UserMsg, "   possibly lost:   %d bytes in %d blocks.", 
                                MAC_(bytes_dubious), blocks_dubious );
       VG_(message)(Vg_UserMsg, "   still reachable: %d bytes in %d blocks.", 
@@ -516,7 +561,7 @@ void MAC_(do_detect_memory_leaks) (
    }
 
    VG_(free) ( lc_shadows );
-   VG_(free) ( lc_reachedness );
+   VG_(free) ( lc_markstack );
 }
 
 /*--------------------------------------------------------------------*/
Index: valgrind/coregrind/vg_scheduler.c
===================================================================
--- valgrind.orig/coregrind/vg_scheduler.c	2005-02-22 23:17:37.000000000 -0800
+++ valgrind/coregrind/vg_scheduler.c	2005-02-23 11:27:47.000000000 -0800
@@ -143,6 +143,16 @@ ThreadId VG_(first_matching_thread_stack
    return VG_INVALID_THREADID;
 }
  
+void VG_(mark_from_registers)(void (*mark_addr)(Addr))
+{
+   ThreadId tid;
+
+   for(tid = 1; tid < VG_N_THREADS; tid++) {
+      if (!VG_(is_valid_tid)(tid))
+	 continue;
+      VGA_(mark_from_registers)(tid, mark_addr);
+   }
+}
 
 /* Print the scheduler status. */
 void VG_(pp_sched_status) ( void )
