Index: Makefile.in
===================================================================
--- Makefile.in	(revision 215334)
+++ Makefile.in	(working copy)
@@ -858,9 +858,10 @@ LIBGCOV_PROFILER = _gcov_interval_profil
 	_gcov_one_value_profiler _gcov_indirect_call_profiler		\
  	_gcov_average_profiler _gcov_ior_profiler			\
 	_gcov_indirect_call_profiler_v2 _gcov_time_profiler
-LIBGCOV_INTERFACE = _gcov_flush _gcov_fork _gcov_execl _gcov_execlp    \
+LIBGCOV_INTERFACE = _gcov_dump _gcov_flush _gcov_fork			\
+	_gcov_execl _gcov_execlp					\
 	_gcov_execle _gcov_execv _gcov_execvp _gcov_execve _gcov_reset
-LIBGCOV_DRIVER = _gcov _gcov_dump
+LIBGCOV_DRIVER = _gcov
 
 libgcov-merge-objects = $(patsubst %,%$(objext),$(LIBGCOV_MERGE))
 libgcov-profiler-objects = $(patsubst %,%$(objext),$(LIBGCOV_PROFILER))
Index: libgcov-driver.c
===================================================================
--- libgcov-driver.c	(revision 215334)
+++ libgcov-driver.c	(working copy)
@@ -777,13 +777,23 @@ __gcov_dump_one (struct gcov_root *root)
   root->run_counted = 1;
 }
 
-/* Per-program/shared-object gcov state.  */
+/* Per-dynamic-object gcov state.  */
 struct gcov_root __gcov_root;
 
+/* Exactly one of these will be live in the process image.  */
+struct gcov_master __gcov_master = 
+  {GCOV_VERSION, 0};
+
 static void
 gcov_exit (void)
 {
   __gcov_dump_one (&__gcov_root);
+  if (__gcov_root.next)
+    __gcov_root.next->prev = __gcov_root.prev;
+  if (__gcov_root.prev)
+    __gcov_root.prev->next = __gcov_root.next;
+  else
+    __gcov_master.root = __gcov_root.next;
 }
 
 /* Add a new object file onto the bb chain.  Invoked automatically
@@ -797,12 +807,21 @@ __gcov_init (struct gcov_info *info)
   if (gcov_version (info, info->version, 0))
     {
       if (!__gcov_root.list)
-        atexit (gcov_exit);
+	{
+	  /* Add to master list and at exit function.  */
+	  if (gcov_version (NULL, __gcov_master.version, "<master>"))
+	    {
+	      __gcov_root.next = __gcov_master.root;
+	      if (__gcov_master.root)
+		__gcov_master.root->prev = &__gcov_root;
+	      __gcov_master.root = &__gcov_root;
+	    }
+	  atexit (gcov_exit);
+	}
 
       info->next = __gcov_root.list;
       __gcov_root.list = info;
     }
-  info->version = 0;
 }
 #endif /* !IN_GCOV_TOOL */
 #endif /* L_gcov */
Index: libgcov-interface.c
===================================================================
--- libgcov-interface.c	(revision 215334)
+++ libgcov-interface.c	(working copy)
@@ -85,7 +85,7 @@ __gcov_flush (void)
   init_mx_once ();
   __gthread_mutex_lock (&__gcov_flush_mx);
 
-  __gcov_dump_one (&__gcov_root);
+  __gcov_dump_int ();
   __gcov_reset_int ();
 
   __gthread_mutex_unlock (&__gcov_flush_mx);
@@ -132,8 +132,16 @@ gcov_clear (const struct gcov_info *list
 void
 __gcov_reset_int (void)
 {
-  gcov_clear (__gcov_root.list);
-  __gcov_root.dumped = 0;
+  struct gcov_root *root;
+
+  /* If we're compatible with the master, iterate over everything,
+     otherise just do us.  */
+  for (root = __gcov_master.version == GCOV_VERSION
+	 ? __gcov_master.root : &__gcov_root; root; root = root->next)
+    {
+      gcov_clear (root->list);
+      root->dumped = 0;
+    }
 }
 
 ALIAS_void_fn (__gcov_reset_int, __gcov_reset);
@@ -145,11 +153,19 @@ ALIAS_void_fn (__gcov_reset_int, __gcov_
    so far, in order to collect profile in region of interest.  */
 
 void
-__gcov_dump (void)
+__gcov_dump_int (void)
 {
-  __gcov_dump_one (&__gcov_root);
+  struct gcov_root *root;
+
+  /* If we're compatible with the master, iterate over everything,
+     otherise just do us.  */
+  for (root = __gcov_master.version == GCOV_VERSION
+	 ? __gcov_master.root : &__gcov_root; root; root = root->next)
+    __gcov_dump_one (root);
 }
 
+ALIAS_void_fn (__gcov_dump_int, __gcov_dump);
+
 #endif /* L_gcov_dump */
 
 #ifdef L_gcov_fork
@@ -169,8 +185,8 @@ __gcov_fork (void)
 #endif
 
 #ifdef L_gcov_execl
-/* A wrapper for the execl function.  Flushes the accumulated profiling data, so
-   that they are not lost.  */
+/* A wrapper for the execl function.  Flushes the accumulated
+   profiling data, so that they are not lost.  */
 
 int
 __gcov_execl (const char *path, char *arg, ...)
Index: libgcov.h
===================================================================
--- libgcov.h	(revision 215334)
+++ libgcov.h	(working copy)
@@ -212,10 +212,21 @@ struct gcov_root
   struct gcov_info *list;
   unsigned dumped : 1;	/* counts have been dumped.  */
   unsigned run_counted : 1;  /* run has been accounted for.  */
+  struct gcov_root *next;
+  struct gcov_root *prev;
 };
 
 extern struct gcov_root __gcov_root ATTRIBUTE_HIDDEN;
 
+struct gcov_master
+{
+  gcov_unsigned_t version;
+  struct gcov_root *root;
+};
+  
+/* Exactly one of these will be active in the process.  */
+extern struct gcov_master __gcov_master;
+
 /* Dump a set of gcov objects.  */
 extern void __gcov_dump_one (struct gcov_root *) ATTRIBUTE_HIDDEN;
 
@@ -230,8 +241,9 @@ extern void __gcov_flush (void) ATTRIBUT
 extern void __gcov_reset (void);
 extern void __gcov_reset_int (void) ATTRIBUTE_HIDDEN;
 
-/* Function to enable early write of profile information so far.  */
+/* User function to enable early write of profile information so far.  */
 extern void __gcov_dump (void);
+extern void __gcov_dump_int (void) ATTRIBUTE_HIDDEN;
 
 /* The merge function that just sums the counters.  */
 extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
