This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: a separate libgcov


Jan Hubicka wrote:

Can't -lgcov be implied by -fprofile-arcs or something?  The idea
of requiring one extra option looks pretty ugly to me.
this is what i've installed. -lgcov is implicitly added.

nathan

--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
         The voices in my head said this was stupid too
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org

2003-01-27  Nathan Sidwell  <nathan@codesourcery.com>

	* Makefile.in (LIB2FUNCS_ST): Remove _gcov.
	(LIBGCOV): New variable.
	(libgcc.mk): Add LIBGCOV.
	(LIBGCC_DEPS): Add libgcov.c.
	(libgcov.a): New target.
	(clean): Remove libgcov.a.
	(install-libgcc): Do libgcov too.
	(stage1-start, stage2-start, stage3-start, stage4-start): Deal
	with libgcov.a.
	* libgcc2.c (L_gcov): Move into ...
	* libgcov.c: ... here. New file.
	* mklibgcc.in: Add libgcov rules.
	* gcc.c (LINK_COMMAND_SPEC): Add -lgcov when profiling.

	* doc/invoke.texi (profile-arcs, test-coverage): Update and
	clarify.
	
	* profile.c (index_counts_file): Remove duplicate check for open file.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.980
diff -c -3 -p -r1.980 Makefile.in
*** Makefile.in	26 Jan 2003 09:17:13 -0000	1.980
--- Makefile.in	27 Jan 2003 21:42:25 -0000
*************** LIB2FUNCS_2 = _floatdixf _fixunsxfsi _fi
*** 825,831 ****
      _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors
  
  # Defined in libgcc2.c, included only in the static library.
! LIB2FUNCS_ST = _eprintf _gcov __gcc_bcmp
  
  FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
      _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
--- 825,834 ----
      _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors
  
  # Defined in libgcc2.c, included only in the static library.
! LIB2FUNCS_ST = _eprintf __gcc_bcmp
! 
! # Defined in libgcov.c, included only in gcov library
! LIBGCOV = _gcov
  
  FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
      _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
*************** libgcc.mk: config.status Makefile mklibg
*** 1054,1059 ****
--- 1057,1063 ----
  	LIB2FUNCS_1='$(LIB2FUNCS_1)' \
  	LIB2FUNCS_2='$(LIB2FUNCS_2)' \
  	LIB2FUNCS_ST='$(LIB2FUNCS_ST)' \
+ 	LIBGCOV='$(LIBGCOV)' \
  	LIB2ADD='$(LIB2ADD)' \
  	LIB2ADD_ST='$(LIB2ADD_ST)' \
  	LIB2ADDEH='$(LIB2ADDEH)' \
*************** libgcc.mk: config.status Makefile mklibg
*** 1082,1093 ****
  
  # All the things that might cause us to want to recompile bits of libgcc.
  LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \
! 	libgcc.mk $(srcdir)/libgcc2.c $(TCONFIG_H) \
  	$(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs \
  	tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
  	$(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \
  	$(srcdir)/config/$(LIB1ASMSRC)
  
  libgcc.a: $(LIBGCC_DEPS)
  	$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
  	  BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
--- 1086,1099 ----
  
  # All the things that might cause us to want to recompile bits of libgcc.
  LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \
! 	libgcc.mk $(srcdir)/libgcc2.c $(srcdir)/libgcov.c $(TCONFIG_H) \
  	$(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs \
  	tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
  	$(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \
  	$(srcdir)/config/$(LIB1ASMSRC)
  
+ libgcov.a: libgcc.a; @true
+ 
  libgcc.a: $(LIBGCC_DEPS)
  	$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
  	  BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
*************** mostlyclean: $(INTL_MOSTLYCLEAN) lang.mo
*** 2728,2734 ****
  # that don't exist in the distribution.
  INTL_CLEAN = intl.clean
  clean: mostlyclean $(INTL_CLEAN) lang.clean
! 	-rm -f libgcc.a libgcc_eh.a libgcc_s$(SHLIB_EXT) libgcc_s$(SHLIB_EXT).1
  	-rm -f config.h tconfig.h bconfig.h tm_p.h tm.h
  	-rm -f cs-*
  	-rm -rf libgcc
--- 2734,2741 ----
  # that don't exist in the distribution.
  INTL_CLEAN = intl.clean
  clean: mostlyclean $(INTL_CLEAN) lang.clean
! 	-rm -f libgcc.a libgcc_eh.a libgcov.a
! 	-rm -f libgcc_s$(SHLIB_EXT) libgcc_s$(SHLIB_EXT).1
  	-rm -f config.h tconfig.h bconfig.h tm_p.h tm.h
  	-rm -f cs-*
  	-rm -rf libgcc
*************** install-man: installdirs $(GENERATED_MAN
*** 2984,2990 ****
  	-chmod a-x $(DESTDIR)$(man7dir)/gpl$(man7ext)
  
  # Install the library.
! install-libgcc: libgcc.mk libgcc.a installdirs
  	$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
  	  BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
  	  AR_FOR_TARGET="$(AR_FOR_TARGET)" \
--- 2991,2997 ----
  	-chmod a-x $(DESTDIR)$(man7dir)/gpl$(man7ext)
  
  # Install the library.
! install-libgcc: libgcc.mk libgcc.a libgcov.a installdirs
  	$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
  	  BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
  	  AR_FOR_TARGET="$(AR_FOR_TARGET)" \
*************** install-libgcc: libgcc.mk libgcc.a insta
*** 3004,3010 ****
  	  slibdir="$(slibdir)" \
  	  -f libgcc.mk install
  
! # Install multiple versions of libgcc.a.
  install-multilib: stmp-multilib installdirs
  	$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
  	  BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
--- 3011,3017 ----
  	  slibdir="$(slibdir)" \
  	  -f libgcc.mk install
  
! # Install multiple versions of libgcc.a, libgcov.a.
  install-multilib: stmp-multilib installdirs
  	$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
  	  BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
*************** stage1-start:
*** 3611,3619 ****
  	-if [ -f as$(exeext) ] ; then (cd stage1 && $(LN_S) ../as$(exeext) .) ; else true ; fi
  	-if [ -f ld$(exeext) ] ; then (cd stage1 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
  	-if [ -f collect-ld$(exeext) ] ; then (cd stage1 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
! 	-rm -f stage1/libgcc.a stage1/libgcc_eh.a
  	-cp libgcc.a stage1
  	-$(RANLIB_FOR_TARGET) stage1/libgcc.a
  	-if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage1; \
  	   $(RANLIB_FOR_TARGET) stage1/libgcc_eh.a; \
  	fi
--- 3618,3628 ----
  	-if [ -f as$(exeext) ] ; then (cd stage1 && $(LN_S) ../as$(exeext) .) ; else true ; fi
  	-if [ -f ld$(exeext) ] ; then (cd stage1 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
  	-if [ -f collect-ld$(exeext) ] ; then (cd stage1 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
! 	-rm -f stage1/libgcc.a stage1/libgcc_eh.a stage1/libgcov.a
  	-cp libgcc.a stage1
  	-$(RANLIB_FOR_TARGET) stage1/libgcc.a
+ 	-cp libgcov.a stage1
+ 	-$(RANLIB_FOR_TARGET) stage1/libgcov.a
  	-if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage1; \
  	   $(RANLIB_FOR_TARGET) stage1/libgcc_eh.a; \
  	fi
*************** stage2-start:
*** 3641,3649 ****
  	-if [ -f as$(exeext) ] ; then (cd stage2 && $(LN_S) ../as$(exeext) .) ; else true ; fi
  	-if [ -f ld$(exeext) ] ; then (cd stage2 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
  	-if [ -f collect-ld$(exeext) ] ; then (cd stage2 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
! 	-rm -f stage2/libgcc.a stage2/libgcc_eh.a
  	-cp libgcc.a stage2
  	-$(RANLIB_FOR_TARGET) stage2/libgcc.a
  	-if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage2; \
  	   $(RANLIB_FOR_TARGET) stage2/libgcc_eh.a; \
  	fi
--- 3650,3660 ----
  	-if [ -f as$(exeext) ] ; then (cd stage2 && $(LN_S) ../as$(exeext) .) ; else true ; fi
  	-if [ -f ld$(exeext) ] ; then (cd stage2 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
  	-if [ -f collect-ld$(exeext) ] ; then (cd stage2 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
! 	-rm -f stage2/libgcc.a stage2/libgcov.a stage2/libgcc_eh.a
  	-cp libgcc.a stage2
  	-$(RANLIB_FOR_TARGET) stage2/libgcc.a
+ 	-cp libgcov.a stage2
+ 	-$(RANLIB_FOR_TARGET) stage2/libgcov.a
  	-if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage2; \
  	   $(RANLIB_FOR_TARGET) stage2/libgcc_eh.a; \
  	fi
*************** stage3-start:
*** 3667,3675 ****
  	-if [ -f as$(exeext) ] ; then (cd stage3 && $(LN_S) ../as$(exeext) .) ; else true ; fi
  	-if [ -f ld$(exeext) ] ; then (cd stage3 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
  	-if [ -f collect-ld$(exeext) ] ; then (cd stage3 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
! 	-rm -f stage3/libgcc.a stage3/libgcc_eh.a
  	-cp libgcc.a stage3
  	-$(RANLIB_FOR_TARGET) stage3/libgcc.a
  	-if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage3; \
  	   $(RANLIB_FOR_TARGET) stage3/libgcc_eh.a; \
  	fi
--- 3678,3688 ----
  	-if [ -f as$(exeext) ] ; then (cd stage3 && $(LN_S) ../as$(exeext) .) ; else true ; fi
  	-if [ -f ld$(exeext) ] ; then (cd stage3 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
  	-if [ -f collect-ld$(exeext) ] ; then (cd stage3 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
! 	-rm -f stage3/libgcc.a stage3/libgcov.a stage3/libgcc_eh.a
  	-cp libgcc.a stage3
  	-$(RANLIB_FOR_TARGET) stage3/libgcc.a
+ 	-cp libgcov.a stage3
+ 	-$(RANLIB_FOR_TARGET) stage3/libgcov.a
  	-if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage3; \
  	   $(RANLIB_FOR_TARGET) stage3/libgcc_eh.a; \
  	fi
*************** stage4-start:
*** 3693,3701 ****
  	-if [ -f as$(exeext) ] ; then (cd stage4 && $(LN_S) ../as$(exeext) .) ; else true ; fi
  	-if [ -f ld$(exeext) ] ; then (cd stage4 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
  	-if [ -f collect-ld$(exeext) ] ; then (cd stage4 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
! 	-rm -f stage4/libgcc.a stage4/libgcc_eh.a
  	-cp libgcc.a stage4
  	-$(RANLIB_FOR_TARGET) stage4/libgcc.a
  	-if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage4; \
  	   $(RANLIB_FOR_TARGET) stage4/libgcc_eh.a; \
  	fi
--- 3706,3716 ----
  	-if [ -f as$(exeext) ] ; then (cd stage4 && $(LN_S) ../as$(exeext) .) ; else true ; fi
  	-if [ -f ld$(exeext) ] ; then (cd stage4 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
  	-if [ -f collect-ld$(exeext) ] ; then (cd stage4 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
! 	-rm -f stage4/libgcc.a stage4/libgcov.a stage4/libgcc_eh.a
  	-cp libgcc.a stage4
  	-$(RANLIB_FOR_TARGET) stage4/libgcc.a
+ 	-cp libgcov.a stage4
+ 	-$(RANLIB_FOR_TARGET) stage4/libgcov.a
  	-if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage4; \
  	   $(RANLIB_FOR_TARGET) stage4/libgcc_eh.a; \
  	fi
Index: libgcc2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcc2.c,v
retrieving revision 1.156
diff -c -3 -p -r1.156 libgcc2.c
*** libgcc2.c	18 Jan 2003 22:32:06 -0000	1.156
--- libgcc2.c	27 Jan 2003 21:42:42 -0000
*************** __eprintf (const char *string, const cha
*** 1235,1679 ****
  #endif
  #endif
  
- #ifdef L_gcov
- 
- /* Gcov profile dumper. Requires atexit and stdio.  */
- 
- #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
- #include <stdio.h>
- 
- #include "gcov-io.h"
- #include <string.h>
- #if defined (TARGET_HAS_F_SETLKW)
- #include <fcntl.h>
- #include <errno.h>
- #endif
- 
- /* Chain of per-object gcov structures.  */
- static struct gcov_info *gcov_list;
- 
- /* A program checksum allows us to distinguish program data for an
-    object file included in multiple programs.  */
- static unsigned gcov_crc32;
- 
- static void
- gcov_version_mismatch (struct gcov_info *ptr, unsigned version)
- {
-   unsigned expected = GCOV_VERSION;
-   unsigned ix;
-   char e[4], v[4];
- 
-   for (ix = 4; ix--; expected >>= 8, version >>= 8)
-     {
-       e[ix] = expected;
-       v[ix] = version;
-     }
-   
-   fprintf (stderr,
- 	   "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
- 	   ptr->filename, e, v);
- }
- 
- /* Dump the coverage counts. We merge with existing counts when
-    possible, to avoid growing the .da files ad infinitum. We use this
-    program's checksum to make sure we only accumulate whole program
-    statistics to the correct summary. An object file might be embedded
-    in two separate programs, and we must keep the two program
-    summaries separate.  */
- 
- static void
- gcov_exit (void)
- {
-   struct gcov_info *ptr;
-   unsigned ix, jx;
-   struct gcov_summary program;
-   gcov_type program_max_one = 0;
-   gcov_type program_max_sum = 0;
-   gcov_type program_sum = 0;
-   unsigned program_arcs = 0;
-   
- #if defined (TARGET_HAS_F_SETLKW)
-   struct flock s_flock;
- 
-   s_flock.l_type = F_WRLCK;
-   s_flock.l_whence = SEEK_SET;
-   s_flock.l_start = 0;
-   s_flock.l_len = 0; /* Until EOF.  */
-   s_flock.l_pid = getpid ();
- #endif
- 
-   memset (&program, 0, sizeof (program));
-   program.checksum = gcov_crc32;
-   
-   for (ptr = gcov_list; ptr; ptr = ptr->next)
-     {
-       FILE *da_file;
-       struct gcov_summary object;
-       struct gcov_summary local_prg;
-       int merging = 0;
-       long base;
-       const struct function_info *fn_info;
-       gcov_type *count_ptr;
-       gcov_type object_max_one = 0;
- 
-       ptr->wkspc = 0;
-       if (!ptr->filename)
- 	continue;
- 
-       for (ix = ptr->n_arc_counts, count_ptr = ptr->arc_counts; ix--;)
- 	{
- 	  gcov_type count = *count_ptr++;
- 
- 	  if (count > object_max_one)
- 	    object_max_one = count;
- 	}
-       if (object_max_one > program_max_one)
- 	program_max_one = object_max_one;
-       
-       memset (&local_prg, 0, sizeof (local_prg));
-       memset (&object, 0, sizeof (object));
-       
-       /* Open for modification */
-       if ((da_file = fopen (ptr->filename, "r+b")))
- 	merging = 1;
-       else if ((da_file = fopen (ptr->filename, "w+b")))
- 	;
-       else
- 	{
- 	  fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
- 	  ptr->filename = 0;
- 	  continue;
- 	}
- 
- #if defined (TARGET_HAS_F_SETLKW)
-       /* After a fork, another process might try to read and/or write
-          the same file simultaneously.  So if we can, lock the file to
-          avoid race conditions.  */
-       while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
- 	     && errno == EINTR)
- 	continue;
- #endif
-       if (merging)
- 	{
- 	  /* Merge data from file.  */
- 	  unsigned tag, length;
- 	      
- 	  if (gcov_read_unsigned (da_file, &tag) || tag != GCOV_DATA_MAGIC)
- 	    {
- 	      fprintf (stderr, "profiling:%s:Not a gcov data file\n",
- 		       ptr->filename);
- 	    read_fatal:;
- 	      fclose (da_file);
- 	      ptr->filename = 0;
- 	      continue;
- 	    }
- 	  if (gcov_read_unsigned (da_file, &length) || length != GCOV_VERSION)
- 	    {
- 	      gcov_version_mismatch (ptr, length);
- 	      goto read_fatal;
- 	    }
- 	  
- 	  /* Merge execution counts for each function.  */
- 	  count_ptr = ptr->arc_counts;
- 	  for (ix = ptr->n_functions, fn_info = ptr->functions;
- 	       ix--; fn_info++)
- 	    {
- 	      if (gcov_read_unsigned (da_file, &tag)
- 		  || gcov_read_unsigned (da_file, &length))
- 		{
- 		read_error:;
- 		  fprintf (stderr, "profiling:%s:Error merging\n",
- 			   ptr->filename);
- 		  goto read_fatal;
- 		}
- 
- 	      /* Check function */
- 	      if (tag != GCOV_TAG_FUNCTION)
- 		{
- 		read_mismatch:;
- 		  fprintf (stderr, "profiling:%s:Merge mismatch at %s\n",
- 			   ptr->filename, fn_info->name);
- 		  goto read_fatal;
- 		}
- 	      {
- 		unsigned flength, checksum;
- 		
- 		if (gcov_read_unsigned (da_file, &flength)
- 		    || gcov_skip_string (da_file, flength)
- 		    || gcov_read_unsigned (da_file, &checksum))
- 		  goto read_error;
- 		if (flength != strlen (fn_info->name)
- 		    || checksum != fn_info->checksum)
- 		  goto read_mismatch;
- 	      }
- 	      /* Check arc counts */
- 	      if (gcov_read_unsigned (da_file, &tag)
- 		  || gcov_read_unsigned (da_file, &length))
- 		goto read_error;
- 	      if (tag != GCOV_TAG_ARC_COUNTS
- 		  || length / 8 != fn_info->n_arc_counts)
- 		goto read_mismatch;
- 	      {
- 		gcov_type count;
- 		
- 		for (jx = fn_info->n_arc_counts; jx--; count_ptr++)
- 		  if (gcov_read_counter (da_file, &count))
- 		    goto read_error;
- 		  else
- 		    *count_ptr += count;
- 	      }
- 	    }
- 
- 	  /* Check object summary */
- 	  if (gcov_read_unsigned (da_file, &tag)
- 	      || gcov_read_unsigned (da_file, &length))
- 	    goto read_error;
- 	  if (tag != GCOV_TAG_OBJECT_SUMMARY)
- 	    goto read_mismatch;
- 	  if (gcov_read_summary (da_file, &object))
- 	    goto read_error;
- 
- 	  /* Check program summary */
- 	  while (1)
- 	    {
- 	      long base = ftell (da_file);
- 	      
- 	      if (gcov_read_unsigned (da_file, &tag)
- 		  || gcov_read_unsigned (da_file, &length))
- 		{
- 		  if (feof (da_file))
- 		    break;
- 		  goto read_error;
- 		}
- 	      if (tag != GCOV_TAG_PROGRAM_SUMMARY
- 		  && tag != GCOV_TAG_PLACEHOLDER_SUMMARY
- 		  && tag != GCOV_TAG_INCORRECT_SUMMARY)
- 		goto read_mismatch;
- 	      if (gcov_read_summary (da_file, &local_prg))
- 		goto read_error;
- 	      if (local_prg.checksum != program.checksum)
- 		continue;
- 	      if (tag == GCOV_TAG_PLACEHOLDER_SUMMARY)
- 		{
- 		  fprintf (stderr,
- 			   "profiling:%s:Concurrent race detected\n",
- 			   ptr->filename);
- 		  goto read_fatal;
- 		}
- 	      merging = -1;
- 	      if (tag != GCOV_TAG_PROGRAM_SUMMARY)
- 		break;
- 	      
- 	      if (program.runs
- 		  && memcmp (&program, &local_prg, sizeof (program)))
- 		{
- 		  fprintf (stderr, "profiling:%s:Invocation mismatch\n",
- 			   ptr->filename);
- 		  local_prg.runs = 0;
- 		}
- 	      else
- 		memcpy (&program, &local_prg, sizeof (program));
- 	      ptr->wkspc = base;
- 	      break;
- 	    }
- 	  fseek (da_file, 0, SEEK_SET);
- 	}
- 
-       object.runs++;
-       object.arcs = ptr->n_arc_counts;
-       object.arc_sum = 0;
-       if (object.arc_max_one < object_max_one)
- 	object.arc_max_one = object_max_one;
-       object.arc_sum_max += object_max_one;
-       
-       /* Write out the data.  */
-       if (/* magic */
- 	  gcov_write_unsigned (da_file, GCOV_DATA_MAGIC)
- 	  /* version number */
- 	  || gcov_write_unsigned (da_file, GCOV_VERSION))
- 	{
- 	write_error:;
- 	  fclose (da_file);
- 	  fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
- 	  ptr->filename = 0;
- 	  continue;
- 	}
-       
-       /* Write execution counts for each function.  */
-       count_ptr = ptr->arc_counts;
-       for (ix = ptr->n_functions, fn_info = ptr->functions; ix--; fn_info++)
- 	{
- 	  /* Announce function.  */
- 	  if (gcov_write_unsigned (da_file, GCOV_TAG_FUNCTION)
- 	      || !(base = gcov_reserve_length (da_file))
- 	      /* function name */
- 	      || gcov_write_string (da_file, fn_info->name,
- 				    strlen (fn_info->name))
- 	      /* function checksum */
- 	      || gcov_write_unsigned (da_file, fn_info->checksum)
- 	      || gcov_write_length (da_file, base))
- 	    goto write_error;
- 	  
- 	  /* arc counts.  */
- 	  if (gcov_write_unsigned (da_file, GCOV_TAG_ARC_COUNTS)
- 	      || !(base = gcov_reserve_length (da_file)))
- 	    goto write_error;
- 	  
- 	  for (jx = fn_info->n_arc_counts; jx--;)
- 	    {
- 	      gcov_type count = *count_ptr++;
- 	      
- 	      object.arc_sum += count;
- 	      if (object.arc_max_sum < count)
- 		object.arc_max_sum = count;
- 	      if (gcov_write_counter (da_file, count))
- 		goto write_error; /* RIP Edsger Dijkstra */
- 	    }
- 	  if (gcov_write_length (da_file, base))
- 	    goto write_error;
- 	}
- 
-       /* Object file summary.  */
-       if (gcov_write_summary (da_file, GCOV_TAG_OBJECT_SUMMARY, &object))
- 	goto write_error;
- 
-       if (merging >= 0)
- 	{
- 	  if (fseek (da_file, 0, SEEK_END))
- 	    goto write_error;
- 	  ptr->wkspc = ftell (da_file);
- 	  if (gcov_write_summary (da_file, GCOV_TAG_PLACEHOLDER_SUMMARY,
- 				  &program))
- 	    goto write_error;
- 	}
-       else if (ptr->wkspc)
- 	{
- 	  /* Zap trailing program summary */
- 	  if (fseek (da_file, ptr->wkspc, SEEK_SET))
- 	    goto write_error;
- 	  if (!local_prg.runs)
- 	    ptr->wkspc = 0;
- 	  if (gcov_write_unsigned (da_file,
- 			     local_prg.runs ? GCOV_TAG_PLACEHOLDER_SUMMARY
- 			     : GCOV_TAG_INCORRECT_SUMMARY))
- 	    goto write_error;
- 	}
-       if (fflush (da_file))
- 	goto write_error;
- 
-       if (fclose (da_file))
- 	{
- 	  fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
- 	  ptr->filename = 0;
- 	}
-       else
- 	{
- 	  program_arcs += ptr->n_arc_counts;
- 	  program_sum += object.arc_sum;
- 	  if (program_max_sum < object.arc_max_sum)
- 	    program_max_sum = object.arc_max_sum;
- 	}
-     }
- 
-   /* Generate whole program statistics.  */
-   program.runs++;
-   program.arcs = program_arcs;
-   program.arc_sum = program_sum;
-   if (program.arc_max_one < program_max_one)
-     program.arc_max_one = program_max_one;
-   if (program.arc_max_sum < program_max_sum)
-     program.arc_max_sum = program_max_sum;
-   program.arc_sum_max += program_max_one;
-   
-   /* Upate whole program statistics.  */
-   for (ptr = gcov_list; ptr; ptr = ptr->next)
-     if (ptr->filename && ptr->wkspc)
-       {
- 	FILE *da_file;
- 	
- 	da_file = fopen (ptr->filename, "r+b");
- 	if (!da_file)
- 	  {
- 	    fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
- 	    continue;
- 	  }
- 	
- #if defined (TARGET_HAS_F_SETLKW)
- 	while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
- 	       && errno == EINTR)
- 	  continue;
- #endif
- 	if (fseek (da_file, ptr->wkspc, SEEK_SET)
-  	    || gcov_write_summary (da_file, GCOV_TAG_PROGRAM_SUMMARY, &program)
-  	    || fflush (da_file))
-  	  fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
- 	if (fclose (da_file))
- 	  fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
-       }
- }
- 
- /* Add a new object file onto the bb chain.  Invoked automatically
-    when running an object file's global ctors.  */
- 
- void
- __gcov_init (struct gcov_info *info)
- {
-   if (!info->version)
-     return;
-   if (info->version != GCOV_VERSION)
-     gcov_version_mismatch (info, info->version);
-   else
-     {
-       const char *ptr = info->filename;
-       unsigned crc32 = gcov_crc32;
-   
-       do
- 	{
- 	  unsigned ix;
- 	  unsigned value = *ptr << 24;
- 
- 	  for (ix = 8; ix--; value <<= 1)
- 	    {
- 	      unsigned feedback;
- 
- 	      feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
- 	      crc32 <<= 1;
- 	      crc32 ^= feedback;
- 	    }
- 	}
-       while (*ptr++);
-       
-       gcov_crc32 = crc32;
-       
-       if (!gcov_list)
- 	atexit (gcov_exit);
-       
-       info->next = gcov_list;
-       gcov_list = info;
-     }
-   info->version = 0;
- }
- 
- /* Called before fork or exec - write out profile information gathered so
-    far and reset it to zero.  This avoids duplication or loss of the
-    profile information gathered so far.  */
- 
- void
- __gcov_flush (void)
- {
-   struct gcov_info *ptr;
- 
-   gcov_exit ();
-   for (ptr = gcov_list; ptr; ptr = ptr->next)
-     {
-       unsigned i;
-       
-       for (i = ptr->n_arc_counts; i--;)
- 	ptr->arc_counts[i] = 0;
-     }
- }
- 
- #endif /* L_gcov */
  
  #ifdef L_clear_cache
  /* Clear part of an instruction cache.  */
--- 1235,1240 ----
Index: libgcov.c
===================================================================
RCS file: libgcov.c
diff -N libgcov.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- libgcov.c	27 Jan 2003 21:42:43 -0000
***************
*** 0 ****
--- 1,473 ----
+ /* Routines required for instrumenting a program.  */
+ /* Compile this one with gcc.  */
+ /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+    2000, 2001, 2002, 2003  Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+ 
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file.  (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combine
+ executable.)
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING.  If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.  */
+ 
+ /* It is incorrect to include config.h here, because this file is being
+    compiled for the target, and hence definitions concerning only the host
+    do not apply.  */
+ 
+ #include "tconfig.h"
+ #include "tsystem.h"
+ #include "coretypes.h"
+ #include "tm.h"
+ 
+ #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
+ #include <stdio.h>
+ 
+ #include "gcov-io.h"
+ #include <string.h>
+ #if defined (TARGET_HAS_F_SETLKW)
+ #include <fcntl.h>
+ #include <errno.h>
+ #endif
+ 
+ /* Chain of per-object gcov structures.  */
+ static struct gcov_info *gcov_list;
+ 
+ /* A program checksum allows us to distinguish program data for an
+    object file included in multiple programs.  */
+ static unsigned gcov_crc32;
+ 
+ static void
+ gcov_version_mismatch (struct gcov_info *ptr, unsigned version)
+ {
+   unsigned expected = GCOV_VERSION;
+   unsigned ix;
+   char e[4], v[4];
+ 
+   for (ix = 4; ix--; expected >>= 8, version >>= 8)
+     {
+       e[ix] = expected;
+       v[ix] = version;
+     }
+   
+   fprintf (stderr,
+ 	   "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
+ 	   ptr->filename, e, v);
+ }
+ 
+ /* Dump the coverage counts. We merge with existing counts when
+    possible, to avoid growing the .da files ad infinitum. We use this
+    program's checksum to make sure we only accumulate whole program
+    statistics to the correct summary. An object file might be embedded
+    in two separate programs, and we must keep the two program
+    summaries separate.  */
+ 
+ static void
+ gcov_exit (void)
+ {
+   struct gcov_info *ptr;
+   unsigned ix, jx;
+   struct gcov_summary program;
+   gcov_type program_max_one = 0;
+   gcov_type program_max_sum = 0;
+   gcov_type program_sum = 0;
+   unsigned program_arcs = 0;
+   
+ #if defined (TARGET_HAS_F_SETLKW)
+   struct flock s_flock;
+ 
+   s_flock.l_type = F_WRLCK;
+   s_flock.l_whence = SEEK_SET;
+   s_flock.l_start = 0;
+   s_flock.l_len = 0; /* Until EOF.  */
+   s_flock.l_pid = getpid ();
+ #endif
+ 
+   memset (&program, 0, sizeof (program));
+   program.checksum = gcov_crc32;
+   
+   for (ptr = gcov_list; ptr; ptr = ptr->next)
+     {
+       FILE *da_file;
+       struct gcov_summary object;
+       struct gcov_summary local_prg;
+       int merging = 0;
+       long base;
+       const struct function_info *fn_info;
+       gcov_type *count_ptr;
+       gcov_type object_max_one = 0;
+ 
+       ptr->wkspc = 0;
+       if (!ptr->filename)
+ 	continue;
+ 
+       for (ix = ptr->n_arc_counts, count_ptr = ptr->arc_counts; ix--;)
+ 	{
+ 	  gcov_type count = *count_ptr++;
+ 
+ 	  if (count > object_max_one)
+ 	    object_max_one = count;
+ 	}
+       if (object_max_one > program_max_one)
+ 	program_max_one = object_max_one;
+       
+       memset (&local_prg, 0, sizeof (local_prg));
+       memset (&object, 0, sizeof (object));
+       
+       /* Open for modification */
+       if ((da_file = fopen (ptr->filename, "r+b")))
+ 	merging = 1;
+       else if ((da_file = fopen (ptr->filename, "w+b")))
+ 	;
+       else
+ 	{
+ 	  fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
+ 	  ptr->filename = 0;
+ 	  continue;
+ 	}
+ 
+ #if defined (TARGET_HAS_F_SETLKW)
+       /* After a fork, another process might try to read and/or write
+          the same file simultaneously.  So if we can, lock the file to
+          avoid race conditions.  */
+       while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
+ 	     && errno == EINTR)
+ 	continue;
+ #endif
+       if (merging)
+ 	{
+ 	  /* Merge data from file.  */
+ 	  unsigned tag, length;
+ 	      
+ 	  if (gcov_read_unsigned (da_file, &tag) || tag != GCOV_DATA_MAGIC)
+ 	    {
+ 	      fprintf (stderr, "profiling:%s:Not a gcov data file\n",
+ 		       ptr->filename);
+ 	    read_fatal:;
+ 	      fclose (da_file);
+ 	      ptr->filename = 0;
+ 	      continue;
+ 	    }
+ 	  if (gcov_read_unsigned (da_file, &length) || length != GCOV_VERSION)
+ 	    {
+ 	      gcov_version_mismatch (ptr, length);
+ 	      goto read_fatal;
+ 	    }
+ 	  
+ 	  /* Merge execution counts for each function.  */
+ 	  count_ptr = ptr->arc_counts;
+ 	  for (ix = ptr->n_functions, fn_info = ptr->functions;
+ 	       ix--; fn_info++)
+ 	    {
+ 	      if (gcov_read_unsigned (da_file, &tag)
+ 		  || gcov_read_unsigned (da_file, &length))
+ 		{
+ 		read_error:;
+ 		  fprintf (stderr, "profiling:%s:Error merging\n",
+ 			   ptr->filename);
+ 		  goto read_fatal;
+ 		}
+ 
+ 	      /* Check function */
+ 	      if (tag != GCOV_TAG_FUNCTION)
+ 		{
+ 		read_mismatch:;
+ 		  fprintf (stderr, "profiling:%s:Merge mismatch at %s\n",
+ 			   ptr->filename, fn_info->name);
+ 		  goto read_fatal;
+ 		}
+ 	      {
+ 		unsigned flength, checksum;
+ 		
+ 		if (gcov_read_unsigned (da_file, &flength)
+ 		    || gcov_skip_string (da_file, flength)
+ 		    || gcov_read_unsigned (da_file, &checksum))
+ 		  goto read_error;
+ 		if (flength != strlen (fn_info->name)
+ 		    || checksum != fn_info->checksum)
+ 		  goto read_mismatch;
+ 	      }
+ 	      /* Check arc counts */
+ 	      if (gcov_read_unsigned (da_file, &tag)
+ 		  || gcov_read_unsigned (da_file, &length))
+ 		goto read_error;
+ 	      if (tag != GCOV_TAG_ARC_COUNTS
+ 		  || length / 8 != fn_info->n_arc_counts)
+ 		goto read_mismatch;
+ 	      {
+ 		gcov_type count;
+ 		
+ 		for (jx = fn_info->n_arc_counts; jx--; count_ptr++)
+ 		  if (gcov_read_counter (da_file, &count))
+ 		    goto read_error;
+ 		  else
+ 		    *count_ptr += count;
+ 	      }
+ 	    }
+ 
+ 	  /* Check object summary */
+ 	  if (gcov_read_unsigned (da_file, &tag)
+ 	      || gcov_read_unsigned (da_file, &length))
+ 	    goto read_error;
+ 	  if (tag != GCOV_TAG_OBJECT_SUMMARY)
+ 	    goto read_mismatch;
+ 	  if (gcov_read_summary (da_file, &object))
+ 	    goto read_error;
+ 
+ 	  /* Check program summary */
+ 	  while (1)
+ 	    {
+ 	      long base = ftell (da_file);
+ 	      
+ 	      if (gcov_read_unsigned (da_file, &tag)
+ 		  || gcov_read_unsigned (da_file, &length))
+ 		{
+ 		  if (feof (da_file))
+ 		    break;
+ 		  goto read_error;
+ 		}
+ 	      if (tag != GCOV_TAG_PROGRAM_SUMMARY
+ 		  && tag != GCOV_TAG_PLACEHOLDER_SUMMARY
+ 		  && tag != GCOV_TAG_INCORRECT_SUMMARY)
+ 		goto read_mismatch;
+ 	      if (gcov_read_summary (da_file, &local_prg))
+ 		goto read_error;
+ 	      if (local_prg.checksum != program.checksum)
+ 		continue;
+ 	      if (tag == GCOV_TAG_PLACEHOLDER_SUMMARY)
+ 		{
+ 		  fprintf (stderr,
+ 			   "profiling:%s:Concurrent race detected\n",
+ 			   ptr->filename);
+ 		  goto read_fatal;
+ 		}
+ 	      merging = -1;
+ 	      if (tag != GCOV_TAG_PROGRAM_SUMMARY)
+ 		break;
+ 	      
+ 	      if (program.runs
+ 		  && memcmp (&program, &local_prg, sizeof (program)))
+ 		{
+ 		  fprintf (stderr, "profiling:%s:Invocation mismatch\n",
+ 			   ptr->filename);
+ 		  local_prg.runs = 0;
+ 		}
+ 	      else
+ 		memcpy (&program, &local_prg, sizeof (program));
+ 	      ptr->wkspc = base;
+ 	      break;
+ 	    }
+ 	  fseek (da_file, 0, SEEK_SET);
+ 	}
+ 
+       object.runs++;
+       object.arcs = ptr->n_arc_counts;
+       object.arc_sum = 0;
+       if (object.arc_max_one < object_max_one)
+ 	object.arc_max_one = object_max_one;
+       object.arc_sum_max += object_max_one;
+       
+       /* Write out the data.  */
+       if (/* magic */
+ 	  gcov_write_unsigned (da_file, GCOV_DATA_MAGIC)
+ 	  /* version number */
+ 	  || gcov_write_unsigned (da_file, GCOV_VERSION))
+ 	{
+ 	write_error:;
+ 	  fclose (da_file);
+ 	  fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
+ 	  ptr->filename = 0;
+ 	  continue;
+ 	}
+       
+       /* Write execution counts for each function.  */
+       count_ptr = ptr->arc_counts;
+       for (ix = ptr->n_functions, fn_info = ptr->functions; ix--; fn_info++)
+ 	{
+ 	  /* Announce function.  */
+ 	  if (gcov_write_unsigned (da_file, GCOV_TAG_FUNCTION)
+ 	      || !(base = gcov_reserve_length (da_file))
+ 	      /* function name */
+ 	      || gcov_write_string (da_file, fn_info->name,
+ 				    strlen (fn_info->name))
+ 	      /* function checksum */
+ 	      || gcov_write_unsigned (da_file, fn_info->checksum)
+ 	      || gcov_write_length (da_file, base))
+ 	    goto write_error;
+ 	  
+ 	  /* arc counts.  */
+ 	  if (gcov_write_unsigned (da_file, GCOV_TAG_ARC_COUNTS)
+ 	      || !(base = gcov_reserve_length (da_file)))
+ 	    goto write_error;
+ 	  
+ 	  for (jx = fn_info->n_arc_counts; jx--;)
+ 	    {
+ 	      gcov_type count = *count_ptr++;
+ 	      
+ 	      object.arc_sum += count;
+ 	      if (object.arc_max_sum < count)
+ 		object.arc_max_sum = count;
+ 	      if (gcov_write_counter (da_file, count))
+ 		goto write_error; /* RIP Edsger Dijkstra */
+ 	    }
+ 	  if (gcov_write_length (da_file, base))
+ 	    goto write_error;
+ 	}
+ 
+       /* Object file summary.  */
+       if (gcov_write_summary (da_file, GCOV_TAG_OBJECT_SUMMARY, &object))
+ 	goto write_error;
+ 
+       if (merging >= 0)
+ 	{
+ 	  if (fseek (da_file, 0, SEEK_END))
+ 	    goto write_error;
+ 	  ptr->wkspc = ftell (da_file);
+ 	  if (gcov_write_summary (da_file, GCOV_TAG_PLACEHOLDER_SUMMARY,
+ 				  &program))
+ 	    goto write_error;
+ 	}
+       else if (ptr->wkspc)
+ 	{
+ 	  /* Zap trailing program summary */
+ 	  if (fseek (da_file, ptr->wkspc, SEEK_SET))
+ 	    goto write_error;
+ 	  if (!local_prg.runs)
+ 	    ptr->wkspc = 0;
+ 	  if (gcov_write_unsigned (da_file,
+ 			     local_prg.runs ? GCOV_TAG_PLACEHOLDER_SUMMARY
+ 			     : GCOV_TAG_INCORRECT_SUMMARY))
+ 	    goto write_error;
+ 	}
+       if (fflush (da_file))
+ 	goto write_error;
+ 
+       if (fclose (da_file))
+ 	{
+ 	  fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
+ 	  ptr->filename = 0;
+ 	}
+       else
+ 	{
+ 	  program_arcs += ptr->n_arc_counts;
+ 	  program_sum += object.arc_sum;
+ 	  if (program_max_sum < object.arc_max_sum)
+ 	    program_max_sum = object.arc_max_sum;
+ 	}
+     }
+ 
+   /* Generate whole program statistics.  */
+   program.runs++;
+   program.arcs = program_arcs;
+   program.arc_sum = program_sum;
+   if (program.arc_max_one < program_max_one)
+     program.arc_max_one = program_max_one;
+   if (program.arc_max_sum < program_max_sum)
+     program.arc_max_sum = program_max_sum;
+   program.arc_sum_max += program_max_one;
+   
+   /* Upate whole program statistics.  */
+   for (ptr = gcov_list; ptr; ptr = ptr->next)
+     if (ptr->filename && ptr->wkspc)
+       {
+ 	FILE *da_file;
+ 	
+ 	da_file = fopen (ptr->filename, "r+b");
+ 	if (!da_file)
+ 	  {
+ 	    fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
+ 	    continue;
+ 	  }
+ 	
+ #if defined (TARGET_HAS_F_SETLKW)
+ 	while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
+ 	       && errno == EINTR)
+ 	  continue;
+ #endif
+ 	if (fseek (da_file, ptr->wkspc, SEEK_SET)
+  	    || gcov_write_summary (da_file, GCOV_TAG_PROGRAM_SUMMARY, &program)
+  	    || fflush (da_file))
+  	  fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
+ 	if (fclose (da_file))
+ 	  fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
+       }
+ }
+ 
+ /* Add a new object file onto the bb chain.  Invoked automatically
+    when running an object file's global ctors.  */
+ 
+ void
+ __gcov_init (struct gcov_info *info)
+ {
+   if (!info->version)
+     return;
+   if (info->version != GCOV_VERSION)
+     gcov_version_mismatch (info, info->version);
+   else
+     {
+       const char *ptr = info->filename;
+       unsigned crc32 = gcov_crc32;
+   
+       do
+ 	{
+ 	  unsigned ix;
+ 	  unsigned value = *ptr << 24;
+ 
+ 	  for (ix = 8; ix--; value <<= 1)
+ 	    {
+ 	      unsigned feedback;
+ 
+ 	      feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
+ 	      crc32 <<= 1;
+ 	      crc32 ^= feedback;
+ 	    }
+ 	}
+       while (*ptr++);
+       
+       gcov_crc32 = crc32;
+       
+       if (!gcov_list)
+ 	atexit (gcov_exit);
+       
+       info->next = gcov_list;
+       gcov_list = info;
+     }
+   info->version = 0;
+ }
+ 
+ /* Called before fork or exec - write out profile information gathered so
+    far and reset it to zero.  This avoids duplication or loss of the
+    profile information gathered so far.  */
+ 
+ void
+ __gcov_flush (void)
+ {
+   struct gcov_info *ptr;
+ 
+   gcov_exit ();
+   for (ptr = gcov_list; ptr; ptr = ptr->next)
+     {
+       unsigned i;
+       
+       for (i = ptr->n_arc_counts; i--;)
+ 	ptr->arc_counts[i] = 0;
+     }
+ }
Index: mklibgcc.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/mklibgcc.in,v
retrieving revision 1.52
diff -c -3 -p -r1.52 mklibgcc.in
*** mklibgcc.in	26 Jan 2003 09:17:13 -0000	1.52
--- mklibgcc.in	27 Jan 2003 21:42:44 -0000
***************
*** 12,17 ****
--- 12,18 ----
  # LIB2FUNCS_1
  # LIB2FUNCS_2
  # LIB2FUNCS_ST
+ # LIBGCOV
  # LIB2ADD
  # LIB2ADD_ST 
  # LIB2ADDEH
*************** make_compile='$(MAKE) GCC_FOR_TARGET="$(
*** 65,70 ****
--- 66,74 ----
  # Dependencies for libgcc2.c
  libgcc2_c_dep='stmp-dirs $(srcdir)/libgcc2.c $(CONFIG_H) coretypes.h $(TM_H) $(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs tsystem.h'" $LIB2ADDEHDEP"
  
+ # Dependencies for libgcov.c
+ libgcov_c_dep='stmp-dirs $(srcdir)/libgcov.c $(CONFIG_H) coretypes.h $(TM_H) $(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs tsystem.h'
+ 
  # Dependencies for fp-bit.c
  fpbit_c_dep='stmp-dirs config.status tsystem.h'
  
*************** for file in $LIB2ADD_ST; do
*** 249,254 ****
--- 253,277 ----
    libgcc2_st_objs="$libgcc2_st_objs ${oname}${objext}"
  done
  
+ #
+ # build libgcov components
+ #
+ 
+ libgcov_objs=""
+ 
+ for name in $LIBGCOV; do
+   for ml in $MULTILIBS; do
+     dir=`echo ${ml} | sed -e 's/;.*$//' -e 's/=/$(EQ)/g'`
+     flags=`echo ${ml} | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`;
+     out="libgcc/${dir}/${name}${objext}"
+ 
+     echo $out: $libgcov_c_dep
+     echo "	$gcc_compile" '$(MAYBE_USE_COLLECT2)' $flags -DL$name \
+       -c '$(srcdir)/libgcov.c' -o $out
+   done
+   libgcov_objs="$libgcov_objs ${name}${objext}"
+ done
+ 
  # SHLIB_MKMAP
  # SHLIB_MKMAP_OPTS
  # SHLIB_MAPFILES
*************** for ml in $MULTILIBS; do
*** 275,280 ****
--- 298,308 ----
      libgcc_st_objs="$libgcc_st_objs libgcc/${dir}/$o"
    done
  
+   libgcov_a_objs=""
+   for o in $libgcov_objs; do
+     libgcov_a_objs="$libgcov_a_objs libgcc/${dir}/$o"
+   done
+   
    if [ "$SHLIB_LINK" -a "$SHLIB_MKMAP" ]; then
      mapfile="libgcc/${dir}/libgcc.map"
      tmpmapfile="libgcc/${dir}/tmp-libgcc.map"
*************** for ml in $MULTILIBS; do
*** 314,319 ****
--- 342,353 ----
    echo '	$(AR_CREATE_FOR_TARGET)' ${dir}/libgcc.a $libgcc_a_objs
    echo '	$(RANLIB_FOR_TARGET)' ${dir}/libgcc.a
  
+   echo ""
+   echo "${dir}/libgcov.a: $libgcov_a_objs"
+   echo "	-rm -rf ${dir}/libgcov.a"
+   echo '	$(AR_CREATE_FOR_TARGET)' ${dir}/libgcov.a $libgcov_a_objs
+   echo '	$(RANLIB_FOR_TARGET)' ${dir}/libgcov.a
+ 
    if [ "$SHLIB_LINK" ]; then
  
      echo ""
*************** for ml in $MULTILIBS; do
*** 395,401 ****
    if [ $dir != . ]; then
      dirs="$dirs ${dir} libgcc/${dir}"
    fi
!   all="$all ${dir}/libgcc.a"
    if [ "$SHLIB_LINK" ]; then
      all="$all ${dir}/libgcc_eh.a"
      if [ -z "$SHLIB_MULTILIB" ]; then
--- 429,435 ----
    if [ $dir != . ]; then
      dirs="$dirs ${dir} libgcc/${dir}"
    fi
!   all="$all ${dir}/libgcc.a ${dir}/libgcov.a"
    if [ "$SHLIB_LINK" ]; then
      all="$all ${dir}/libgcc_eh.a"
      if [ -z "$SHLIB_MULTILIB" ]; then
*************** for ml in $MULTILIBS; do
*** 456,461 ****
--- 490,497 ----
    fi
    echo '	$(INSTALL_DATA)' ${dir}/libgcc.a ${ldir}/
    echo '	$(RANLIB_FOR_TARGET)' ${ldir}/libgcc.a
+   echo '	$(INSTALL_DATA)' ${dir}/libgcov.a ${ldir}/
+   echo '	$(RANLIB_FOR_TARGET)' ${ldir}/libgcov.a
  
    if [ "$SHLIB_LINK" ]; then
      echo '	$(INSTALL_DATA)' ${dir}/libgcc_eh.a ${ldir}/
Index: profile.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/profile.c,v
retrieving revision 1.106
diff -c -3 -p -r1.106 profile.c
*** profile.c	18 Jan 2003 22:32:06 -0000	1.106
--- profile.c	27 Jan 2003 21:42:48 -0000
*************** index_counts_file ()
*** 289,304 ****
    unsigned magic, version, ix, checksum;
    long *summary;
  
-   if (!da_file)
-     return 0;
-   counts_file_index = htab_create (10, htab_counts_index_hash, htab_counts_index_eq, htab_counts_index_del);
- 
    /* No .da file, no data.  */
    if (!da_file)
      return 0;
  
    /* Now index all profile sections.  */
- 
    rewind (da_file);
  
    summary = NULL;
--- 289,300 ----
    unsigned magic, version, ix, checksum;
    long *summary;
  
    /* No .da file, no data.  */
    if (!da_file)
      return 0;
+   counts_file_index = htab_create (10, htab_counts_index_hash, htab_counts_index_eq, htab_counts_index_del);
  
    /* Now index all profile sections.  */
    rewind (da_file);
  
    summary = NULL;
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.231
diff -c -3 -p -r1.231 invoke.texi
*** doc/invoke.texi	27 Jan 2003 18:06:39 -0000	1.231
--- doc/invoke.texi	27 Jan 2003 21:43:17 -0000
*************** allocation when it finishes.
*** 3035,3061 ****
  
  @item -fprofile-arcs
  @opindex fprofile-arcs
! Instrument @dfn{arcs} during compilation to generate coverage data or
! for profile-directed block ordering.  During execution the program
! records how many times each branch is executed and how many times it is
! taken.  When the compiled program exits it saves this data to a file
! called @file{@var{auxname}.da} for each source file.  @var{auxname} is
! generated from the name of the output file, if explicitly specified and
! it is not the final executable, otherwise it is the basename of the
! source file. In both cases any suffix is removed (e.g.  @file{foo.da}
! for input file @file{dir/foo.c}, or @file{dir/foo.da} for output file
! specified as @option{-o dir/foo.o}).
! 
! For profile-directed block ordering, compile the program with
! @option{-fprofile-arcs} plus optimization and code generation options,
! generate the arc profile information by running the program on a
! selected workload, and then compile the program again with the same
! optimization and code generation options plus
  @option{-fbranch-probabilities} (@pxref{Optimize Options,,Options that
  Control Optimization}).
  
! The other use of @option{-fprofile-arcs} is for use with @command{gcov},
! when it is used with the @option{-ftest-coverage} option.
  
  With @option{-fprofile-arcs}, for each function of your program GCC
  creates a program flow graph, then finds a spanning tree for the graph.
--- 3035,3080 ----
  
  @item -fprofile-arcs
  @opindex fprofile-arcs
! Add code so that program flow @dfn{arcs} are instrumented.  During
! execution the program records how many times each branch and call is
! executed and how many times it is taken or returns.  When the compiled
! program exits it saves this data to a file called
! @file{@var{auxname}.da} for each source file. The data may be used for
! profile-directed optimizations (@option{-fbranch-probabilities}), or for
! test coverage analysis (@option{-ftest-coverage}). Each object file's
! @var{auxname} is generated from the name of the output file, if
! explicitly specified and it is not the final executable, otherwise it is
! the basename of the source file. In both cases any suffix is removed
! (e.g.  @file{foo.da} for input file @file{dir/foo.c}, or
! @file{dir/foo.da} for output file specified as @option{-o dir/foo.o}).
! 
! @itemize
! 
! @item
! Compile the source files with @option{-fprofile-arcs} plus optimization
! and code generation options. For test coverage analysis, use the
! additional @option{-ftest-coverage} option. You do not need to profile
! every source file in a program.
! 
! @item
! Link your object files as normal.
! 
! @item
! Run the program on a representative workload to generate the arc profile
! information. This may be repeated any number of times.
! 
! @item
! For profile-directed optimizations, compile the source files again with
! the same optimization and code generation options plus
  @option{-fbranch-probabilities} (@pxref{Optimize Options,,Options that
  Control Optimization}).
  
! @item
! For test coverage analysis, use @command{gcov} to produce human readable
! information from the @file{.bbg} and @file{.da} files. Refer to the
! @command{gcov} documentation for further information.
! 
! @end itemize
  
  With @option{-fprofile-arcs}, for each function of your program GCC
  creates a program flow graph, then finds a spanning tree for the graph.
*************** block must be created to hold the instru
*** 3068,3101 ****
  @need 2000
  @item -ftest-coverage
  @opindex ftest-coverage
! Create data files for the @command{gcov} code-coverage utility
! (@pxref{Gcov,, @command{gcov}---a Test Coverage Program}).  See
! @option{-fprofile-arcs} option above for a description of @var{auxname}.
! 
! @table @gcctabopt
! @item @var{auxname}.bb
! A mapping from basic blocks to line numbers, which @command{gcov} uses to
! associate basic block execution counts with line numbers.
! 
! @item @var{auxname}.bbg
! A list of all arcs in the program flow graph.  This allows @command{gcov}
! to reconstruct the program flow graph, so that it can compute all basic
! block and arc execution counts from the information in the
! @file{@var{auxname}.da} file.
! @end table
! 
! Use @option{-ftest-coverage} with @option{-fprofile-arcs}; the latter
! option adds instrumentation to the program, which then writes
! execution counts to another data file:
! 
! @table @gcctabopt
! @item @var{auxname}.da
! Runtime arc execution counts, used in conjunction with the arc
! information in the file @file{@var{auxname}.bbg}.
! @end table
! 
! Coverage data will map better to the source files if
! @option{-ftest-coverage} is used without optimization.
  
  @item -d@var{letters}
  @opindex d
--- 3087,3099 ----
  @need 2000
  @item -ftest-coverage
  @opindex ftest-coverage
! Produce a graph file that the @command{gcov} code-coverage utility
! (@pxref{Gcov,, @command{gcov}---a Test Coverage Program}) can use to
! show program coverage. Each source file's data file is called
! @file{@var{auxname}.bbg}. Refer to the @option{-fprofile-arcs} option
! above for a description of @var{auxname} and instructions on how to
! generate test coverage data. Coverage data will match the source files
! more closely, if you do not optimize.
  
  @item -d@var{letters}
  @opindex d
Index: gcc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcc.c,v
retrieving revision 1.359
diff -c -3 -p -r1.359 gcc.c
*** gcc.c	19 Jan 2003 13:04:21 -0000	1.359
--- gcc.c	27 Jan 2003 22:24:37 -0000
*************** proper position among the other output f
*** 676,682 ****
  %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
      %(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r} %{s} %{t}\
      %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
!     %{static:} %{L*} %(link_libgcc) %o %{!nostdlib:%{!nodefaultlibs:%(link_gcc_c_sequence)}}\
      %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
  #endif
  
--- 676,683 ----
  %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
      %(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r} %{s} %{t}\
      %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
!     %{static:} %{L*} %(link_libgcc) %o %{fprofile-arcs:-lgcov}\
!     %{!nostdlib:%{!nodefaultlibs:%(link_gcc_c_sequence)}}\
      %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
  #endif
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]