diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2003-01-27 23:22:17 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2003-01-27 23:22:17 +0000 |
commit | 23af32e6ea2031cb4bffc1edc8d0368d5e5dfada (patch) | |
tree | 2a2a67d83f3dfe20178bb96db57b38e585380170 /gcc/libgcc2.c | |
parent | acabc2201e43691ffb41b2cee2de1e628dfce9f4 (diff) | |
download | gcc-23af32e6ea2031cb4bffc1edc8d0368d5e5dfada.zip gcc-23af32e6ea2031cb4bffc1edc8d0368d5e5dfada.tar.gz gcc-23af32e6ea2031cb4bffc1edc8d0368d5e5dfada.tar.bz2 |
Makefile.in (LIB2FUNCS_ST): Remove _gcov.
* 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.
From-SVN: r61905
Diffstat (limited to 'gcc/libgcc2.c')
-rw-r--r-- | gcc/libgcc2.c | 439 |
1 files changed, 0 insertions, 439 deletions
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index a47dfd1..deb772f 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. */ |