summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2003-01-27 23:22:17 +0000
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2003-01-27 23:22:17 +0000
commitad8617cf3aae37463a6d61baa16b7b95a7520ead (patch)
tree2a2a67d83f3dfe20178bb96db57b38e585380170 /gcc
parent2dd7852ce343c33ec54fe545c112612f88c84751 (diff)
downloadgcc-ad8617cf3aae37463a6d61baa16b7b95a7520ead.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@61905 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/Makefile.in33
-rw-r--r--gcc/doc/invoke.texi90
-rw-r--r--gcc/gcc.c3
-rw-r--r--gcc/libgcc2.c439
-rw-r--r--gcc/libgcov.c473
-rw-r--r--gcc/mklibgcc.in38
-rw-r--r--gcc/profile.c6
8 files changed, 602 insertions, 501 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0d7452e481b..bb0804fbdfa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,24 @@
+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.
+
2003-01-27 Jerry Quinn <jlquinn@optonline.net>
* gcc/doc/invoke.texi (Optimization Options): Group together
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 572378eb0fa..4cb7de27116 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -825,7 +825,10 @@ LIB2FUNCS_2 = _floatdixf _fixunsxfsi _fixtfdi _fixunstfdi _floatditf \
_addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors
# Defined in libgcc2.c, included only in the static library.
-LIB2FUNCS_ST = _eprintf _gcov __gcc_bcmp
+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 \
@@ -1054,6 +1057,7 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext
LIB2FUNCS_1='$(LIB2FUNCS_1)' \
LIB2FUNCS_2='$(LIB2FUNCS_2)' \
LIB2FUNCS_ST='$(LIB2FUNCS_ST)' \
+ LIBGCOV='$(LIBGCOV)' \
LIB2ADD='$(LIB2ADD)' \
LIB2ADD_ST='$(LIB2ADD_ST)' \
LIB2ADDEH='$(LIB2ADDEH)' \
@@ -1082,12 +1086,14 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext
# 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) \
+ 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)" \
@@ -2728,7 +2734,8 @@ mostlyclean: $(INTL_MOSTLYCLEAN) lang.mostlyclean
# 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 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
@@ -2984,7 +2991,7 @@ install-man: installdirs $(GENERATED_MANPAGES) lang.install-man
-chmod a-x $(DESTDIR)$(man7dir)/gpl$(man7ext)
# Install the library.
-install-libgcc: libgcc.mk libgcc.a installdirs
+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)" \
@@ -3004,7 +3011,7 @@ install-libgcc: libgcc.mk libgcc.a installdirs
slibdir="$(slibdir)" \
-f libgcc.mk install
-# Install multiple versions of libgcc.a.
+# 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)" \
@@ -3611,9 +3618,11 @@ stage1-start:
-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
+ -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
@@ -3641,9 +3650,11 @@ stage2-start:
-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
+ -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
@@ -3667,9 +3678,11 @@ stage3-start:
-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
+ -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
@@ -3693,9 +3706,11 @@ stage4-start:
-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
+ -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
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index f8a03960d70..e4c39c59011 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -3035,27 +3035,46 @@ allocation when it finishes.
@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
+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}).
-The other use of @option{-fprofile-arcs} is for use with @command{gcov},
-when it is used with the @option{-ftest-coverage} option.
+@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.
@@ -3068,34 +3087,13 @@ block must be created to hold the instrumentation code.
@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.
+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
diff --git a/gcc/gcc.c b/gcc/gcc.c
index ca3a51337f6..3a36d3517b1 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -676,7 +676,8 @@ proper position among the other output files. */
%{!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)}}\
+ %{static:} %{L*} %(link_libgcc) %o %{fprofile-arcs:-lgcov}\
+ %{!nostdlib:%{!nodefaultlibs:%(link_gcc_c_sequence)}}\
%{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
#endif
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c
index a47dfd10a32..deb772fa629 100644
--- a/gcc/libgcc2.c
+++ b/gcc/libgcc2.c
@@ -1235,445 +1235,6 @@ __eprintf (const char *string, const char *expression,
#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. */
diff --git a/gcc/libgcov.c b/gcc/libgcov.c
new file mode 100644
index 00000000000..57bfb263265
--- /dev/null
+++ b/gcc/libgcov.c
@@ -0,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;
+ }
+}
diff --git a/gcc/mklibgcc.in b/gcc/mklibgcc.in
index faa5a69fb59..a18b8dd0a8b 100644
--- a/gcc/mklibgcc.in
+++ b/gcc/mklibgcc.in
@@ -12,6 +12,7 @@
# LIB2FUNCS_1
# LIB2FUNCS_2
# LIB2FUNCS_ST
+# LIBGCOV
# LIB2ADD
# LIB2ADD_ST
# LIB2ADDEH
@@ -65,6 +66,9 @@ make_compile='$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
# 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'
@@ -249,6 +253,25 @@ for file in $LIB2ADD_ST; do
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
@@ -275,6 +298,11 @@ for ml in $MULTILIBS; do
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"
@@ -314,6 +342,12 @@ for ml in $MULTILIBS; do
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 ""
@@ -395,7 +429,7 @@ for ml in $MULTILIBS; do
if [ $dir != . ]; then
dirs="$dirs ${dir} libgcc/${dir}"
fi
- all="$all ${dir}/libgcc.a"
+ all="$all ${dir}/libgcc.a ${dir}/libgcov.a"
if [ "$SHLIB_LINK" ]; then
all="$all ${dir}/libgcc_eh.a"
if [ -z "$SHLIB_MULTILIB" ]; then
@@ -456,6 +490,8 @@ for ml in $MULTILIBS; do
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}/
diff --git a/gcc/profile.c b/gcc/profile.c
index 5ee790a14df..de2d309b449 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -289,16 +289,12 @@ index_counts_file ()
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;
+ 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;