Hi, the following patch implements a new dumper interface to allow
dumping of profile data for all instrumented shared libraries.

For good reasons, existing libgcov implements the dumping on a
per-shared library basis (i.e., gcov_exit is hidden, gcov_list is file
static). This allows each shared library's profile data to be dumped
independently with separate summary data. The downside is that there
is no interface that can be invoked to dump profile data for all
shared modules.

The attached patch does that. Ok for trunk after testing?

thanks,

David
Index: libgcc/ChangeLog
===================================================================
--- libgcc/ChangeLog    (revision 212682)
+++ libgcc/ChangeLog    (working copy)
@@ -1,3 +1,9 @@
+2014-07-18  Xinliang David Li  <davi...@google.com>
+
+       * libgcov-driver.c: Force __gcov_dump to be exported
+       * libgcov-interface.c (register_dumper): New function.
+       (__gcov_dump_all): Ditto.
+
 2014-07-14  Richard Biener  <rguent...@suse.de>
 
        * libgcov.h (struct gcov_fn_info): Make ctrs size 1.
Index: libgcc/libgcov-driver.c
===================================================================
--- libgcc/libgcov-driver.c     (revision 212682)
+++ libgcc/libgcov-driver.c     (working copy)
@@ -55,6 +55,13 @@ extern void set_gcov_dump_complete (void
 extern void reset_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
 extern int get_gcov_dump_complete (void) ATTRIBUTE_HIDDEN;
 extern void set_gcov_list (struct gcov_info *) ATTRIBUTE_HIDDEN;
+  
+#ifndef IN_GCOV_TOOL
+
+/* Creates strong reference to force _gcov_dump.o to be linked
+   in shared library for exported interfaces.  */
+void (*__gcov_dummy_ref)(void) = &__gcov_dump;
+#endif
 
 struct gcov_fn_buffer
 {
Index: libgcc/libgcov-interface.c
===================================================================
--- libgcc/libgcov-interface.c  (revision 212682)
+++ libgcc/libgcov-interface.c  (working copy)
@@ -115,6 +115,43 @@ __gcov_dump (void)
   set_gcov_dump_complete ();
 }
 
+typedef void (*gcov_dumper_type) (void);
+struct dumper_entry
+{
+  gcov_dumper_type dumper;
+  struct dumper_entry *next_dumper;
+};
+
+static struct dumper_entry this_dumper = {&__gcov_dump, 0};
+
+/* global dumper list with default visibilty. */
+struct dumper_entry *__gcov_dumper_list;
+
+
+__attribute__((constructor))
+static void 
+register_dumper (void)
+{
+  this_dumper.next_dumper = __gcov_dumper_list;
+  __gcov_dumper_list = &this_dumper;
+}
+
+/* Public interface to dump profile data for all shared libraries
+   via registered dumpers from the libraries. This interface
+   has default visibility (unlike gcov_dump which has hidden
+   visbility.  */
+
+void
+__gcov_dump_all (void)
+{
+  struct dumper_entry *dumper = __gcov_dumper_list;
+  while (dumper)
+   {
+     dumper->dumper ();
+     dumper = dumper->next_dumper;
+   }
+}
+
 #endif /* L_gcov_dump */
 
 
Index: libgcc/libgcov.h
===================================================================
--- libgcc/libgcov.h    (revision 212682)
+++ libgcc/libgcov.h    (working copy)
@@ -218,8 +218,14 @@ extern void __gcov_flush (void) ATTRIBUT
 /* Function to reset all counters to 0.  */
 extern void __gcov_reset (void);
 
-/* Function to enable early write of profile information so far.  */
-extern void __gcov_dump (void);
+/* Function to enable early write of profile information so far.  
+   __GCOV_DUMP is also used by __GCOV_DUMP_ALL. The latter 
+   depends on __GCOV_DUMP to have hidden or protected visibility
+   so that each library has its own copy of the registered dumper.  */
+extern void __gcov_dump (void) ATTRIBUTE_HIDDEN;
+
+/* Call __gcov_dump registered from each shared library.  */
+void __gcov_dump_all (void);
 
 /* The merge function that just sums the counters.  */
 extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;

Reply via email to