Commit 7d63a2fa by Nathan Sidwell Committed by Nathan Sidwell

gcov-io.h (gcov_write_bytes, [...]): Remove here.

	* gcov-io.h (gcov_write_bytes, gcov_read_bytes): Remove here.
	(GCOV_TAG_*) Force type to gcov_unsigned_t.
	(GCOV_CHECK, GCOV_CHECK_READING, GCOV_CHECK_WRITING): New.
	(struct gcov_var): Remove modified. Add start, length, offset,
	overread. Have buffer array for libgcov.
	(gcov_sync, gcov_seek): Definitions moved to gcov-io.c.
	(gcov_position, gcov_rewrite, gcov_is_eof): Adjust.
	* gcov-io.c (gcov_open): Set mode, do not read anything.
	(gcov_close): Write final block.
	 (gcov_write_block, gcov_allocate): New.
	(gcov_write_bytes): Make static. Write or allocate buffer.
	(gcov_write_unsigned, gcov_write_counter): Buffer can never be
	null.
	(gcov_write_string): Adjust.
	(gcov_write_tag)
	(gcov_write_length): Adjust. Flush the block.
	(gcov_write_tag_length): Buffer can never be null.
	(gcov_read_bytes): Make static. Read in block.
	(gcov_sync): Moved here. Adjust.
	(gcov_seek): Moved here. Adjust.
	* coverage.c (read_counts_file): Adjust.
	* gcov-dump.c (print_prefix): Add position parameter.
	(flag_dump_positions): New flag.
	(options, main, print_usage): Add it.
	(dump_file, tag_blocks, tag_arcs, tag_lines, tag_counters,
	tag_summary): Adjust.
	* gcov.c (read_graph_file, read_count_file): Adjust.
	* libgcov.c (gcov_exit): Adjust.

