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
This commit is contained in:
Nathan Sidwell 2003-05-14 16:01:20 +00:00 committed by Nathan Sidwell
parent 990f4800f2
commit 7d63a2fae0
7 changed files with 417 additions and 282 deletions

View File

@ -1,5 +1,34 @@
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
(libgcov.a): Depend on libgcc.a.
(gcov.o, gcov-dump.o): Add gcov-io.c.

View File

@ -158,7 +158,9 @@ read_counts_file ()
unsigned ix;
counts_entry_t *summaried = NULL;
unsigned seen_summary = 0;
gcov_unsigned_t tag;
int error = 0;
if (!gcov_open (da_file_name, 1))
return;
@ -187,13 +189,11 @@ read_counts_file ()
counts_hash = htab_create (10,
htab_counts_entry_hash, htab_counts_entry_eq,
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;
int error;
tag = gcov_read_unsigned ();
length = gcov_read_unsigned ();
offset = gcov_position ();
if (tag == GCOV_TAG_FUNCTION)
@ -284,14 +284,16 @@ read_counts_file ()
}
gcov_sync (offset, length);
if ((error = gcov_is_error ()))
{
warning (error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
da_file_name);
htab_delete (counts_hash);
break;
}
break;
}
if (!gcov_is_eof ())
{
warning (error < 0 ? "`%s' has overflowed" : "`%s' is corrupted",
da_file_name);
htab_delete (counts_hash);
}
gcov_close ();
}

View File

@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA. */
#include "gcov-io.c"
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_version PARAMS ((void));
static void tag_function PARAMS ((const char *, unsigned, unsigned));
@ -47,12 +47,14 @@ typedef struct tag_format
} tag_format_t;
static int flag_dump_contents = 0;
static int flag_dump_positions = 0;
static const struct option options[] =
{
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
{ "long", no_argument, NULL, 'l' },
{ "positions", no_argument, NULL, 'o' },
};
static const tag_format_t tag_table[] =
@ -75,7 +77,7 @@ int main (argc, argv)
{
int opt;
while ((opt = getopt_long (argc, argv, "hlv", options, NULL)) != -1)
while ((opt = getopt_long (argc, argv, "hlpv", options, NULL)) != -1)
{
switch (opt)
{
@ -88,6 +90,9 @@ int main (argc, argv)
case 'l':
flag_dump_contents = 1;
break;
case 'p':
flag_dump_positions = 1;
break;
default:
fprintf (stderr, "unknown flag `%c'\n", opt);
}
@ -106,6 +111,7 @@ print_usage ()
printf (" -h, --help Print this help\n");
printf (" -v, --version Print version number\n");
printf (" -l, --long Dump record contents too\n");
printf (" -p, --positions Dump record positions\n");
}
static void
@ -124,13 +130,17 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
}
static void
print_prefix (filename, depth)
print_prefix (filename, depth, position)
const char *filename;
unsigned depth;
gcov_position_t position;
{
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
@ -178,30 +188,29 @@ dump_file (filename)
printf ("%s:warning:current version is `%.4s'\n", filename, e);
}
while (!gcov_is_eof ())
while (1)
{
unsigned tag = gcov_read_unsigned ();
unsigned length = gcov_read_unsigned ();
unsigned long base = gcov_position ();
gcov_position_t base, position = gcov_position ();
unsigned tag, length;
tag_format_t const *format;
unsigned tag_depth;
int error;
unsigned mask;
tag = gcov_read_unsigned ();
if (!tag)
tag_depth = depth;
else
break;
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;
for (tag_depth = 4; mask; mask >>= 8)
if ((mask & 0xff) != 0xff)
{
if ((mask & 0xff) != 0xff)
{
printf ("%s:tag `%08x' is invalid\n", filename, tag);
break;
}
tag_depth--;
printf ("%s:tag `%08x' is invalid\n", filename, tag);
break;
}
tag_depth--;
}
for (format = tag_table; format->name; format++)
if (format->tag == tag)
@ -220,7 +229,7 @@ dump_file (filename)
tags[depth - 1] = tag;
}
print_prefix (filename, tag_depth);
print_prefix (filename, tag_depth, position);
printf ("%08x:%4u:%s", tag, length, format->name);
if (format->proc)
(*format->proc) (filename, tag, length);
@ -246,6 +255,8 @@ dump_file (filename)
break;
}
}
if (!gcov_is_eof ())
printf ("%s:early end of file\n", filename);
gcov_close ();
}
@ -289,7 +300,11 @@ tag_blocks (filename, tag, length)
for (ix = 0; ix != n_blocks; ix++)
{
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 ());
}
}
@ -311,11 +326,16 @@ tag_arcs (filename, tag, length)
for (ix = 0; ix != n_arcs; ix++)
{
unsigned dst = gcov_read_unsigned ();
unsigned flags = gcov_read_unsigned ();
unsigned dst, flags;
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);
}
}
@ -334,6 +354,7 @@ tag_lines (filename, tag, length)
while (1)
{
gcov_position_t position = gcov_position ();
const char *source = NULL;
unsigned lineno = gcov_read_unsigned ();
@ -347,7 +368,9 @@ tag_lines (filename, tag, length)
if (!sep)
{
printf ("\n%s:\tblock %u:", filename, blockno);
printf ("\n");
print_prefix (filename, 0, position);
printf ("\tblock %u:", blockno);
sep = "";
}
if (lineno)
@ -381,10 +404,16 @@ tag_counters (filename, tag, length)
for (ix = 0; ix != n_counts; ix++)
{
gcov_type count = gcov_read_counter ();
gcov_type count;
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 (HOST_WIDEST_INT_PRINT_DEC, count);
}
@ -405,7 +434,9 @@ tag_summary (filename, tag, length)
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);
printf (", sum_all=" HOST_WIDEST_INT_PRINT_DEC,

View File

@ -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
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
indicates whether a new file should be created, or an existing file
opened for modification. If MODE is >= 0 an existing file will be
@ -36,7 +45,6 @@ GCOV_LINKAGE int
gcov_open (const char *name, int mode)
{
int result = 1;
size_t alloc = 1024;
#if GCOV_LOCKED
struct flock s_flock;
@ -49,63 +57,32 @@ gcov_open (const char *name, int mode)
if (gcov_var.file)
abort ();
gcov_var.position = gcov_var.length = 0;
gcov_var.error = gcov_var.modified = 0;
gcov_var.start = 0;
gcov_var.offset = gcov_var.length = 0;
gcov_var.overread = -4u;
gcov_var.error = 0;
if (mode >= 0)
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;
gcov_var.file = fopen (name, "w+b");
if (gcov_var.file)
gcov_var.mode = -1;
}
if (!gcov_var.file)
return 0;
setbuf (gcov_var.file, (char *)0);
#if GCOV_LOCKED
while (fcntl (fileno (gcov_var.file), F_SETLKW, &s_flock)
&& errno == EINTR)
continue;
#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;
}
@ -115,15 +92,12 @@ gcov_open (const char *name, int mode)
GCOV_LINKAGE int
gcov_close ()
{
int result = 0;
if (gcov_var.file)
{
if (gcov_var.modified
&& (fseek (gcov_var.file, 0, SEEK_SET)
|| fwrite (gcov_var.buffer, gcov_var.length,
1, gcov_var.file) != 1))
result = 1;
#if !IN_GCOV
if (gcov_var.offset && gcov_var.mode < 0)
gcov_write_block (gcov_var.offset);
#endif
fclose (gcov_var.file);
gcov_var.file = 0;
gcov_var.length = 0;
@ -133,47 +107,64 @@ gcov_close ()
gcov_var.alloc = 0;
gcov_var.buffer = 0;
#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
/* 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
pointer to those bytes, or NULL on failure. */
GCOV_LINKAGE unsigned char *
static unsigned char *
gcov_write_bytes (unsigned bytes)
{
char unsigned *result;
if (gcov_var.position + bytes > gcov_var.alloc)
{
size_t new_size = (gcov_var.alloc + bytes) * 3 / 2;
if (!gcov_var.buffer)
return 0;
GCOV_CHECK_WRITING ();
#if IN_LIBGCOV
result = realloc (gcov_var.buffer, new_size);
if (!result)
if (gcov_var.offset >= GCOV_BLOCK_SIZE)
{
gcov_write_block (GCOV_BLOCK_SIZE);
if (gcov_var.offset)
{
free (gcov_var.buffer);
gcov_var.buffer = 0;
gcov_var.alloc = 0;
gcov_var.position = gcov_var.length = 0;
gcov_var.error = 1;
return 0;
GCOV_CHECK (gcov_var.offset == 4);
memcpy (gcov_var.buffer, gcov_var.buffer + GCOV_BLOCK_SIZE, 4);
}
#else
result = xrealloc (gcov_var.buffer, new_size);
#endif
gcov_var.alloc = new_size;
gcov_var.buffer = result;
}
#else
if (gcov_var.offset + bytes > gcov_var.alloc)
gcov_allocate (gcov_var.offset + bytes);
#endif
result = &gcov_var.buffer[gcov_var.offset];
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;
}
@ -186,8 +177,6 @@ gcov_write_unsigned (gcov_unsigned_t value)
unsigned char *buffer = gcov_write_bytes (4);
unsigned ix;
if (!buffer)
return;
for (ix = 4; ix--; )
{
buffer[ix] = value;
@ -209,8 +198,6 @@ gcov_write_counter (gcov_type value)
unsigned char *buffer = gcov_write_bytes (8);
unsigned ix;
if (!buffer)
return;
for (ix = 8; ix--; )
{
buffer[ix] = value;
@ -233,6 +220,8 @@ gcov_write_string (const char *string)
unsigned pad = 0;
unsigned rem = 0;
unsigned char *buffer;
unsigned ix;
unsigned value;
if (string)
{
@ -241,19 +230,15 @@ gcov_write_string (const char *string)
}
buffer = gcov_write_bytes (4 + length + rem);
if (buffer)
value = length;
for (ix = 4; ix--; )
{
unsigned ix;
unsigned value = length;
for (ix = 4; ix--; )
{
buffer[ix] = value;
value >>= 8;
}
memcpy (buffer + 4, string, length);
memcpy (buffer + 4 + length, &pad, rem);
buffer[ix] = value;
value >>= 8;
}
memcpy (buffer + 4, string, length);
memcpy (buffer + 4 + length, &pad, rem);
}
#endif
@ -264,12 +249,10 @@ gcov_write_string (const char *string)
GCOV_LINKAGE gcov_position_t
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 ix;
if (!buffer)
return 0;
for (ix = 4; ix--; )
{
buffer[ix] = tag;
@ -287,18 +270,24 @@ gcov_write_tag (gcov_unsigned_t tag)
GCOV_LINKAGE void
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;
unsigned char *buffer = &gcov_var.buffer[position + 4];
unsigned ix;
for (ix = 4; ix--; )
{
buffer[ix] = length;
length >>= 8;
}
buffer[ix] = length;
length >>= 8;
}
if (gcov_var.offset >= GCOV_BLOCK_SIZE)
gcov_write_block (gcov_var.offset);
}
#else /* IN_LIBGCOV */
@ -311,8 +300,6 @@ gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length)
unsigned char *buffer = gcov_write_bytes (8);
unsigned ix;
if (!buffer)
return;
for (ix = 4; ix--; )
{
buffer[ix] = tag;
@ -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
NULL on failure (read past EOF). */
GCOV_LINKAGE const unsigned char *
static const unsigned char *
gcov_read_bytes (unsigned bytes)
{
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;
return 0;
gcov_var.start += gcov_var.offset;
#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.position];
gcov_var.position += bytes;
result = &gcov_var.buffer[gcov_var.offset];
gcov_var.offset += bytes;
return result;
}
@ -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
/* Return the modification time of the current gcov file. */

View File

@ -202,35 +202,31 @@ typedef HOST_WIDEST_INT gcov_type;
#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
to be extern, so prefix them with __gcov so that we do not conflict.
In the compiler we want it extern, so that they can be accessed from
/* In gcov we want function linkage to be static. In libgcov we need
these functions to be extern, so prefix them with __gcov. In the
compiler we want it extern, so that they can be accessed from
elsewhere. */
#if IN_LIBGCOV
#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
#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
#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_rewrite __gcov_rewrite
#define gcov_is_eof __gcov_is_eof
#define gcov_is_error __gcov_is_error
#pragma GCC poison gcov_time
#define gcov_is_eof __gcov_is_eof
#define gcov_write_unsigned __gcov_write_unsigned
#define gcov_write_counter __gcov_write_counter
#define gcov_write_summary __gcov_write_summary
#define gcov_read_unsigned __gcov_read_unsigned
#define gcov_read_counter __gcov_read_counter
#define gcov_read_summary __gcov_read_summary
/* Poison these, so they don't accidentally slip in. */
#pragma GCC poison gcov_write_string gcov_write_tag gcov_write_length
#pragma GCC poison gcov_read_string gcov_sync gcov_time
#endif
#ifndef GCOV_LINKAGE
@ -255,18 +251,19 @@ typedef HOST_WIDEST_INT gcov_type;
file. Values [41..9f] for those in the bbg file and [a1..ff] for
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_BLOCKS ((unsigned)0x01410000)
#define GCOV_TAG_BLOCKS ((gcov_unsigned_t)0x01410000)
#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_LINES ((unsigned)0x01450000)
#define GCOV_TAG_COUNTER_BASE ((unsigned)0x01a10000) /* First counter */
#define GCOV_TAG_LINES ((gcov_unsigned_t)0x01450000)
#define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000)
#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_SUMMABLE * (2 * 4 + 3 * 8))
#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000)
#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000)
#define GCOV_TAG_SUMMARY_LENGTH \
(1 * 4 + GCOV_COUNTERS_SUMMABLE * (2 * 4 + 3 * 8))
/* Counters that are collected. */
#define GCOV_COUNTER_ARCS 0 /* Arc transitions. */
@ -282,10 +279,10 @@ typedef HOST_WIDEST_INT gcov_type;
/* Convert a counter index to a tag. */
#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. */
#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. */
#define GCOV_TAG_IS_COUNTER(TAG) \
(!((TAG) & 0xFFFF) && GCOV_COUNTER_FOR_TAG (TAG) < GCOV_COUNTERS)
@ -387,105 +384,108 @@ extern void __gcov_merge_add (gcov_type *, unsigned);
#if IN_LIBGCOV >= 0
/* Because small reads and writes, interspersed with seeks cause lots
of disk activity, we buffer the entire count files. */
/* Optimum size read from or written to disk. */
#define GCOV_BLOCK_SIZE (1 << 12)
GCOV_LINKAGE struct gcov_var
{
FILE *file;
gcov_position_t position;
gcov_position_t length;
gcov_position_t start; /* Position of first byte of block */
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;
unsigned modified;
int error;
unsigned char *buffer;
#endif
} 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_close (void);
#if !IN_GCOV
GCOV_LINKAGE unsigned char *gcov_write_bytes (unsigned);
GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t);
/* Available everywhere. */
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
/* Available only in libgcov */
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_summary (gcov_unsigned_t /*tag*/,
const struct gcov_summary *);
#endif
#endif /* !IN_GCOV */
GCOV_LINKAGE const unsigned char *gcov_read_bytes (unsigned);
GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void);
GCOV_LINKAGE gcov_type gcov_read_counter (void);
#if !IN_LIBGCOV
GCOV_LINKAGE const char *gcov_read_string (void);
#endif
GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *);
static gcov_position_t gcov_position (void);
static void gcov_sync (gcov_position_t /*base*/, gcov_unsigned_t /*length */);
static void gcov_seek (gcov_position_t /*position*/);
static void gcov_rewrite (void);
static int gcov_is_eof (void);
static int gcov_is_error (void);
GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/);
#else
/* Available outside libgcov */
GCOV_LINKAGE const char *gcov_read_string (void);
GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/,
gcov_unsigned_t /*length */);
#endif
#if !IN_GCOV
/* Available outside gcov */
GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t);
#endif
#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
/* Available in gcov */
GCOV_LINKAGE time_t gcov_time (void);
#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. */
static inline gcov_position_t
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
gcov_save_position, LENGTH should be a record length, or zero. */
static inline void
gcov_sync (gcov_position_t base, gcov_unsigned_t length)
{
if (gcov_var.buffer)
{
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. */
static inline void
gcov_seek (gcov_position_t base)
{
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 non-zero if we read to end of file. */
static inline int
gcov_is_eof ()
{
return gcov_var.position == gcov_var.length;
return !gcov_var.overread;
}
/* Return non-zero if the error flag is set. */
@ -496,6 +496,20 @@ gcov_is_error ()
return gcov_var.file ? gcov_var.error : 1;
}
#if IN_LIBGCOV
/* Move to beginning of file and intialize for writing. */
static inline void
gcov_rewrite (void)
{
GCOV_CHECK_READING ();
gcov_var.mode = -1;
gcov_var.start = 0;
gcov_var.offset = 0;
fseek (gcov_var.file, 0L, SEEK_SET);
}
#endif
#endif /* IN_LIBGCOV >= 0 */
#endif /* GCC_GCOV_IO_H */

View File

@ -711,7 +711,8 @@ read_graph_file ()
struct function_info *fn = NULL;
source_t *src = NULL;
unsigned ix;
unsigned tag;
if (!gcov_open (bbg_file_name, 1))
{
fnotice (stderr, "%s:cannot open graph file\n", bbg_file_name);
@ -740,11 +741,10 @@ read_graph_file ()
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 long base = gcov_position ();
gcov_position_t base = gcov_position ();
if (tag == GCOV_TAG_FUNCTION)
{
@ -906,12 +906,14 @@ read_graph_file ()
}
gcov_sync (base, length);
if (gcov_is_error ())
{
corrupt:;
fnotice (stderr, "%s:corrupted\n", bbg_file_name);
gcov_close ();
return 1;
}
break;
}
if (!gcov_is_eof ())
{
corrupt:;
fnotice (stderr, "%s:corrupted\n", bbg_file_name);
gcov_close ();
return 1;
}
gcov_close ();
@ -976,7 +978,9 @@ read_count_file ()
{
unsigned ix;
unsigned version;
unsigned tag;
function_t *fn = NULL;
int error = 0;
if (!gcov_open (da_file_name, 1))
{
@ -1005,12 +1009,10 @@ read_count_file ()
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 long base = gcov_position ();
int error;
if (tag == GCOV_TAG_OBJECT_SUMMARY)
gcov_read_summary (&object_summary);
@ -1061,13 +1063,16 @@ read_count_file ()
}
gcov_sync (base, length);
if ((error = gcov_is_error ()))
{
fnotice (stderr, error < 0
? "%s:overflowed\n" : "%s:corrupted\n", da_file_name);
goto cleanup;
}
break;
}
if (!gcov_is_eof ())
{
fnotice (stderr, error < 0 ? "%s:overflowed\n" : "%s:corrupted\n",
da_file_name);
goto cleanup;
}
gcov_close ();
return 0;
}

View File

@ -152,10 +152,10 @@ gcov_exit (void)
const struct gcov_ctr_info *ci_ptr;
struct gcov_ctr_summary *cs_ptr;
struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
int error;
int error = 0;
int merging;
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. */
memset (&this_object, 0, sizeof (this_object));
@ -256,12 +256,14 @@ gcov_exit (void)
}
/* Check program & object summary */
while (!gcov_is_eof ())
while (1)
{
gcov_position_t base = gcov_position ();
int is_program;
tag = gcov_read_unsigned ();
if (!tag)
break;
length = gcov_read_unsigned ();
is_program = tag == GCOV_TAG_PROGRAM_SUMMARY;
if (length != GCOV_TAG_SUMMARY_LENGTH
@ -269,24 +271,26 @@ gcov_exit (void)
goto read_mismatch;
gcov_read_summary (is_program ? &program : &object);
if ((error = gcov_is_error ()))
goto read_error;
if (is_program && program.checksum == gcov_crc32)
{
read_error:;
fprintf (stderr, error < 0 ?
"profiling:%s:Overflow merging\n" :
"profiling:%s:Error merging\n", gi_ptr->filename);
goto read_fatal;
summary_pos = base;
goto rewrite;
}
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 ();
}
else
memset (&object, 0, sizeof (object));
if (!(summary_pos + 1))
if (!summary_pos)
memset (&program, 0, sizeof (program));
/* Merge the summaries. */