* gcov-io.h (GCOV_LOCKED): New #define.
(GCOV_LINKAGE): Make sure it is #defined.
(gcov_write_string, gcov_write_tag, gcov_write_length,
gcov_read_string, gcov_time): Poison in libgcov.
(gcov_seek_end): Remove.
(gcov_write_tag_length, gcov_sync, gcov_rewrite): New.
(GCOV_TAG_FUNCTION_LENGTH, GCOV_TAG_BLOCKS_LENGTH,
GCOV_TAG_ARCS_LENGTH, GCOV_TAG_COUNTER_LENGTH,
GCOV_TAG_SUMMARY_LENGTH): New #defines.
(gcov_write_tag, gcov_write_length): Not in libgcov.
* gcov-io.c (gcov_open): Use GCOV_LOCKED.
(gcov_write_tag, gcov_write_length): Not in libgcov.
(gcov_write_tag_length): New.
(gcov_write_summary): Use gcov_write_tag_length.
* libgcov.c: Always #include gcov-io.h.
(IN_LIBGCOV): -1 for inhibit_libc, +1 otherwise.
(GCOV_LINKAGE): Define to nothing for L_gcov.
(gcov_exit): Replace gcov_write_tag, gcov_write_length with
gcov_write_tag_length. Use gcov_rewrite & gcov_seek.
* gcov.c (read_graph_file): Replace gcov_seek by gcov_sync.
(read_count_file): Likewise.
* gcov-dump.c (dump_file): Likewise.
* coverag.c (read_counts_file): Likewise.
From-SVN: r66555
+2003-05-07 Nathan Sidwell <nathan@codesourcery.com>
+
+ * gcov-io.h (GCOV_LOCKED): New #define.
+ (GCOV_LINKAGE): Make sure it is #defined.
+ (gcov_write_string, gcov_write_tag, gcov_write_length,
+ gcov_read_string, gcov_time): Poison in libgcov.
+ (gcov_seek_end): Remove.
+ (gcov_write_tag_length, gcov_sync, gcov_rewrite): New.
+ (GCOV_TAG_FUNCTION_LENGTH, GCOV_TAG_BLOCKS_LENGTH,
+ GCOV_TAG_ARCS_LENGTH, GCOV_TAG_COUNTER_LENGTH,
+ GCOV_TAG_SUMMARY_LENGTH): New #defines.
+ (gcov_write_tag, gcov_write_length): Not in libgcov.
+ * gcov-io.c (gcov_open): Use GCOV_LOCKED.
+ (gcov_write_tag, gcov_write_length): Not in libgcov.
+ (gcov_write_tag_length): New.
+ (gcov_write_summary): Use gcov_write_tag_length.
+ * libgcov.c: Always #include gcov-io.h.
+ (IN_LIBGCOV): -1 for inhibit_libc, +1 otherwise.
+ (GCOV_LINKAGE): Define to nothing for L_gcov.
+ (gcov_exit): Replace gcov_write_tag, gcov_write_length with
+ gcov_write_tag_length. Use gcov_rewrite & gcov_seek.
+ * gcov.c (read_graph_file): Replace gcov_seek by gcov_sync.
+ (read_count_file): Likewise.
+ * gcov-dump.c (dump_file): Likewise.
+ * coverag.c (read_counts_file): Likewise.
+
2003-05-06 Mark Mitchell <mark@codesourcery.com>
PR other/10658
for (ix = 0; ix != n_counts; ix++)
entry->counts[ix] += gcov_read_counter ();
}
- gcov_seek (offset, length);
+ gcov_sync (offset, length);
if ((error = gcov_is_error ()))
{
warning (error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
printf ("%s:record size mismatch %lu bytes unread\n",
filename, length - actual_length);
}
- gcov_seek (base, length);
+ gcov_sync (base, length);
if ((error = gcov_is_error ()))
{
printf (error < 0 ? "%s:counter overflow at %lu\n" :
{
int result = 1;
size_t alloc = 1024;
-#if defined (TARGET_HAS_F_SETLKW) && IN_LIBGCOV
+#if GCOV_LOCKED
struct flock s_flock;
s_flock.l_type = F_WRLCK;
if (!gcov_var.file)
return 0;
-#if defined (TARGET_HAS_F_SETLKW) && IN_LIBGCOV
+#if GCOV_LOCKED
while (fcntl (fileno (gcov_var.file), F_SETLKW, &s_flock)
&& errno == EINTR)
continue;
}
#endif
+#if !IN_LIBGCOV
/* Write a tag TAG and reserve space for the record length. Return a
value to be used for gcov_write_length. */
}
}
}
+#endif
+
+/* Write a tag TAG and length LENGTH. */
+
+GCOV_LINKAGE void
+gcov_write_tag_length (unsigned tag, unsigned length)
+{
+ unsigned char *buffer = gcov_write_bytes (8);
+ unsigned ix;
+
+ if (!buffer)
+ return;
+ for (ix = 4; ix--; )
+ {
+ buffer[ix] = tag;
+ tag >>= 8;
+ }
+ for (ix = 4; ix--; )
+ {
+ buffer[ix + 4] = length;
+ length >>= 8;
+ }
+ return;
+}
#if IN_LIBGCOV
/* Write a summary structure to the gcov file. Return non-zero on
{
unsigned ix;
const struct gcov_ctr_summary *csum;
- unsigned long base;
- base = gcov_write_tag (tag);
+ gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH);
gcov_write_unsigned (summary->checksum);
for (csum = summary->ctrs, ix = GCOV_COUNTERS; ix--; csum++)
{
gcov_write_counter (csum->run_max);
gcov_write_counter (csum->sum_max);
}
- gcov_write_length (base);
}
#endif /* IN_LIBGCOV */
#else
#define GCOV_LOCKED 0
#endif
-#endif /* IN_LIBGCOV */
+#else /* !IN_LIBGCOV */
+#if defined (HOST_HAS_F_SETLKW)
+#define GCOV_LOCKED 1
+#else
+#define GCOV_LOCKED 0
+#endif
#if IN_GCOV
+#define GCOV_LINKAGE static
typedef HOST_WIDEST_INT gcov_type;
#if IN_GCOV > 0
#include <sys/types.h>
#endif
#endif
+#endif /* !IN_LIBGCOV */
/* In gcov we want function linkage to be static, so we do not
polute the global namespace. In libgcov we need these functions
In the compiler we want it extern, so that they can be accessed from
elsewhere. */
#if IN_LIBGCOV
-
-#define GCOV_LINKAGE /* nothing */
#define gcov_var __gcov_var
#define gcov_open __gcov_open
#define gcov_close __gcov_close
#define gcov_write_bytes __gcov_write_bytes
#define gcov_write_unsigned __gcov_write_unsigned
#define gcov_write_counter __gcov_write_counter
-#define gcov_write_string __gcov_write_string
-#define gcov_write_tag __gcov_write_tag
-#define gcov_write_length __gcov_write_length
+#pragma GCC poison gcov_write_string
+#pragma GCC poison gcov_write_tag
+#pragma GCC poison gcov_write_length
+#define gcov_write_tag_length __gcov_write_tag_length
#define gcov_write_summary __gcov_write_summary
#define gcov_read_bytes __gcov_read_bytes
#define gcov_read_unsigned __gcov_read_unsigned
#define gcov_read_counter __gcov_read_counter
-#define gcov_read_string __gcov_read_string
+#pragma GCC poison gcov_read_string
#define gcov_read_summary __gcov_read_summary
#define gcov_position __gcov_position
+#define gcov_sync __gcov_sync
#define gcov_seek __gcov_seek
-#define gcov_seek_end __gcov_seek_end
+#define gcov_rewrite __gcov_rewrite
#define gcov_is_eof __gcov_is_eof
#define gcov_is_error __gcov_is_error
-#define gcov_time __gcov_time
-
-#elif IN_GCOV
-
-#define GCOV_LINKAGE static
-
-#else /* !IN_LIBGCOV && !IN_GCOV */
+#pragma GCC poison gcov_time
+#endif
#ifndef GCOV_LINKAGE
#define GCOV_LINKAGE extern
#endif
-#endif
-
/* File suffixes. */
#define GCOV_DATA_SUFFIX ".da"
#define GCOV_GRAPH_SUFFIX ".bbg"
the data file. */
#define GCOV_TAG_FUNCTION ((unsigned)0x01000000)
+#define GCOV_TAG_FUNCTION_LENGTH (2 * 4)
#define GCOV_TAG_BLOCKS ((unsigned)0x01410000)
+#define GCOV_TAG_BLOCKS_LENGTH(NUM) ((NUM) * 4)
#define GCOV_TAG_ARCS ((unsigned)0x01430000)
+#define GCOV_TAG_ARCS_LENGTH(NUM) (1 * 4 + (NUM) * (2 * 4))
#define GCOV_TAG_LINES ((unsigned)0x01450000)
#define GCOV_TAG_COUNTER_BASE ((unsigned)0x01a10000) /* First counter */
+#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 8)
#define GCOV_TAG_OBJECT_SUMMARY ((unsigned)0xa1000000)
#define GCOV_TAG_PROGRAM_SUMMARY ((unsigned)0xa3000000)
+#define GCOV_TAG_SUMMARY_LENGTH (1 * 4 + GCOV_COUNTERS * (2 * 4 + 3 * 8))
/* Counters that are collected. */
#define GCOV_COUNTER_ARCS 0 /* Arc transitions. */
extern void __gcov_merge_add (gcov_type *, unsigned);
#endif /* IN_LIBGCOV */
+#if IN_LIBGCOV >= 0
+
/* Because small reads and writes, interspersed with seeks cause lots
of disk activity, we buffer the entire count files. */
#else
GCOV_LINKAGE void gcov_write_string (const char *);
#endif
+#if !IN_LIBGCOV
GCOV_LINKAGE unsigned long gcov_write_tag (unsigned);
GCOV_LINKAGE void gcov_write_length (unsigned long /*position*/);
+#endif
+GCOV_LINKAGE void gcov_write_tag_length (unsigned, unsigned);
#if IN_LIBGCOV
GCOV_LINKAGE void gcov_write_summary (unsigned, const struct gcov_summary *);
#endif
#endif
GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *);
static unsigned long gcov_position (void);
-static void gcov_seek (unsigned long /*base*/, unsigned /*length */);
-static unsigned long gcov_seek_end (void);
+static void gcov_sync (unsigned long /*base*/, unsigned /*length */);
+static void gcov_seek (unsigned long /*position*/);
+static void gcov_rewrite (void);
static int gcov_is_eof (void);
static int gcov_is_error (void);
#if IN_GCOV > 0
gcov_save_position, LENGTH should be a record length, or zero. */
static inline void
-gcov_seek (unsigned long base, unsigned length)
+gcov_sync (unsigned long base, unsigned length)
{
if (gcov_var.buffer)
{
/* Move to the end of the gcov file. */
-static inline unsigned long
-gcov_seek_end ()
+static inline void
+gcov_seek (unsigned long base)
{
- gcov_var.position = gcov_var.length;
- return gcov_var.position;
+ gcov_var.position = base < gcov_var.length ? base : gcov_var.length;
+}
+
+/* Move to beginning of file and intialize for writing. */
+
+static inline void
+gcov_rewrite (void)
+{
+ gcov_var.position = 0;
}
/* Tests whether we have reached end of .da file. */
return gcov_var.file ? gcov_var.error : 1;
}
+#endif /* IN_LIBGCOV >= 0 */
+
#endif /* GCC_GCOV_IO_H */
fn = NULL;
current_tag = 0;
}
- gcov_seek (base, length);
+ gcov_sync (base, length);
if (gcov_is_error ())
{
corrupt:;
for (ix = 0; ix != fn->num_counts; ix++)
fn->counts[ix] += gcov_read_counter ();
}
- gcov_seek (base, length);
+ gcov_sync (base, length);
if ((error = gcov_is_error ()))
{
fnotice (stderr, error < 0
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
-#if defined(inhibit_libc)
-/* If libc and its header files are not available, provide dummy functions. */
-
-#ifdef L_gcov
-void __gcov_init (void *p);
-void __gcov_flush (void);
-
-void __gcov_init (void *p) { }
-void __gcov_flush (void) { }
-#endif
-
-#ifdef L_gcov_merge_add
-void __gcov_merge_add (void *, unsigned);
-
-void __gcov_merge_add (void *counters, unsigned n_counters) { }
-#endif
-
-#else
-
/* 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 "coretypes.h"
#include "tm.h"
+#if defined(inhibit_libc)
+#define IN_LIBGCOV (-1)
+#else
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
#include <stdio.h>
+#define IN_LIBGCOV 1
+#if defined(L_gcov)
+#define GCOV_LINKAGE /* nothing */
+#endif
+#endif
+#include "gcov-io.h"
+
+#if defined(inhibit_libc)
+/* If libc and its header files are not available, provide dummy functions. */
+
+#ifdef L_gcov
+void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
+void __gcov_flush (void) {}
+#endif
+
+#ifdef L_gcov_merge_add
+void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
+ unsigned n_counters __attribute__ ((unused))) {}
+#endif
+
+#else
#include <string.h>
-#if defined (TARGET_HAS_F_SETLKW)
+#if GCOV_LOCKED
#include <fcntl.h>
#include <errno.h>
#endif
-#define IN_LIBGCOV 1
-#include "gcov-io.h"
#ifdef L_gcov
#include "gcov-io.c"
struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
int error;
int merging;
- unsigned long base;
unsigned tag, length;
- unsigned long summary_pos = 0;
+ unsigned long summary_pos = ~0UL;
/* Totals for this object file. */
memset (&this_object, 0, sizeof (this_object));
/* Check function */
if (tag != GCOV_TAG_FUNCTION
+ || length != GCOV_TAG_FUNCTION_LENGTH
|| gcov_read_unsigned () != fi_ptr->ident
|| gcov_read_unsigned () != fi_ptr->checksum)
{
for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
if ((1 << t_ix) & gi_ptr->ctr_mask)
{
- unsigned n_counts;
- gcov_merge_fn merge;
+ unsigned n_counts = fi_ptr->n_ctrs[c_ix];
+ gcov_merge_fn merge = gi_ptr->counts[c_ix].merge;
tag = gcov_read_unsigned ();
length = gcov_read_unsigned ();
-
if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
- || fi_ptr->n_ctrs[c_ix] * 8 != length)
+ || length != GCOV_TAG_COUNTER_LENGTH (n_counts))
goto read_mismatch;
- n_counts = fi_ptr->n_ctrs[c_ix];
- merge = gi_ptr->counts[c_ix].merge;
(*merge) (values[c_ix], n_counts);
values[c_ix] += n_counts;
c_ix++;
goto read_error;
}
- /* Check object summary */
- if (gcov_read_unsigned () != GCOV_TAG_OBJECT_SUMMARY)
- goto read_mismatch;
- gcov_read_unsigned ();
- gcov_read_summary (&object);
-
- /* Check program summary */
+ /* Check program & object summary */
while (!gcov_is_eof ())
{
- base = gcov_position ();
+ unsigned long base = gcov_position ();
+ int is_program;
+
tag = gcov_read_unsigned ();
- gcov_read_unsigned ();
- if (tag != GCOV_TAG_PROGRAM_SUMMARY)
+ length = gcov_read_unsigned ();
+ is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
+ if (length != GCOV_TAG_SUMMARY_LENGTH
+ || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY))
goto read_mismatch;
- gcov_read_summary (&program);
+ gcov_read_summary (is_program ? &program : &object);
if ((error = gcov_is_error ()))
{
read_error:;
fprintf (stderr, error < 0 ?
"profiling:%s:Overflow merging\n" :
- "profiling:%s:Error merging\n",
- gi_ptr->filename);
+ "profiling:%s:Error merging\n", gi_ptr->filename);
goto read_fatal;
}
- if (program.checksum != gcov_crc32)
+ if (!is_program || program.checksum != gcov_crc32)
continue;
summary_pos = base;
break;
}
- gcov_seek (0, 0);
+ gcov_rewrite ();
}
else
memset (&object, 0, sizeof (object));
- if (!summary_pos)
+ if (!(summary_pos + 1))
memset (&program, 0, sizeof (program));
/* Merge the summaries. */
((const char *) fi_ptr + fi_stride))
{
/* Announce function. */
- base = gcov_write_tag (GCOV_TAG_FUNCTION);
+ gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH);
gcov_write_unsigned (fi_ptr->ident);
gcov_write_unsigned (fi_ptr->checksum);
- gcov_write_length (base);
for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
if ((1 << t_ix) & gi_ptr->ctr_mask)
{
- unsigned n_counts;
+ unsigned n_counts = fi_ptr->n_ctrs[c_ix];
gcov_type *c_ptr;
- base = gcov_write_tag (GCOV_TAG_FOR_COUNTER (t_ix));
+ gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
+ GCOV_TAG_COUNTER_LENGTH (n_counts));
c_ptr = values[c_ix];
- for (n_counts = fi_ptr->n_ctrs[c_ix]; n_counts--; c_ptr++)
- gcov_write_counter (*c_ptr);
+ while (n_counts--)
+ gcov_write_counter (*c_ptr++);
values[c_ix] = c_ptr;
- gcov_write_length (base);
c_ix++;
}
}
gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
/* Generate whole program statistics. */
- if (summary_pos)
- gcov_seek (summary_pos, 0);
- else
- gcov_seek_end ();
+ gcov_seek (summary_pos);
gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
if ((error = gcov_close ()))
- {
fprintf (stderr, error < 0 ?
"profiling:%s:Overflow writing\n" :
"profiling:%s:Error writing\n",
gi_ptr->filename);
- gi_ptr->filename = 0;
- }
}
}