From-SVN: r66805
parent 990f4800
2003-05-14 Nathan Sidwell <nathan@codesourcery.com> 2003-05-14 Nathan Sidwell <nathan@codesourcery.com>
* gcov-io.h (gcov_write_bytes, gcov_read_bytes): Remove here.
(GCOV_TAG_*) Force type to gcov_unsigned_t.
(GCOV_CHECK, GCOV_CHECK_READING, GCOV_CHECK_WRITING): New.
(struct gcov_var): Remove modified. Add start, length, offset,
overread. Have buffer array for libgcov.
(gcov_sync, gcov_seek): Definitions moved to gcov-io.c.
(gcov_position, gcov_rewrite, gcov_is_eof): Adjust.
* gcov-io.c (gcov_open): Set mode, do not read anything.
(gcov_close): Write final block.
(gcov_write_block, gcov_allocate): New.
(gcov_write_bytes): Make static. Write or allocate buffer.
(gcov_write_unsigned, gcov_write_counter): Buffer can never be
null.
(gcov_write_string): Adjust.
(gcov_write_tag)
(gcov_write_length): Adjust. Flush the block.
(gcov_write_tag_length): Buffer can never be null.
(gcov_read_bytes): Make static. Read in block.
(gcov_sync): Moved here. Adjust.
(gcov_seek): Moved here. Adjust.
* coverage.c (read_counts_file): Adjust.
* gcov-dump.c (print_prefix): Add position parameter.
(flag_dump_positions): New flag.
(options, main, print_usage): Add it.
(dump_file, tag_blocks, tag_arcs, tag_lines, tag_counters,
tag_summary): Adjust.
* gcov.c (read_graph_file, read_count_file): Adjust.
* libgcov.c (gcov_exit): Adjust.
* Makefile.in (LIBGCC_DEPS): Use $(srcdir) on gcov files * Makefile.in (LIBGCC_DEPS): Use $(srcdir) on gcov files
(libgcov.a): Depend on libgcc.a. (libgcov.a): Depend on libgcc.a.
(gcov.o, gcov-dump.o): Add gcov-io.c. (gcov.o, gcov-dump.o): Add gcov-io.c.
......
...@@ -158,7 +158,9 @@ read_counts_file () ...@@ -158,7 +158,9 @@ read_counts_file ()
unsigned ix; unsigned ix;
counts_entry_t *summaried = NULL; counts_entry_t *summaried = NULL;
unsigned seen_summary = 0; unsigned seen_summary = 0;
gcov_unsigned_t tag;
int error = 0;
if (!gcov_open (da_file_name, 1)) if (!gcov_open (da_file_name, 1))
return; return;
...@@ -187,13 +189,11 @@ read_counts_file () ...@@ -187,13 +189,11 @@ read_counts_file ()
counts_hash = htab_create (10, counts_hash = htab_create (10,
htab_counts_entry_hash, htab_counts_entry_eq, htab_counts_entry_hash, htab_counts_entry_eq,
htab_counts_entry_del); htab_counts_entry_del);
while (!gcov_is_eof ()) while ((tag = gcov_read_unsigned ()))
{ {
gcov_unsigned_t tag, length; gcov_unsigned_t length;
gcov_position_t offset; gcov_position_t offset;
int error;
tag = gcov_read_unsigned ();
length = gcov_read_unsigned (); length = gcov_read_unsigned ();
offset = gcov_position (); offset = gcov_position ();
if (tag == GCOV_TAG_FUNCTION) if (tag == GCOV_TAG_FUNCTION)
...@@ -284,14 +284,16 @@ read_counts_file () ...@@ -284,14 +284,16 @@ read_counts_file ()
} }
gcov_sync (offset, length); gcov_sync (offset, length);
if ((error = gcov_is_error ())) if ((error = gcov_is_error ()))
{ break;
warning (error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
da_file_name);
htab_delete (counts_hash);
break;
}
} }
if (!gcov_is_eof ())
{
warning (error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
da_file_name);
htab_delete (counts_hash);
}
gcov_close (); gcov_close ();
} }
......
...@@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA. */
#include "gcov-io.c" #include "gcov-io.c"
static void dump_file PARAMS ((const char *)); static void dump_file PARAMS ((const char *));
static void print_prefix PARAMS ((const char *, unsigned)); static void print_prefix PARAMS ((const char *, unsigned, gcov_position_t));
static void print_usage PARAMS ((void)); static void print_usage PARAMS ((void));
static void print_version PARAMS ((void)); static void print_version PARAMS ((void));
static void tag_function PARAMS ((const char *, unsigned, unsigned)); static void tag_function PARAMS ((const char *, unsigned, unsigned));
...@@ -47,12 +47,14 @@ typedef struct tag_format ...@@ -47,12 +47,14 @@ typedef struct tag_format
} tag_format_t; } tag_format_t;
static int flag_dump_contents = 0; static int flag_dump_contents = 0;
static int flag_dump_positions = 0;
static const struct option options[] = static const struct option options[] =
{ {
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'v' },
{ "long", no_argument, NULL, 'l' }, { "long", no_argument, NULL, 'l' },
{ "positions", no_argument, NULL, 'o' },
}; };
static const tag_format_t tag_table[] = static const tag_format_t tag_table[] =
...@@ -75,7 +77,7 @@ int main (argc, argv) ...@@ -75,7 +77,7 @@ int main (argc, argv)
{ {
int opt; int opt;
while ((opt = getopt_long (argc, argv, "hlv", options, NULL)) != -1) while ((opt = getopt_long (argc, argv, "hlpv", options, NULL)) != -1)
{ {
switch (opt) switch (opt)
{ {
...@@ -88,6 +90,9 @@ int main (argc, argv) ...@@ -88,6 +90,9 @@ int main (argc, argv)
case 'l': case 'l':
flag_dump_contents = 1; flag_dump_contents = 1;
break; break;
case 'p':
flag_dump_positions = 1;
break;
default: default:
fprintf (stderr, "unknown flag `%c'\n", opt); fprintf (stderr, "unknown flag `%c'\n", opt);
} }
...@@ -106,6 +111,7 @@ print_usage () ...@@ -106,6 +111,7 @@ print_usage ()
printf (" -h, --help Print this help\n"); printf (" -h, --help Print this help\n");
printf (" -v, --version Print version number\n"); printf (" -v, --version Print version number\n");
printf (" -l, --long Dump record contents too\n"); printf (" -l, --long Dump record contents too\n");
printf (" -p, --positions Dump record positions\n");
} }
static void static void
...@@ -124,13 +130,17 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ...@@ -124,13 +130,17 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
} }
static void static void
print_prefix (filename, depth) print_prefix (filename, depth, position)
const char *filename; const char *filename;
unsigned depth; unsigned depth;
gcov_position_t position;
{ {
static const char prefix[] = " "; static const char prefix[] = " ";
printf ("%s:%.*s", filename, (int) depth, prefix); printf ("%s:", filename);
if (flag_dump_positions)
printf ("%lu:", (unsigned long) position);
printf ("%.*s", (int) depth, prefix);
} }
static void static void
...@@ -178,30 +188,29 @@ dump_file (filename) ...@@ -178,30 +188,29 @@ dump_file (filename)
printf ("%s:warning:current version is `%.4s'\n", filename, e); printf ("%s:warning:current version is `%.4s'\n", filename, e);
} }
while (!gcov_is_eof ()) while (1)
{ {
unsigned tag = gcov_read_unsigned (); gcov_position_t base, position = gcov_position ();
unsigned length = gcov_read_unsigned (); unsigned tag, length;
unsigned long base = gcov_position ();
tag_format_t const *format; tag_format_t const *format;
unsigned tag_depth; unsigned tag_depth;
int error; int error;
unsigned mask;
tag = gcov_read_unsigned ();
if (!tag) if (!tag)
tag_depth = depth; break;
else length = gcov_read_unsigned ();
base = gcov_position ();
mask = GCOV_TAG_MASK (tag) >> 1;
for (tag_depth = 4; mask; mask >>= 8)
{ {
unsigned mask = GCOV_TAG_MASK (tag) >> 1; if ((mask & 0xff) != 0xff)
for (tag_depth = 4; mask; mask >>= 8)
{ {
if ((mask & 0xff) != 0xff) printf ("%s:tag `%08x' is invalid\n", filename, tag);
{ break;
printf ("%s:tag `%08x' is invalid\n", filename, tag);
break;
}
tag_depth--;
} }
tag_depth--;
} }
for (format = tag_table; format->name; format++) for (format = tag_table; format->name; format++)
if (format->tag == tag) if (format->tag == tag)
...@@ -220,7 +229,7 @@ dump_file (filename) ...@@ -220,7 +229,7 @@ dump_file (filename)
tags[depth - 1] = tag; tags[depth - 1] = tag;
} }
print_prefix (filename, tag_depth); print_prefix (filename, tag_depth, position);
printf ("%08x:%4u:%s", tag, length, format->name); printf ("%08x:%4u:%s", tag, length, format->name);
if (format->proc) if (format->proc)
(*format->proc) (filename, tag, length); (*format->proc) (filename, tag, length);
...@@ -246,6 +255,8 @@ dump_file (filename) ...@@ -246,6 +255,8 @@ dump_file (filename)
break; break;
} }
} }
if (!gcov_is_eof ())
printf ("%s:early end of file\n", filename);
gcov_close (); gcov_close ();
} }
...@@ -289,7 +300,11 @@ tag_blocks (filename, tag, length) ...@@ -289,7 +300,11 @@ tag_blocks (filename, tag, length)
for (ix = 0; ix != n_blocks; ix++) for (ix = 0; ix != n_blocks; ix++)
{ {
if (!(ix & 7)) if (!(ix & 7))
printf ("\n%s:\t\t%u", filename, ix); {
printf ("\n");
print_prefix (filename, 0, gcov_position ());
printf ("\t\t%u", ix);
}
printf (" %04x", gcov_read_unsigned ()); printf (" %04x", gcov_read_unsigned ());
} }
} }
...@@ -311,11 +326,16 @@ tag_arcs (filename, tag, length) ...@@ -311,11 +326,16 @@ tag_arcs (filename, tag, length)
for (ix = 0; ix != n_arcs; ix++) for (ix = 0; ix != n_arcs; ix++)
{ {
unsigned dst = gcov_read_unsigned (); unsigned dst, flags;
unsigned flags = gcov_read_unsigned ();
if (!(ix & 3)) if (!(ix & 3))
printf ("\n%s:\tblock %u:", filename, blockno); {
printf ("\n");
print_prefix (filename, 0, gcov_position ());
printf ("\tblock %u:", blockno);
}
dst = gcov_read_unsigned ();
flags = gcov_read_unsigned ();
printf (" %u:%04x", dst, flags); printf (" %u:%04x", dst, flags);
} }
} }
...@@ -334,6 +354,7 @@ tag_lines (filename, tag, length) ...@@ -334,6 +354,7 @@ tag_lines (filename, tag, length)
while (1) while (1)
{ {
gcov_position_t position = gcov_position ();
const char *source = NULL; const char *source = NULL;
unsigned lineno = gcov_read_unsigned (); unsigned lineno = gcov_read_unsigned ();
...@@ -347,7 +368,9 @@ tag_lines (filename, tag, length) ...@@ -347,7 +368,9 @@ tag_lines (filename, tag, length)
if (!sep) if (!sep)
{ {
printf ("\n%s:\tblock %u:", filename, blockno); printf ("\n");
print_prefix (filename, 0, position);
printf ("\tblock %u:", blockno);
sep = ""; sep = "";
} }
if (lineno) if (lineno)
...@@ -381,10 +404,16 @@ tag_counters (filename, tag, length) ...@@ -381,10 +404,16 @@ tag_counters (filename, tag, length)
for (ix = 0; ix != n_counts; ix++) for (ix = 0; ix != n_counts; ix++)
{ {
gcov_type count = gcov_read_counter (); gcov_type count;
if (!(ix & 7)) if (!(ix & 7))
printf ("\n%s:\t\t%u", filename, ix); {
printf ("\n");
print_prefix (filename, 0, gcov_position ());
printf ("\t\t%u", ix);
}
count = gcov_read_counter ();
printf (" "); printf (" ");
printf (HOST_WIDEST_INT_PRINT_DEC, count); printf (HOST_WIDEST_INT_PRINT_DEC, count);
} }
...@@ -405,7 +434,9 @@ tag_summary (filename, tag, length) ...@@ -405,7 +434,9 @@ tag_summary (filename, tag, length)
for (ix = 0; ix != GCOV_COUNTERS; ix++) for (ix = 0; ix != GCOV_COUNTERS; ix++)
{ {
printf ("\n%sL\t\tcounts=%u, runs=%u", filename, printf ("\n");
print_prefix (filename, 0, 0);
printf ("\t\tcounts=%u, runs=%u",
summary.ctrs[ix].num, summary.ctrs[ix].runs); summary.ctrs[ix].num, summary.ctrs[ix].runs);
printf (", sum_all=" HOST_WIDEST_INT_PRINT_DEC, printf (", sum_all=" HOST_WIDEST_INT_PRINT_DEC,
......
...@@ -24,6 +24,15 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -24,6 +24,15 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Routines declared in gcov-io.h. This file should be #included by /* Routines declared in gcov-io.h. This file should be #included by
another source file, after having #included gcov-io.h. */ another source file, after having #included gcov-io.h. */
#if !IN_GCOV
static void gcov_write_block (unsigned);
static unsigned char *gcov_write_bytes (unsigned);
#endif
static const unsigned char *gcov_read_bytes (unsigned);
#if !IN_LIBGCOV
static void gcov_allocate (unsigned);
#endif
/* Open a gcov file. NAME is the name of the file to open and MODE /* Open a gcov file. NAME is the name of the file to open and MODE
indicates whether a new file should be created, or an existing file indicates whether a new file should be created, or an existing file
opened for modification. If MODE is >= 0 an existing file will be opened for modification. If MODE is >= 0 an existing file will be
...@@ -36,7 +45,6 @@ GCOV_LINKAGE int ...@@ -36,7 +45,6 @@ GCOV_LINKAGE int
gcov_open (const char *name, int mode) gcov_open (const char *name, int mode)
{ {
int result = 1; int result = 1;
size_t alloc = 1024;
#if GCOV_LOCKED #if GCOV_LOCKED
struct flock s_flock; struct flock s_flock;
...@@ -49,63 +57,32 @@ gcov_open (const char *name, int mode) ...@@ -49,63 +57,32 @@ gcov_open (const char *name, int mode)
if (gcov_var.file) if (gcov_var.file)
abort (); abort ();
gcov_var.position = gcov_var.length = 0; gcov_var.start = 0;
gcov_var.error = gcov_var.modified = 0; gcov_var.offset = gcov_var.length = 0;
gcov_var.overread = -4u;
gcov_var.error = 0;
if (mode >= 0) if (mode >= 0)
gcov_var.file = fopen (name, "r+b"); gcov_var.file = fopen (name, "r+b");
if (!gcov_var.file && mode <= 0) if (gcov_var.file)
gcov_var.mode = 1;
else if (mode <= 0)
{ {
result = -1; result = -1;
gcov_var.file = fopen (name, "w+b"); gcov_var.file = fopen (name, "w+b");
if (gcov_var.file)
gcov_var.mode = -1;
} }
if (!gcov_var.file) if (!gcov_var.file)
return 0; return 0;
setbuf (gcov_var.file, (char *)0);
#if GCOV_LOCKED #if GCOV_LOCKED
while (fcntl (fileno (gcov_var.file), F_SETLKW, &s_flock) while (fcntl (fileno (gcov_var.file), F_SETLKW, &s_flock)
&& errno == EINTR) && errno == EINTR)
continue; continue;
#endif #endif
if (result >= 0)
{
if (fseek (gcov_var.file, 0, SEEK_END))
{
fclose (gcov_var.file);
gcov_var.file = 0;
return 0;
}
gcov_var.length = ftell (gcov_var.file);
fseek (gcov_var.file, 0, SEEK_SET);
alloc += gcov_var.length;
}
if (alloc > gcov_var.alloc)
{
if (gcov_var.buffer)
free (gcov_var.buffer);
gcov_var.alloc = alloc;
#if IN_LIBGCOV
gcov_var.buffer = malloc (gcov_var.alloc);
if (!gcov_var.buffer)
{
fclose (gcov_var.file);
gcov_var.file = 0;
gcov_var.length = 0;
gcov_var.alloc = 0;
return 0;
}
#else
gcov_var.buffer = xmalloc (gcov_var.alloc);
#endif
}
if (result >= 0
&& fread (gcov_var.buffer, gcov_var.length, 1, gcov_var.file) != 1)
{
fclose (gcov_var.file);
gcov_var.file = 0;
gcov_var.length = 0;
return 0;
}
return result; return result;
} }
...@@ -115,15 +92,12 @@ gcov_open (const char *name, int mode) ...@@ -115,15 +92,12 @@ gcov_open (const char *name, int mode)
GCOV_LINKAGE int GCOV_LINKAGE int
gcov_close () gcov_close ()
{ {
int result = 0;
if (gcov_var.file) if (gcov_var.file)
{ {
if (gcov_var.modified #if !IN_GCOV
&& (fseek (gcov_var.file, 0, SEEK_SET) if (gcov_var.offset && gcov_var.mode < 0)
|| fwrite (gcov_var.buffer, gcov_var.length, gcov_write_block (gcov_var.offset);
1, gcov_var.file) != 1)) #endif
result = 1;
fclose (gcov_var.file); fclose (gcov_var.file);
gcov_var.file = 0; gcov_var.file = 0;
gcov_var.length = 0; gcov_var.length = 0;
...@@ -133,47 +107,64 @@ gcov_close () ...@@ -133,47 +107,64 @@ gcov_close ()
gcov_var.alloc = 0; gcov_var.alloc = 0;
gcov_var.buffer = 0; gcov_var.buffer = 0;
#endif #endif
return result ? 1 : gcov_var.error; gcov_var.mode = 0;
return gcov_var.error;
}
#if !IN_LIBGCOV
static void
gcov_allocate (unsigned length)
{
size_t new_size = gcov_var.alloc;
if (!new_size)
new_size = GCOV_BLOCK_SIZE;
new_size += length;
new_size *= 2;
gcov_var.alloc = new_size;
gcov_var.buffer = xrealloc (gcov_var.buffer, new_size);
} }
#endif
#if !IN_GCOV #if !IN_GCOV
/* Write out the current block, if needs be. */
static void
gcov_write_block (unsigned size)
{
if (fwrite (gcov_var.buffer, size, 1, gcov_var.file) != 1)
gcov_var.error = 1;
gcov_var.start += size;
gcov_var.offset -= size;
}
/* Allocate space to write BYTES bytes to the gcov file. Return a /* Allocate space to write BYTES bytes to the gcov file. Return a
pointer to those bytes, or NULL on failure. */ pointer to those bytes, or NULL on failure. */
GCOV_LINKAGE unsigned char * static unsigned char *
gcov_write_bytes (unsigned bytes) gcov_write_bytes (unsigned bytes)
{ {
char unsigned *result; char unsigned *result;
if (gcov_var.position + bytes > gcov_var.alloc) GCOV_CHECK_WRITING ();
{
size_t new_size = (gcov_var.alloc + bytes) * 3 / 2;
if (!gcov_var.buffer)
return 0;
#if IN_LIBGCOV #if IN_LIBGCOV
result = realloc (gcov_var.buffer, new_size); if (gcov_var.offset >= GCOV_BLOCK_SIZE)
if (!result) {
gcov_write_block (GCOV_BLOCK_SIZE);
if (gcov_var.offset)
{ {
free (gcov_var.buffer); GCOV_CHECK (gcov_var.offset == 4);
gcov_var.buffer = 0; memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4);
gcov_var.alloc = 0;
gcov_var.position = gcov_var.length = 0;
gcov_var.error = 1;
return 0;
} }
}
#else #else
result = xrealloc (gcov_var.buffer, new_size); if (gcov_var.offset + bytes > gcov_var.alloc)
gcov_allocate (gcov_var.offset + bytes);
#endif #endif
gcov_var.alloc = new_size; result = &gcov_var.buffer[gcov_var.offset];
gcov_var.buffer = result; gcov_var.offset += bytes;
}
result = &gcov_var.buffer[gcov_var.position];
gcov_var.position += bytes;
gcov_var.modified = 1;
if (gcov_var.position > gcov_var.length)
gcov_var.length = gcov_var.position;
return result; return result;
} }
...@@ -186,8 +177,6 @@ gcov_write_unsigned (gcov_unsigned_t value) ...@@ -186,8 +177,6 @@ gcov_write_unsigned (gcov_unsigned_t value)
unsigned char *buffer = gcov_write_bytes (4); unsigned char *buffer = gcov_write_bytes (4);
unsigned ix; unsigned ix;
if (!buffer)
return;
for (ix = 4; ix--; ) for (ix = 4; ix--; )
{ {
buffer[ix] = value; buffer[ix] = value;
...@@ -209,8 +198,6 @@ gcov_write_counter (gcov_type value) ...@@ -209,8 +198,6 @@ gcov_write_counter (gcov_type value)
unsigned char *buffer = gcov_write_bytes (8); unsigned char *buffer = gcov_write_bytes (8);
unsigned ix; unsigned ix;
if (!buffer)
return;
for (ix = 8; ix--; ) for (ix = 8; ix--; )
{ {
buffer[ix] = value; buffer[ix] = value;
...@@ -233,6 +220,8 @@ gcov_write_string (const char *string) ...@@ -233,6 +220,8 @@ gcov_write_string (const char *string)
unsigned pad = 0; unsigned pad = 0;
unsigned rem = 0; unsigned rem = 0;
unsigned char *buffer; unsigned char *buffer;
unsigned ix;
unsigned value;
if (string) if (string)
{ {
...@@ -241,19 +230,15 @@ gcov_write_string (const char *string) ...@@ -241,19 +230,15 @@ gcov_write_string (const char *string)
} }
buffer = gcov_write_bytes (4 + length + rem); buffer = gcov_write_bytes (4 + length + rem);
if (buffer)
value = length;
for (ix = 4; ix--; )
{ {
unsigned ix; buffer[ix] = value;
unsigned value = length; value >>= 8;
for (ix = 4; ix--; )
{
buffer[ix] = value;
value >>= 8;
}
memcpy (buffer + 4, string, length);
memcpy (buffer + 4 + length, &pad, rem);
} }
memcpy (buffer + 4, string, length);
memcpy (buffer + 4 + length, &pad, rem);
} }
#endif #endif
...@@ -264,12 +249,10 @@ gcov_write_string (const char *string) ...@@ -264,12 +249,10 @@ gcov_write_string (const char *string)
GCOV_LINKAGE gcov_position_t GCOV_LINKAGE gcov_position_t
gcov_write_tag (gcov_unsigned_t tag) gcov_write_tag (gcov_unsigned_t tag)
{ {
gcov_position_t result = gcov_var.position; gcov_position_t result = gcov_var.start + gcov_var.offset;
unsigned char *buffer = gcov_write_bytes (8); unsigned char *buffer = gcov_write_bytes (8);
unsigned ix; unsigned ix;
if (!buffer)
return 0;
for (ix = 4; ix--; ) for (ix = 4; ix--; )
{ {
buffer[ix] = tag; buffer[ix] = tag;
...@@ -287,18 +270,24 @@ gcov_write_tag (gcov_unsigned_t tag) ...@@ -287,18 +270,24 @@ gcov_write_tag (gcov_unsigned_t tag)
GCOV_LINKAGE void GCOV_LINKAGE void
gcov_write_length (gcov_position_t position) gcov_write_length (gcov_position_t position)
{ {
if (position) unsigned offset;
gcov_unsigned_t length;
unsigned char *buffer;
unsigned ix;
GCOV_CHECK_WRITING ();
GCOV_CHECK (position + 8 <= gcov_var.start + gcov_var.offset);
GCOV_CHECK (position >= gcov_var.start);
offset = position - gcov_var.start;
length = gcov_var.offset - offset - 8;
buffer = &gcov_var.buffer[offset + 4];
for (ix = 4; ix--; )
{ {
gcov_unsigned_t length = gcov_var.position - position - 8; buffer[ix] = length;
unsigned char *buffer = &gcov_var.buffer[position + 4]; length >>= 8;
unsigned ix;
for (ix = 4; ix--; )
{
buffer[ix] = length;
length >>= 8;
}
} }
if (gcov_var.offset >= GCOV_BLOCK_SIZE)
gcov_write_block (gcov_var.offset);
} }
#else /* IN_LIBGCOV */ #else /* IN_LIBGCOV */
...@@ -311,8 +300,6 @@ gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length) ...@@ -311,8 +300,6 @@ gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length)
unsigned char *buffer = gcov_write_bytes (8); unsigned char *buffer = gcov_write_bytes (8);
unsigned ix; unsigned ix;
if (!buffer)
return;
for (ix = 4; ix--; ) for (ix = 4; ix--; )
{ {
buffer[ix] = tag; buffer[ix] = tag;
...@@ -353,19 +340,47 @@ gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary) ...@@ -353,19 +340,47 @@ gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary)
/* Return a pointer to read BYTES bytes from the gcov file. Returns /* Return a pointer to read BYTES bytes from the gcov file. Returns
NULL on failure (read past EOF). */ NULL on failure (read past EOF). */
GCOV_LINKAGE const unsigned char * static const unsigned char *
gcov_read_bytes (unsigned bytes) gcov_read_bytes (unsigned bytes)
{ {
const unsigned char *result; const unsigned char *result;
unsigned excess = gcov_var.length - gcov_var.offset;
if (gcov_var.position + bytes > gcov_var.length) GCOV_CHECK_READING ();
if (excess < bytes)
{ {
gcov_var.error = 1; gcov_var.start += gcov_var.offset;
return 0; #if IN_LIBGCOV
if (excess)
{
GCOV_CHECK (excess == 4);
memcpy (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, 4);
}
#else
memmove (gcov_var.buffer, gcov_var.buffer + gcov_var.offset, excess);
#endif
gcov_var.offset = 0;
gcov_var.length = excess;
#if IN_LIBGCOV
GCOV_CHECK (!gcov_var.length || gcov_var.length == 4);
excess = GCOV_BLOCK_SIZE;
#else
if (gcov_var.length + bytes > gcov_var.alloc)
gcov_allocate (gcov_var.length + bytes);
excess = gcov_var.alloc - gcov_var.length;
#endif
excess = fread (gcov_var.buffer + gcov_var.offset,
1, excess, gcov_var.file);
gcov_var.length += excess;
if (gcov_var.length < bytes)
{
gcov_var.overread += bytes - gcov_var.length;
gcov_var.length = 0;
return 0;
}
} }
result = &gcov_var.buffer[gcov_var.offset];
result = &gcov_var.buffer[gcov_var.position]; gcov_var.offset += bytes;
gcov_var.position += bytes;
return result; return result;
} }
...@@ -452,6 +467,41 @@ gcov_read_summary (struct gcov_summary *summary) ...@@ -452,6 +467,41 @@ gcov_read_summary (struct gcov_summary *summary)
} }
} }
#if !IN_LIBGCOV
/* Reset to a known position. BASE should have been obtained from
gcov_position, LENGTH should be a record length. */
GCOV_LINKAGE void
gcov_sync (gcov_position_t base, gcov_unsigned_t length)
{
GCOV_CHECK_READING ();
base += length;
if (base - gcov_var.start <= gcov_var.length)
gcov_var.offset = base - gcov_var.start;
else
{
gcov_var.offset = gcov_var.length = 0;
fseek (gcov_var.file, base, SEEK_SET);
gcov_var.start = ftell (gcov_var.file);
}
}
#endif
#if IN_LIBGCOV
/* Move to the a set position in a gcov file. BASE is zero to move to
the end, and non-zero to move to that position. */
GCOV_LINKAGE void
gcov_seek (gcov_position_t base)
{
GCOV_CHECK_WRITING ();
if (gcov_var.offset)
gcov_write_block (gcov_var.offset);
fseek (gcov_var.file, base, base ? SEEK_SET : SEEK_END);
gcov_var.start = ftell (gcov_var.file);
}
#endif
#if IN_GCOV > 0 #if IN_GCOV > 0
/* Return the modification time of the current gcov file. */ /* Return the modification time of the current gcov file. */
......
...@@ -202,35 +202,31 @@ typedef HOST_WIDEST_INT gcov_type; ...@@ -202,35 +202,31 @@ typedef HOST_WIDEST_INT gcov_type;
#endif /* !IN_LIBGCOV */ #endif /* !IN_LIBGCOV */
/* In gcov we want function linkage to be static, so we do not /* In gcov we want function linkage to be static. In libgcov we need
polute the global namespace. In libgcov we need these functions these functions to be extern, so prefix them with __gcov. In the
to be extern, so prefix them with __gcov so that we do not conflict. compiler we want it extern, so that they can be accessed from
In the compiler we want it extern, so that they can be accessed from
elsewhere. */ elsewhere. */
#if IN_LIBGCOV #if IN_LIBGCOV
#define gcov_var __gcov_var #define gcov_var __gcov_var
#define gcov_open __gcov_open #define gcov_open __gcov_open
#define gcov_close __gcov_close #define gcov_close __gcov_close
#define gcov_write_bytes __gcov_write_bytes #define gcov_write_tag_length __gcov_write_tag_length
#define gcov_position __gcov_position
#define gcov_seek __gcov_seek
#define gcov_rewrite __gcov_rewrite
#define gcov_is_error __gcov_is_error
#define gcov_is_eof __gcov_is_eof
#define gcov_write_unsigned __gcov_write_unsigned #define gcov_write_unsigned __gcov_write_unsigned
#define gcov_write_counter __gcov_write_counter #define gcov_write_counter __gcov_write_counter
#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_write_summary __gcov_write_summary
#define gcov_read_bytes __gcov_read_bytes
#define gcov_read_unsigned __gcov_read_unsigned #define gcov_read_unsigned __gcov_read_unsigned
#define gcov_read_counter __gcov_read_counter #define gcov_read_counter __gcov_read_counter
#pragma GCC poison gcov_read_string
#define gcov_read_summary __gcov_read_summary #define gcov_read_summary __gcov_read_summary
#define gcov_position __gcov_position
#define gcov_sync __gcov_sync /* Poison these, so they don't accidentally slip in. */
#define gcov_seek __gcov_seek #pragma GCC poison gcov_write_string gcov_write_tag gcov_write_length
#define gcov_rewrite __gcov_rewrite #pragma GCC poison gcov_read_string gcov_sync gcov_time
#define gcov_is_eof __gcov_is_eof
#define gcov_is_error __gcov_is_error
#pragma GCC poison gcov_time
#endif #endif
#ifndef GCOV_LINKAGE #ifndef GCOV_LINKAGE
...@@ -255,18 +251,19 @@ typedef HOST_WIDEST_INT gcov_type; ...@@ -255,18 +251,19 @@ typedef HOST_WIDEST_INT gcov_type;
file. Values [41..9f] for those in the bbg file and [a1..ff] for file. Values [41..9f] for those in the bbg file and [a1..ff] for
the data file. */ the data file. */
#define GCOV_TAG_FUNCTION ((unsigned)0x01000000) #define GCOV_TAG_FUNCTION ((gcov_unsigned_t)0x01000000)
#define GCOV_TAG_FUNCTION_LENGTH (2 * 4) #define GCOV_TAG_FUNCTION_LENGTH (2 * 4)
#define GCOV_TAG_BLOCKS ((unsigned)0x01410000) #define GCOV_TAG_BLOCKS ((gcov_unsigned_t)0x01410000)
#define GCOV_TAG_BLOCKS_LENGTH(NUM) ((NUM) * 4) #define GCOV_TAG_BLOCKS_LENGTH(NUM) ((NUM) * 4)
#define GCOV_TAG_ARCS ((unsigned)0x01430000) #define GCOV_TAG_ARCS ((gcov_unsigned_t)0x01430000)
#define GCOV_TAG_ARCS_LENGTH(NUM) (1 * 4 + (NUM) * (2 * 4)) #define GCOV_TAG_ARCS_LENGTH(NUM) (1 * 4 + (NUM) * (2 * 4))
#define GCOV_TAG_LINES ((unsigned)0x01450000) #define GCOV_TAG_LINES ((gcov_unsigned_t)0x01450000)
#define GCOV_TAG_COUNTER_BASE ((unsigned)0x01a10000) /* First counter */ #define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000)
#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 8) #define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 8)
#define GCOV_TAG_OBJECT_SUMMARY ((unsigned)0xa1000000) #define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000)
#define GCOV_TAG_PROGRAM_SUMMARY ((unsigned)0xa3000000) #define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000)
#define GCOV_TAG_SUMMARY_LENGTH (1 * 4 + GCOV_COUNTERS_SUMMABLE * (2 * 4 + 3 * 8)) #define GCOV_TAG_SUMMARY_LENGTH \
(1 * 4 + GCOV_COUNTERS_SUMMABLE * (2 * 4 + 3 * 8))
/* Counters that are collected. */ /* Counters that are collected. */
#define GCOV_COUNTER_ARCS 0 /* Arc transitions. */ #define GCOV_COUNTER_ARCS 0 /* Arc transitions. */
...@@ -282,10 +279,10 @@ typedef HOST_WIDEST_INT gcov_type; ...@@ -282,10 +279,10 @@ typedef HOST_WIDEST_INT gcov_type;
/* Convert a counter index to a tag. */ /* Convert a counter index to a tag. */
#define GCOV_TAG_FOR_COUNTER(COUNT) \ #define GCOV_TAG_FOR_COUNTER(COUNT) \
(GCOV_TAG_COUNTER_BASE + ((COUNT) << 17)) (GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17))
/* Convert a tag to a counter. */ /* Convert a tag to a counter. */
#define GCOV_COUNTER_FOR_TAG(TAG) \ #define GCOV_COUNTER_FOR_TAG(TAG) \
(((TAG) - GCOV_TAG_COUNTER_BASE) >> 17) ((unsigned)(((TAG) - GCOV_TAG_COUNTER_BASE) >> 17))
/* Check whether a tag is a counter tag. */ /* Check whether a tag is a counter tag. */
#define GCOV_TAG_IS_COUNTER(TAG) \ #define GCOV_TAG_IS_COUNTER(TAG) \
(!((TAG) & 0xFFFF) && GCOV_COUNTER_FOR_TAG (TAG) < GCOV_COUNTERS) (!((TAG) & 0xFFFF) && GCOV_COUNTER_FOR_TAG (TAG) < GCOV_COUNTERS)
...@@ -387,114 +384,131 @@ extern void __gcov_merge_add (gcov_type *, unsigned); ...@@ -387,114 +384,131 @@ extern void __gcov_merge_add (gcov_type *, unsigned);
#if IN_LIBGCOV >= 0 #if IN_LIBGCOV >= 0
/* Because small reads and writes, interspersed with seeks cause lots /* Optimum size read from or written to disk. */
of disk activity, we buffer the entire count files. */ #define GCOV_BLOCK_SIZE (1 << 12)
GCOV_LINKAGE struct gcov_var GCOV_LINKAGE struct gcov_var
{ {
FILE *file; FILE *file;
gcov_position_t position; gcov_position_t start; /* Position of first byte of block */
gcov_position_t length; unsigned offset; /* Read/write position within the block. */
unsigned length; /* Read limit in the block. */
unsigned overread; /* Number of bytes overread. */
int error; /* < 0 overflow, > 0 disk error. */
int mode; /* < 0 writing, > 0 reading */
#if IN_LIBGCOV
/* Holds one block plus 4 bytes, thus all coverage reads & writes
fit within this buffer and we always can transfer GCOV_BLOCK_SIZE
to and from the disk. libgcov never backtracks and only writes 4
or 8 byte objects. */
unsigned char buffer[GCOV_BLOCK_SIZE + 4];
#else
/* Holds a variable length block, as the compiler can write
strings and needs to backtrack. */
size_t alloc; size_t alloc;
unsigned modified;
int error;
unsigned char *buffer; unsigned char *buffer;
#endif
} gcov_var; } gcov_var;
/* Functions for reading and writing gcov files. */ /* Functions for reading and writing gcov files. You can open a file
for (1) reading or (2) writing or (3) reading then rewriting. When
reading a file you may use the gcov_read_* functions, gcov_sync,
gcov_position, & gcov_error. When writing a file you
may use the gcov_write functions, gcov_seek & gcov_error. When a
file is to be rewritten you use the functions for reading, then
gcov_rewrite then the functions for writing. Your file may become
corrupted if you break these invariants. */
GCOV_LINKAGE int gcov_open (const char */*name*/, int /*truncate*/); GCOV_LINKAGE int gcov_open (const char */*name*/, int /*truncate*/);
GCOV_LINKAGE int gcov_close (void); GCOV_LINKAGE int gcov_close (void);
#if !IN_GCOV
GCOV_LINKAGE unsigned char *gcov_write_bytes (unsigned); /* Available everywhere. */
GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t); static gcov_position_t gcov_position (void);
static int gcov_is_error (void);
static int gcov_is_eof (void);
GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void);
GCOV_LINKAGE gcov_type gcov_read_counter (void);
GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *);
#if IN_LIBGCOV #if IN_LIBGCOV
/* Available only in libgcov */
GCOV_LINKAGE void gcov_write_counter (gcov_type); GCOV_LINKAGE void gcov_write_counter (gcov_type);
#else
GCOV_LINKAGE void gcov_write_string (const char *);
#endif
#if !IN_LIBGCOV
GCOV_LINKAGE gcov_position_t gcov_write_tag (gcov_unsigned_t);
GCOV_LINKAGE void gcov_write_length (gcov_position_t /*position*/);
#else
GCOV_LINKAGE void gcov_write_tag_length (gcov_unsigned_t, gcov_unsigned_t); GCOV_LINKAGE void gcov_write_tag_length (gcov_unsigned_t, gcov_unsigned_t);
GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t /*tag*/, GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t /*tag*/,
const struct gcov_summary *); const struct gcov_summary *);
#endif static void gcov_rewrite (void);
#endif /* !IN_GCOV */ GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/);
GCOV_LINKAGE const unsigned char *gcov_read_bytes (unsigned); #else
GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void); /* Available outside libgcov */
GCOV_LINKAGE gcov_type gcov_read_counter (void);
#if !IN_LIBGCOV
GCOV_LINKAGE const char *gcov_read_string (void); GCOV_LINKAGE const char *gcov_read_string (void);
GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/,
gcov_unsigned_t /*length */);
#endif #endif
GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *);
static gcov_position_t gcov_position (void); #if !IN_GCOV
static void gcov_sync (gcov_position_t /*base*/, gcov_unsigned_t /*length */); /* Available outside gcov */
static void gcov_seek (gcov_position_t /*position*/); GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t);
static void gcov_rewrite (void); #endif
static int gcov_is_eof (void);
static int gcov_is_error (void); #if !IN_GCOV && !IN_LIBGCOV
/* Available only in compiler */
GCOV_LINKAGE void gcov_write_string (const char *);
GCOV_LINKAGE gcov_position_t gcov_write_tag (gcov_unsigned_t);
GCOV_LINKAGE void gcov_write_length (gcov_position_t /*position*/);
#endif
#if IN_GCOV > 0 #if IN_GCOV > 0
/* Available in gcov */
GCOV_LINKAGE time_t gcov_time (void); GCOV_LINKAGE time_t gcov_time (void);
#endif #endif
/* Make sure the library is used correctly. */
#if ENABLE_CHECKING
#define GCOV_CHECK(expr) ((expr) ? (void)0 : (void)abort ())
#else
#define GCOV_CHECK(expr)
#endif
#define GCOV_CHECK_READING() GCOV_CHECK(gcov_var.mode > 0)
#define GCOV_CHECK_WRITING() GCOV_CHECK(gcov_var.mode < 0)
/* Save the current position in the gcov file. */ /* Save the current position in the gcov file. */
static inline gcov_position_t static inline gcov_position_t
gcov_position (void) gcov_position (void)
{ {
return gcov_var.position; GCOV_CHECK_READING ();
return gcov_var.start + gcov_var.offset;
} }
/* Reset to a known position. BASE should have been obtained from /* Return non-zero if we read to end of file. */
gcov_save_position, LENGTH should be a record length, or zero. */
static inline void static inline int
gcov_sync (gcov_position_t base, gcov_unsigned_t length) gcov_is_eof ()
{ {
if (gcov_var.buffer) return !gcov_var.overread;
{
base += length;
if (gcov_var.length < base)
{
gcov_var.error = 1;
base = gcov_var.length;
}
gcov_var.position = base;
}
} }
/* Move to the end of the gcov file. */ /* Return non-zero if the error flag is set. */
static inline void static inline int
gcov_seek (gcov_position_t base) gcov_is_error ()
{ {
gcov_var.position = base < gcov_var.length ? base : gcov_var.length; return gcov_var.file ? gcov_var.error : 1;
} }
#if IN_LIBGCOV
/* Move to beginning of file and intialize for writing. */ /* Move to beginning of file and intialize for writing. */
static inline void static inline void
gcov_rewrite (void) gcov_rewrite (void)
{ {
gcov_var.position = 0; GCOV_CHECK_READING ();
} gcov_var.mode = -1;
gcov_var.start = 0;
/* Tests whether we have reached end of .da file. */ gcov_var.offset = 0;
fseek (gcov_var.file, 0L, SEEK_SET);
static inline int
gcov_is_eof ()
{
return gcov_var.position == gcov_var.length;
}
/* Return non-zero if the error flag is set. */
static inline int
gcov_is_error ()
{
return gcov_var.file ? gcov_var.error : 1;
} }
#endif
#endif /* IN_LIBGCOV >= 0 */ #endif /* IN_LIBGCOV >= 0 */
......
...@@ -711,7 +711,8 @@ read_graph_file () ...@@ -711,7 +711,8 @@ read_graph_file ()
struct function_info *fn = NULL; struct function_info *fn = NULL;
source_t *src = NULL; source_t *src = NULL;
unsigned ix; unsigned ix;
unsigned tag;
if (!gcov_open (bbg_file_name, 1)) if (!gcov_open (bbg_file_name, 1))
{ {
fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name); fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
...@@ -740,11 +741,10 @@ read_graph_file () ...@@ -740,11 +741,10 @@ read_graph_file ()
bbg_file_name, v, e); bbg_file_name, v, e);
} }
while (!gcov_is_eof ()) while ((tag = gcov_read_unsigned ()))
{ {
unsigned tag = gcov_read_unsigned ();
unsigned length = gcov_read_unsigned (); unsigned length = gcov_read_unsigned ();
unsigned long base = gcov_position (); gcov_position_t base = gcov_position ();
if (tag == GCOV_TAG_FUNCTION) if (tag == GCOV_TAG_FUNCTION)
{ {
...@@ -906,12 +906,14 @@ read_graph_file () ...@@ -906,12 +906,14 @@ read_graph_file ()
} }
gcov_sync (base, length); gcov_sync (base, length);
if (gcov_is_error ()) if (gcov_is_error ())
{ break;
corrupt:; }
fnotice (stderr, "%s:corrupted\n", bbg_file_name); if (!gcov_is_eof ())
gcov_close (); {
return 1; corrupt:;
} fnotice (stderr, "%s:corrupted\n", bbg_file_name);
gcov_close ();
return 1;
} }
gcov_close (); gcov_close ();
...@@ -976,7 +978,9 @@ read_count_file () ...@@ -976,7 +978,9 @@ read_count_file ()
{ {
unsigned ix; unsigned ix;
unsigned version; unsigned version;
unsigned tag;
function_t *fn = NULL; function_t *fn = NULL;
int error = 0;
if (!gcov_open (da_file_name, 1)) if (!gcov_open (da_file_name, 1))
{ {
...@@ -1005,12 +1009,10 @@ read_count_file () ...@@ -1005,12 +1009,10 @@ read_count_file ()
da_file_name, v, e); da_file_name, v, e);
} }
while (!gcov_is_eof ()) while ((tag = gcov_read_unsigned ()))
{ {
unsigned tag = gcov_read_unsigned ();
unsigned length = gcov_read_unsigned (); unsigned length = gcov_read_unsigned ();
unsigned long base = gcov_position (); unsigned long base = gcov_position ();
int error;
if (tag == GCOV_TAG_OBJECT_SUMMARY) if (tag == GCOV_TAG_OBJECT_SUMMARY)
gcov_read_summary (&object_summary); gcov_read_summary (&object_summary);
...@@ -1061,13 +1063,16 @@ read_count_file () ...@@ -1061,13 +1063,16 @@ read_count_file ()
} }
gcov_sync (base, length); gcov_sync (base, length);
if ((error = gcov_is_error ())) if ((error = gcov_is_error ()))
{ break;
fnotice (stderr, error < 0
? "%s:overflowed\n" : "%s:corrupted\n", da_file_name);
goto cleanup;
}
} }
if (!gcov_is_eof ())
{
fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
da_file_name);
goto cleanup;
}
gcov_close (); gcov_close ();
return 0; return 0;
} }
......
...@@ -152,10 +152,10 @@ gcov_exit (void) ...@@ -152,10 +152,10 @@ gcov_exit (void)
const struct gcov_ctr_info *ci_ptr; const struct gcov_ctr_info *ci_ptr;
struct gcov_ctr_summary *cs_ptr; struct gcov_ctr_summary *cs_ptr;
struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all; struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
int error; int error = 0;
int merging; int merging;
gcov_unsigned_t tag, length; gcov_unsigned_t tag, length;
gcov_position_t summary_pos = ~(gcov_position_t)0; gcov_position_t summary_pos = 0;
/* Totals for this object file. */ /* Totals for this object file. */
memset (&this_object, 0, sizeof (this_object)); memset (&this_object, 0, sizeof (this_object));
...@@ -256,12 +256,14 @@ gcov_exit (void) ...@@ -256,12 +256,14 @@ gcov_exit (void)
} }
/* Check program & object summary */ /* Check program & object summary */
while (!gcov_is_eof ()) while (1)
{ {
gcov_position_t base = gcov_position (); gcov_position_t base = gcov_position ();
int is_program; int is_program;
tag = gcov_read_unsigned (); tag = gcov_read_unsigned ();
if (!tag)
break;
length = gcov_read_unsigned (); length = gcov_read_unsigned ();
is_program = tag == GCOV_TAG_PROGRAM_SUMMARY; is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
if (length != GCOV_TAG_SUMMARY_LENGTH if (length != GCOV_TAG_SUMMARY_LENGTH
...@@ -269,24 +271,26 @@ gcov_exit (void) ...@@ -269,24 +271,26 @@ gcov_exit (void)
goto read_mismatch; goto read_mismatch;
gcov_read_summary (is_program ? &program : &object); gcov_read_summary (is_program ? &program : &object);
if ((error = gcov_is_error ())) if ((error = gcov_is_error ()))
goto read_error;
if (is_program && program.checksum == gcov_crc32)
{ {
read_error:; summary_pos = base;
fprintf (stderr, error < 0 ? goto rewrite;
"profiling:%s:Overflow merging\n" :
"profiling:%s:Error merging\n", gi_ptr->filename);
goto read_fatal;
} }
if (!is_program || program.checksum != gcov_crc32)
continue;
summary_pos = base;
break;
} }
if (!gcov_is_eof ())
{
read_error:;
fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
: "profiling:%s:Error merging\n", gi_ptr->filename);
goto read_fatal;
}
rewrite:;
gcov_rewrite (); gcov_rewrite ();
} }
else else
memset (&object, 0, sizeof (object)); memset (&object, 0, sizeof (object));
if (!(summary_pos + 1)) if (!summary_pos)
memset (&program, 0, sizeof (program)); memset (&program, 0, sizeof (program));
/* Merge the summaries. */ /* Merge the summaries. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment