gcov-io.h: Update documentation.
* gcov-io.h: Update documentation. (GCOV_GRAPH_SUFFIX, GCOV_GRAPH_MAGIC): Rename to GCOV_NOTE_SUFFIX, GCOV_NOTE_MAGIC. (GCOV_DATA_SUFFIX, GCOV_NOTE_SUFFIX): Update. (GCOV_DATA_MAGIC, GCOV_NOTE_MAGIC): Make non-palindromic. (struct gcov_var): Change buffer's type. Add endian flag. (gcov_open): Remove mode in libgcov. (gcov_magic): Prototype. * gcov-io.c (from_file): New. (gcov_open): Clear endian flag. (gcov_magic): New. (gcov_write_bytes, gcov_read_bytes): Return gcov_unsigned_t pointers. (gcov_write_unsigned, gcov_write_counter, gcov_write_string, gcov_write_tag, gcov_write_length, gcov_write_tag_length): Update. (gcov_read_unsigned, gcov_read_counter, gcov_read_string): Update. * gcov-iov.c (main): Correct cast. * coverage.c (read_counts_file): Use gcov_magic. Remove endianness conversion. (gcov_begin_output): Use GCOV_NOTE_MAGIC. (coverage_init): Use GCOV_NOTE_SUFFIX. * libgcov.c (gcov_version_mismatch): Remove endianness conversion. Rename to gcov_version, and return flag. (gcov_exit): Use gcov_version. (__gcov_init): Use gcov_version. * Makefile.in (coverageexts): Update. * gcov.c (print_version): Remove endianness conversion. (create_file_names): Use GCOV_NOTE_SUFFIX. (read_graph_file): Use gcov_magic. (read_count_file): Likewise. * gcov-dump.c (dump_file): Remove endianness conversion, use gcov_magic. From-SVN: r69137
This commit is contained in:
parent
83599948cd
commit
160e2e4f23
@ -1,3 +1,38 @@
|
|||||||
|
2003-07-09 Nathan Sidwell <nathan@codesourcery.com>
|
||||||
|
|
||||||
|
* gcov-io.h: Update documentation.
|
||||||
|
(GCOV_GRAPH_SUFFIX, GCOV_GRAPH_MAGIC): Rename to GCOV_NOTE_SUFFIX,
|
||||||
|
GCOV_NOTE_MAGIC.
|
||||||
|
(GCOV_DATA_SUFFIX, GCOV_NOTE_SUFFIX): Update.
|
||||||
|
(GCOV_DATA_MAGIC, GCOV_NOTE_MAGIC): Make non-palindromic.
|
||||||
|
(struct gcov_var): Change buffer's type. Add endian flag.
|
||||||
|
(gcov_open): Remove mode in libgcov.
|
||||||
|
(gcov_magic): Prototype.
|
||||||
|
* gcov-io.c (from_file): New.
|
||||||
|
(gcov_open): Clear endian flag.
|
||||||
|
(gcov_magic): New.
|
||||||
|
(gcov_write_bytes, gcov_read_bytes): Return gcov_unsigned_t
|
||||||
|
pointers.
|
||||||
|
(gcov_write_unsigned, gcov_write_counter, gcov_write_string,
|
||||||
|
gcov_write_tag, gcov_write_length, gcov_write_tag_length): Update.
|
||||||
|
(gcov_read_unsigned, gcov_read_counter, gcov_read_string): Update.
|
||||||
|
* gcov-iov.c (main): Correct cast.
|
||||||
|
* coverage.c (read_counts_file): Use gcov_magic. Remove endianness
|
||||||
|
conversion.
|
||||||
|
(gcov_begin_output): Use GCOV_NOTE_MAGIC.
|
||||||
|
(coverage_init): Use GCOV_NOTE_SUFFIX.
|
||||||
|
* libgcov.c (gcov_version_mismatch): Remove endianness conversion.
|
||||||
|
Rename to gcov_version, and return flag.
|
||||||
|
(gcov_exit): Use gcov_version.
|
||||||
|
(__gcov_init): Use gcov_version.
|
||||||
|
* Makefile.in (coverageexts): Update.
|
||||||
|
* gcov.c (print_version): Remove endianness conversion.
|
||||||
|
(create_file_names): Use GCOV_NOTE_SUFFIX.
|
||||||
|
(read_graph_file): Use gcov_magic.
|
||||||
|
(read_count_file): Likewise.
|
||||||
|
* gcov-dump.c (dump_file): Remove endianness conversion, use
|
||||||
|
gcov_magic.
|
||||||
|
|
||||||
2003-07-09 Nathan Sidwell <nathan@codesourcery.com>
|
2003-07-09 Nathan Sidwell <nathan@codesourcery.com>
|
||||||
|
|
||||||
* configure.in (BUILD_PREFIX, BUILD_PREFIX_1): Set if enable
|
* configure.in (BUILD_PREFIX, BUILD_PREFIX_1): Set if enable
|
||||||
|
@ -125,7 +125,7 @@ BOOT_CFLAGS = -g -O2
|
|||||||
# contain the optimization flags, as you normally want code coverage
|
# contain the optimization flags, as you normally want code coverage
|
||||||
# without optimization.
|
# without optimization.
|
||||||
COVERAGE_FLAGS = @coverage_flags@
|
COVERAGE_FLAGS = @coverage_flags@
|
||||||
coverageexts = .{da,bbg}
|
coverageexts = .{gcda,gcno}
|
||||||
|
|
||||||
# The warning flags are separate from BOOT_CFLAGS because people tend to
|
# The warning flags are separate from BOOT_CFLAGS because people tend to
|
||||||
# override optimization flags and we'd like them to still have warnings
|
# override optimization flags and we'd like them to still have warnings
|
||||||
|
@ -150,8 +150,7 @@ static void
|
|||||||
read_counts_file (void)
|
read_counts_file (void)
|
||||||
{
|
{
|
||||||
gcov_unsigned_t fn_ident = 0;
|
gcov_unsigned_t fn_ident = 0;
|
||||||
gcov_unsigned_t version, checksum = -1;
|
gcov_unsigned_t checksum = -1;
|
||||||
unsigned ix;
|
|
||||||
counts_entry_t *summaried = NULL;
|
counts_entry_t *summaried = NULL;
|
||||||
unsigned seen_summary = 0;
|
unsigned seen_summary = 0;
|
||||||
gcov_unsigned_t tag;
|
gcov_unsigned_t tag;
|
||||||
@ -160,24 +159,18 @@ read_counts_file (void)
|
|||||||
if (!gcov_open (da_file_name, 1))
|
if (!gcov_open (da_file_name, 1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
|
if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
|
||||||
{
|
{
|
||||||
warning ("`%s' is not a gcov data file", da_file_name);
|
warning ("`%s' is not a gcov data file", da_file_name);
|
||||||
gcov_close ();
|
gcov_close ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ((version = gcov_read_unsigned ()) != GCOV_VERSION)
|
else if ((tag = gcov_read_unsigned ()) != GCOV_VERSION)
|
||||||
{
|
{
|
||||||
char v[4], e[4];
|
|
||||||
gcov_unsigned_t required = GCOV_VERSION;
|
gcov_unsigned_t required = GCOV_VERSION;
|
||||||
|
|
||||||
for (ix = 4; ix--; required >>= 8, version >>= 8)
|
|
||||||
{
|
|
||||||
v[ix] = version;
|
|
||||||
e[ix] = required;
|
|
||||||
}
|
|
||||||
warning ("`%s' is version `%.4s', expected version `%.4s'",
|
warning ("`%s' is version `%.4s', expected version `%.4s'",
|
||||||
da_file_name, v, e);
|
da_file_name, (const char *)&tag, (const char *)&required);
|
||||||
gcov_close ();
|
gcov_close ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -446,7 +439,7 @@ coverage_begin_output (void)
|
|||||||
error ("cannot open %s", bbg_file_name);
|
error ("cannot open %s", bbg_file_name);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gcov_write_unsigned (GCOV_GRAPH_MAGIC);
|
gcov_write_unsigned (GCOV_NOTE_MAGIC);
|
||||||
gcov_write_unsigned (GCOV_VERSION);
|
gcov_write_unsigned (GCOV_VERSION);
|
||||||
gcov_write_unsigned (local_tick);
|
gcov_write_unsigned (local_tick);
|
||||||
}
|
}
|
||||||
@ -897,9 +890,9 @@ coverage_init (const char *filename)
|
|||||||
strcat (da_file_name, GCOV_DATA_SUFFIX);
|
strcat (da_file_name, GCOV_DATA_SUFFIX);
|
||||||
|
|
||||||
/* Name of bbg file. */
|
/* Name of bbg file. */
|
||||||
bbg_file_name = (char *) xmalloc (len + strlen (GCOV_GRAPH_SUFFIX) + 1);
|
bbg_file_name = (char *) xmalloc (len + strlen (GCOV_NOTE_SUFFIX) + 1);
|
||||||
strcpy (bbg_file_name, filename);
|
strcpy (bbg_file_name, filename);
|
||||||
strcat (bbg_file_name, GCOV_GRAPH_SUFFIX);
|
strcat (bbg_file_name, GCOV_NOTE_SUFFIX);
|
||||||
|
|
||||||
read_counts_file ();
|
read_counts_file ();
|
||||||
}
|
}
|
||||||
|
@ -155,33 +155,32 @@ dump_file (const char *filename)
|
|||||||
/* magic */
|
/* magic */
|
||||||
{
|
{
|
||||||
unsigned magic = gcov_read_unsigned ();
|
unsigned magic = gcov_read_unsigned ();
|
||||||
unsigned version = gcov_read_unsigned ();
|
unsigned version;
|
||||||
const char *type = NULL;
|
const char *type = NULL;
|
||||||
char e[4], v[4], m[4];
|
int endianness = 0;
|
||||||
unsigned expected = GCOV_VERSION;
|
|
||||||
unsigned ix;
|
if ((endianness = gcov_magic (magic, GCOV_DATA_MAGIC)))
|
||||||
int different = version != GCOV_VERSION;
|
|
||||||
|
|
||||||
if (magic == GCOV_DATA_MAGIC)
|
|
||||||
type = "data";
|
type = "data";
|
||||||
else if (magic == GCOV_GRAPH_MAGIC)
|
else if ((endianness = gcov_magic (magic, GCOV_NOTE_MAGIC)))
|
||||||
type = "graph";
|
type = "note";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf ("%s:not a gcov file\n", filename);
|
printf ("%s:not a gcov file\n", filename);
|
||||||
gcov_close ();
|
gcov_close ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (ix = 4; ix--; expected >>= 8, version >>= 8, magic >>= 8)
|
version = gcov_read_unsigned ();
|
||||||
|
|
||||||
|
printf ("%s:%s:magic `%.4s':version `%.4s'%s\n", filename, type,
|
||||||
|
(const char *)&magic, (const char *)&version,
|
||||||
|
endianness < 0 ? " (swapped endianness)" : "");
|
||||||
|
if (version != GCOV_VERSION)
|
||||||
{
|
{
|
||||||
e[ix] = expected;
|
unsigned expected = GCOV_VERSION;
|
||||||
v[ix] = version;
|
|
||||||
m[ix] = magic;
|
printf ("%s:warning:current version is `%.4s'\n", filename,
|
||||||
|
(const char *)expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("%s:%s:magic `%.4s':version `%.4s'\n", filename, type, m, v);
|
|
||||||
if (different)
|
|
||||||
printf ("%s:warning:current version is `%.4s'\n", filename, e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stamp */
|
/* stamp */
|
||||||
|
194
gcc/gcov-io.c
194
gcc/gcov-io.c
@ -26,13 +26,25 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||||||
|
|
||||||
#if !IN_GCOV
|
#if !IN_GCOV
|
||||||
static void gcov_write_block (unsigned);
|
static void gcov_write_block (unsigned);
|
||||||
static unsigned char *gcov_write_bytes (unsigned);
|
static gcov_unsigned_t *gcov_write_bytes (unsigned);
|
||||||
#endif
|
#endif
|
||||||
static const unsigned char *gcov_read_bytes (unsigned);
|
static const gcov_unsigned_t *gcov_read_bytes (unsigned);
|
||||||
#if !IN_LIBGCOV
|
#if !IN_LIBGCOV
|
||||||
static void gcov_allocate (unsigned);
|
static void gcov_allocate (unsigned);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline gcov_unsigned_t from_file (gcov_unsigned_t value)
|
||||||
|
{
|
||||||
|
#if !IN_LIBGCOV
|
||||||
|
if (gcov_var.endian)
|
||||||
|
{
|
||||||
|
value = (value >> 16) | (value << 16);
|
||||||
|
value = ((value & 0xff00ff) << 8) | ((value >> 8) & 0xff00ff);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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
|
||||||
@ -42,9 +54,15 @@ static void gcov_allocate (unsigned);
|
|||||||
opening an existing file and <0 on creating a new one. */
|
opening an existing file and <0 on creating a new one. */
|
||||||
|
|
||||||
GCOV_LINKAGE int
|
GCOV_LINKAGE int
|
||||||
|
#if IN_LIBGCOV
|
||||||
|
gcov_open (const char *name)
|
||||||
|
#else
|
||||||
gcov_open (const char *name, int mode)
|
gcov_open (const char *name, int mode)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
int result = 1;
|
#if IN_LIBGCOV
|
||||||
|
const int mode = 0;
|
||||||
|
#endif
|
||||||
#if GCOV_LOCKED
|
#if GCOV_LOCKED
|
||||||
struct flock s_flock;
|
struct flock s_flock;
|
||||||
|
|
||||||
@ -61,20 +79,22 @@ gcov_open (const char *name, int mode)
|
|||||||
gcov_var.offset = gcov_var.length = 0;
|
gcov_var.offset = gcov_var.length = 0;
|
||||||
gcov_var.overread = -4u;
|
gcov_var.overread = -4u;
|
||||||
gcov_var.error = 0;
|
gcov_var.error = 0;
|
||||||
|
#if !IN_LIBGCOV
|
||||||
|
gcov_var.endian = 0;
|
||||||
|
#endif
|
||||||
if (mode >= 0)
|
if (mode >= 0)
|
||||||
gcov_var.file = fopen (name, "r+b");
|
gcov_var.file = fopen (name, "r+b");
|
||||||
if (gcov_var.file)
|
if (gcov_var.file)
|
||||||
gcov_var.mode = 1;
|
gcov_var.mode = 1;
|
||||||
else if (mode <= 0)
|
else if (mode <= 0)
|
||||||
{
|
{
|
||||||
result = -1;
|
|
||||||
gcov_var.file = fopen (name, "w+b");
|
gcov_var.file = fopen (name, "w+b");
|
||||||
if (gcov_var.file)
|
if (gcov_var.file)
|
||||||
gcov_var.mode = -1;
|
gcov_var.mode = mode * 2 + 1;
|
||||||
}
|
}
|
||||||
if (!gcov_var.file)
|
if (!gcov_var.file)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
setbuf (gcov_var.file, (char *)0);
|
setbuf (gcov_var.file, (char *)0);
|
||||||
|
|
||||||
#if GCOV_LOCKED
|
#if GCOV_LOCKED
|
||||||
@ -83,7 +103,7 @@ gcov_open (const char *name, int mode)
|
|||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return result;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close the current gcov file. Flushes data to disk. Returns nonzero
|
/* Close the current gcov file. Flushes data to disk. Returns nonzero
|
||||||
@ -111,6 +131,27 @@ gcov_close (void)
|
|||||||
return gcov_var.error;
|
return gcov_var.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !IN_LIBGCOV
|
||||||
|
/* Check if MAGIC is EXPECTED. Use it to determine endianness of the
|
||||||
|
file. Returns +1 for same endian, -1 for other endian and zero for
|
||||||
|
not EXPECTED. */
|
||||||
|
|
||||||
|
GCOV_LINKAGE int
|
||||||
|
gcov_magic (gcov_unsigned_t magic, gcov_unsigned_t expected)
|
||||||
|
{
|
||||||
|
if (magic == expected)
|
||||||
|
return 1;
|
||||||
|
magic = (magic >> 16) | (magic << 16);
|
||||||
|
magic = ((magic & 0xff00ff) << 8) | ((magic >> 8) & 0xff00ff);
|
||||||
|
if (magic == expected)
|
||||||
|
{
|
||||||
|
gcov_var.endian = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !IN_LIBGCOV
|
#if !IN_LIBGCOV
|
||||||
static void
|
static void
|
||||||
gcov_allocate (unsigned length)
|
gcov_allocate (unsigned length)
|
||||||
@ -142,12 +183,13 @@ gcov_write_block (unsigned 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. */
|
||||||
|
|
||||||
static unsigned char *
|
static gcov_unsigned_t *
|
||||||
gcov_write_bytes (unsigned bytes)
|
gcov_write_bytes (unsigned bytes)
|
||||||
{
|
{
|
||||||
char unsigned *result;
|
gcov_unsigned_t *result;
|
||||||
|
|
||||||
GCOV_CHECK_WRITING ();
|
GCOV_CHECK_WRITING ();
|
||||||
|
GCOV_CHECK (!(bytes & 3));
|
||||||
#if IN_LIBGCOV
|
#if IN_LIBGCOV
|
||||||
if (gcov_var.offset >= GCOV_BLOCK_SIZE)
|
if (gcov_var.offset >= GCOV_BLOCK_SIZE)
|
||||||
{
|
{
|
||||||
@ -162,7 +204,7 @@ gcov_write_bytes (unsigned bytes)
|
|||||||
if (gcov_var.offset + bytes > gcov_var.alloc)
|
if (gcov_var.offset + bytes > gcov_var.alloc)
|
||||||
gcov_allocate (gcov_var.offset + bytes);
|
gcov_allocate (gcov_var.offset + bytes);
|
||||||
#endif
|
#endif
|
||||||
result = &gcov_var.buffer[gcov_var.offset];
|
result = (gcov_unsigned_t *)&gcov_var.buffer[gcov_var.offset];
|
||||||
gcov_var.offset += bytes;
|
gcov_var.offset += bytes;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -174,18 +216,9 @@ gcov_write_bytes (unsigned bytes)
|
|||||||
GCOV_LINKAGE void
|
GCOV_LINKAGE void
|
||||||
gcov_write_unsigned (gcov_unsigned_t value)
|
gcov_write_unsigned (gcov_unsigned_t value)
|
||||||
{
|
{
|
||||||
unsigned char *buffer = gcov_write_bytes (4);
|
gcov_unsigned_t *buffer = gcov_write_bytes (4);
|
||||||
unsigned ix;
|
|
||||||
|
|
||||||
for (ix = 4; ix--; )
|
buffer[0] = value;
|
||||||
{
|
|
||||||
buffer[ix] = value;
|
|
||||||
value >>= 8;
|
|
||||||
}
|
|
||||||
if (sizeof (value) > 4 && value)
|
|
||||||
gcov_var.error = -1;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write counter VALUE to coverage file. Sets error flag
|
/* Write counter VALUE to coverage file. Sets error flag
|
||||||
@ -195,17 +228,16 @@ gcov_write_unsigned (gcov_unsigned_t value)
|
|||||||
GCOV_LINKAGE void
|
GCOV_LINKAGE void
|
||||||
gcov_write_counter (gcov_type value)
|
gcov_write_counter (gcov_type value)
|
||||||
{
|
{
|
||||||
unsigned char *buffer = gcov_write_bytes (8);
|
gcov_unsigned_t *buffer = gcov_write_bytes (8);
|
||||||
unsigned ix;
|
|
||||||
|
|
||||||
for (ix = 8; ix--; )
|
buffer[0] = (gcov_unsigned_t) value;
|
||||||
{
|
if (sizeof (value) > sizeof (gcov_unsigned_t))
|
||||||
buffer[ix] = value;
|
buffer[1] = (gcov_unsigned_t) (value >> 32);
|
||||||
value >>= 8;
|
else
|
||||||
}
|
buffer[1] = 0;
|
||||||
if ((sizeof (value) > 8 && value) || value < 0)
|
|
||||||
|
if (value < 0)
|
||||||
gcov_var.error = -1;
|
gcov_var.error = -1;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
#endif /* IN_LIBGCOV */
|
#endif /* IN_LIBGCOV */
|
||||||
|
|
||||||
@ -217,28 +249,20 @@ GCOV_LINKAGE void
|
|||||||
gcov_write_string (const char *string)
|
gcov_write_string (const char *string)
|
||||||
{
|
{
|
||||||
unsigned length = 0;
|
unsigned length = 0;
|
||||||
unsigned pad = 0;
|
unsigned alloc = 0;
|
||||||
unsigned rem = 0;
|
gcov_unsigned_t *buffer;
|
||||||
unsigned char *buffer;
|
|
||||||
unsigned ix;
|
|
||||||
unsigned value;
|
|
||||||
|
|
||||||
if (string)
|
if (string)
|
||||||
{
|
{
|
||||||
length = strlen (string);
|
length = strlen (string);
|
||||||
rem = 4 - (length & 3);
|
alloc = (length + 4) >> 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = gcov_write_bytes (4 + length + rem);
|
buffer = gcov_write_bytes (4 + alloc * 4);
|
||||||
|
|
||||||
value = length;
|
buffer[0] = alloc;
|
||||||
for (ix = 4; ix--; )
|
buffer[alloc] = 0;
|
||||||
{
|
memcpy (&buffer[1], string, length);
|
||||||
buffer[ix] = value;
|
|
||||||
value >>= 8;
|
|
||||||
}
|
|
||||||
memcpy (buffer + 4, string, length);
|
|
||||||
memcpy (buffer + 4 + length, &pad, rem);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -250,15 +274,11 @@ 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.start + gcov_var.offset;
|
gcov_position_t result = gcov_var.start + gcov_var.offset;
|
||||||
unsigned char *buffer = gcov_write_bytes (8);
|
gcov_unsigned_t *buffer = gcov_write_bytes (8);
|
||||||
unsigned ix;
|
|
||||||
|
|
||||||
for (ix = 4; ix--; )
|
buffer[0] = tag;
|
||||||
{
|
buffer[1] = 0;
|
||||||
buffer[ix] = tag;
|
|
||||||
tag >>= 8;
|
|
||||||
}
|
|
||||||
memset (buffer + 4, 0, 4);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,20 +292,15 @@ gcov_write_length (gcov_position_t position)
|
|||||||
{
|
{
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
gcov_unsigned_t length;
|
gcov_unsigned_t length;
|
||||||
unsigned char *buffer;
|
gcov_unsigned_t *buffer;
|
||||||
unsigned ix;
|
|
||||||
|
|
||||||
GCOV_CHECK_WRITING ();
|
GCOV_CHECK_WRITING ();
|
||||||
GCOV_CHECK (position + 8 <= gcov_var.start + gcov_var.offset);
|
GCOV_CHECK (position + 8 <= gcov_var.start + gcov_var.offset);
|
||||||
GCOV_CHECK (position >= gcov_var.start);
|
GCOV_CHECK (position >= gcov_var.start);
|
||||||
offset = position - gcov_var.start;
|
offset = position - gcov_var.start;
|
||||||
length = gcov_var.offset - offset - 8;
|
length = gcov_var.offset - offset - 8;
|
||||||
buffer = &gcov_var.buffer[offset + 4];
|
buffer = (gcov_unsigned_t *) &gcov_var.buffer[offset];
|
||||||
for (ix = 4; ix--; )
|
buffer[1] = length;
|
||||||
{
|
|
||||||
buffer[ix] = length;
|
|
||||||
length >>= 8;
|
|
||||||
}
|
|
||||||
if (gcov_var.offset >= GCOV_BLOCK_SIZE)
|
if (gcov_var.offset >= GCOV_BLOCK_SIZE)
|
||||||
gcov_write_block (gcov_var.offset);
|
gcov_write_block (gcov_var.offset);
|
||||||
}
|
}
|
||||||
@ -297,20 +312,10 @@ gcov_write_length (gcov_position_t position)
|
|||||||
GCOV_LINKAGE void
|
GCOV_LINKAGE void
|
||||||
gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length)
|
gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length)
|
||||||
{
|
{
|
||||||
unsigned char *buffer = gcov_write_bytes (8);
|
gcov_unsigned_t *buffer = gcov_write_bytes (8);
|
||||||
unsigned ix;
|
|
||||||
|
|
||||||
for (ix = 4; ix--; )
|
buffer[0] = tag;
|
||||||
{
|
buffer[1] = length;
|
||||||
buffer[ix] = tag;
|
|
||||||
tag >>= 8;
|
|
||||||
}
|
|
||||||
for (ix = 4; ix--; )
|
|
||||||
{
|
|
||||||
buffer[ix + 4] = length;
|
|
||||||
length >>= 8;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a summary structure to the gcov file. Return nonzero on
|
/* Write a summary structure to the gcov file. Return nonzero on
|
||||||
@ -340,13 +345,14 @@ 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). */
|
||||||
|
|
||||||
static const unsigned char *
|
static const gcov_unsigned_t *
|
||||||
gcov_read_bytes (unsigned bytes)
|
gcov_read_bytes (unsigned bytes)
|
||||||
{
|
{
|
||||||
const unsigned char *result;
|
const gcov_unsigned_t *result;
|
||||||
unsigned excess = gcov_var.length - gcov_var.offset;
|
unsigned excess = gcov_var.length - gcov_var.offset;
|
||||||
|
|
||||||
GCOV_CHECK_READING ();
|
GCOV_CHECK_READING ();
|
||||||
|
GCOV_CHECK (!(bytes & 3));
|
||||||
if (excess < bytes)
|
if (excess < bytes)
|
||||||
{
|
{
|
||||||
gcov_var.start += gcov_var.offset;
|
gcov_var.start += gcov_var.offset;
|
||||||
@ -379,7 +385,7 @@ gcov_read_bytes (unsigned bytes)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = &gcov_var.buffer[gcov_var.offset];
|
result = (gcov_unsigned_t *)&gcov_var.buffer[gcov_var.offset];
|
||||||
gcov_var.offset += bytes;
|
gcov_var.offset += bytes;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -390,20 +396,12 @@ gcov_read_bytes (unsigned bytes)
|
|||||||
GCOV_LINKAGE gcov_unsigned_t
|
GCOV_LINKAGE gcov_unsigned_t
|
||||||
gcov_read_unsigned (void)
|
gcov_read_unsigned (void)
|
||||||
{
|
{
|
||||||
gcov_unsigned_t value = 0;
|
gcov_unsigned_t value;
|
||||||
unsigned ix;
|
const gcov_unsigned_t *buffer = gcov_read_bytes (4);
|
||||||
const unsigned char *buffer = gcov_read_bytes (4);
|
|
||||||
|
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return 0;
|
return 0;
|
||||||
for (ix = sizeof (value); ix < 4; ix++)
|
value = from_file (buffer[0]);
|
||||||
if (buffer[ix])
|
|
||||||
gcov_var.error = -1;
|
|
||||||
for (ix = 0; ix != 4; ix++)
|
|
||||||
{
|
|
||||||
value <<= 8;
|
|
||||||
value |= buffer[ix];
|
|
||||||
}
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,20 +411,17 @@ gcov_read_unsigned (void)
|
|||||||
GCOV_LINKAGE gcov_type
|
GCOV_LINKAGE gcov_type
|
||||||
gcov_read_counter (void)
|
gcov_read_counter (void)
|
||||||
{
|
{
|
||||||
gcov_type value = 0;
|
gcov_type value;
|
||||||
unsigned ix;
|
const gcov_unsigned_t *buffer = gcov_read_bytes (8);
|
||||||
const unsigned char *buffer = gcov_read_bytes (8);
|
|
||||||
|
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return 0;
|
return 0;
|
||||||
for (ix = sizeof (value); ix < 8; ix++)
|
value = from_file (buffer[0]);
|
||||||
if (buffer[ix])
|
if (sizeof (value) > sizeof (gcov_unsigned_t))
|
||||||
gcov_var.error = -1;
|
value |= ((gcov_type) from_file (buffer[1])) << 32;
|
||||||
for (ix = 0; ix != 8; ix++)
|
else if (buffer[1])
|
||||||
{
|
gcov_var.error = -1;
|
||||||
value <<= 8;
|
|
||||||
value |= buffer[ix];
|
|
||||||
}
|
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
gcov_var.error = -1;
|
gcov_var.error = -1;
|
||||||
return value;
|
return value;
|
||||||
@ -445,7 +440,6 @@ gcov_read_string (void)
|
|||||||
if (!length)
|
if (!length)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
length += 4 - (length & 3);
|
|
||||||
return (const char *) gcov_read_bytes (length);
|
return (const char *) gcov_read_bytes (length);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
170
gcc/gcov-io.h
170
gcc/gcov-io.h
@ -28,24 +28,25 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||||||
This exception does not however invalidate any other reasons why
|
This exception does not however invalidate any other reasons why
|
||||||
the executable file might be covered by the GNU General Public License. */
|
the executable file might be covered by the GNU General Public License. */
|
||||||
|
|
||||||
/* Coverage information is held in two files. A basic block graph
|
/* Coverage information is held in two files. A notes file, which is
|
||||||
file, which is generated by the compiler, and a counter file, which
|
generated by the compiler, and a data file, which is generated
|
||||||
is generated by the program under test. Both files use a similar
|
by the program under test. Both files use a similar structure. We
|
||||||
structure. We do not attempt to make these files backwards
|
do not attempt to make these files backwards compatible with
|
||||||
compatible with previous versions, as you only need coverage
|
previous versions, as you only need coverage information when
|
||||||
information when developing a program. We do hold version
|
developing a program. We do hold version information, so that
|
||||||
information, so that mismatches can be detected, and we use a
|
mismatches can be detected, and we use a format that allows tools
|
||||||
format that allows tools to skip information they do not understand
|
to skip information they do not understand or are not interested
|
||||||
or are not interested in.
|
in.
|
||||||
|
|
||||||
Numbers are recorded in big endian unsigned binary form. Either in
|
Numbers are recorded in the 32 bit unsigned binary form of the
|
||||||
32 or 64 bits. Strings are stored with a length count and NUL
|
endianness of the machine generating the file. 64 bit numbers are
|
||||||
terminator, and 0 to 3 bytes of zero padding up to the next 4 byte
|
stored as two 32 bit numbers, the low part first. Strings are
|
||||||
boundary. Zero length and NULL strings are simply stored as a
|
stored as length rounded up to 4 followed by the string and then 1
|
||||||
length of zero (they have no trailing NUL or padding).
|
to 4 NUL bytes. Zero length and NULL strings are simply stored as
|
||||||
|
a length of zero (they have no trailing NUL or padding).
|
||||||
|
|
||||||
int32: byte3 byte2 byte1 byte0
|
int32: byte3 byte2 byte1 byte0 | byte0 byte1 byte2 byte3
|
||||||
int64: byte7 byte6 byte5 byte4 byte3 byte2 byte1 byte0
|
int64: int32:low int32:high
|
||||||
string: int32:0 | int32:length char* char:0 padding
|
string: int32:0 | int32:length char* char:0 padding
|
||||||
padding: | char:0 | char:0 char:0 | char:0 char:0 char:0
|
padding: | char:0 | char:0 char:0 | char:0 char:0 char:0
|
||||||
item: int32 | int64 | string
|
item: int32 | int64 | string
|
||||||
@ -54,31 +55,30 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||||||
|
|
||||||
file : int32:magic int32:version int32:stamp record*
|
file : int32:magic int32:version int32:stamp record*
|
||||||
|
|
||||||
The magic ident is different for the bbg and the counter files.
|
The magic ident is different for the notes and the data files. The
|
||||||
The version is the same for both files and is derived from gcc's
|
magic ident is used to determine the endianness of the file, when
|
||||||
version number. The stamp value is used to synchronize bbg and
|
reading. The version is the same for both files and is derived
|
||||||
counter files and to synchronize merging within a counter file. It
|
from gcc's version number. The stamp value is used to synchronize
|
||||||
need not be an absolute time stamp, merely a ticker that increments
|
note and data files and to synchronize merging within a data
|
||||||
fast enough and cycles slow enough to distinguish different
|
file. It need not be an absolute time stamp, merely a ticker that
|
||||||
compile/run/compile cycles.
|
increments fast enough and cycles slow enough to distinguish
|
||||||
|
different compile/run/compile cycles.
|
||||||
|
|
||||||
Although the ident and version are formally 32 bit
|
Although the ident and version are formally 32 bit numbers, they
|
||||||
numbers, they are derived from 4 character ASCII strings. The
|
are derived from 4 character ASCII strings. The version number
|
||||||
version number consists of the single character major version
|
consists of the single character major version number, a two
|
||||||
number, a two character minor version number (leading zero for
|
character minor version number (leading zero for versions less than
|
||||||
versions less than 10), and a single character indicating the
|
10), and a single character indicating the status of the release.
|
||||||
status of the release. That will be 'e' experimental, 'p'
|
That will be 'e' experimental, 'p' prerelease and 'r' for release.
|
||||||
prerelease and 'r' for release. Because, by good fortune, these are
|
Because, by good fortune, these are in alphabetical order, string
|
||||||
in alphabetical order, string collating can be used to compare
|
collating can be used to compare version strings. Be aware that
|
||||||
version strings, and because numbers are stored big endian, numeric
|
the 'e' designation will (naturally) be unstable and might be
|
||||||
comparison can be used when it is read as a 32 bit value. Be aware
|
|
||||||
that the 'e' designation will (naturally) be unstable and might be
|
|
||||||
incompatible with itself. For gcc 3.4 experimental, it would be
|
incompatible with itself. For gcc 3.4 experimental, it would be
|
||||||
'304e' (0x33303465). When the major version reaches 10, the letters
|
'304e' (0x33303465). When the major version reaches 10, the
|
||||||
A-Z will be used. Assuming minor increments releases every 6
|
letters A-Z will be used. Assuming minor increments releases every
|
||||||
months, we have to make a major increment every 50 years. Assuming
|
6 months, we have to make a major increment every 50 years.
|
||||||
major increments releases every 5 years, we're ok for the next 155
|
Assuming major increments releases every 5 years, we're ok for the
|
||||||
years -- good enough for me.
|
next 155 years -- good enough for me.
|
||||||
|
|
||||||
A record has a tag, length and variable amount of data.
|
A record has a tag, length and variable amount of data.
|
||||||
|
|
||||||
@ -87,21 +87,21 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||||||
data: item*
|
data: item*
|
||||||
|
|
||||||
Records are not nested, but there is a record hierarchy. Tag
|
Records are not nested, but there is a record hierarchy. Tag
|
||||||
numbers reflect this hierarchy. Tags are unique across bbg and da
|
numbers reflect this hierarchy. Tags are unique across note and
|
||||||
files. Some record types have a varying amount of data. The LENGTH
|
data files. Some record types have a varying amount of data. The
|
||||||
is usually used to determine how much data. The tag value is split
|
LENGTH is usually used to determine how much data. The tag value
|
||||||
into 4 8-bit fields, one for each of four possible levels. The
|
is split into 4 8-bit fields, one for each of four possible levels.
|
||||||
most significant is allocated first. Unused levels are zero.
|
The most significant is allocated first. Unused levels are zero.
|
||||||
Active levels are odd-valued, so that the LSB of the level is one.
|
Active levels are odd-valued, so that the LSB of the level is one.
|
||||||
A sub-level incorporates the values of its superlevels. This
|
A sub-level incorporates the values of its superlevels. This
|
||||||
formatting allows you to determine the tag hierarchy, without
|
formatting allows you to determine the tag hierarchy, without
|
||||||
understanding the tags themselves, and is similar to the standard
|
understanding the tags themselves, and is similar to the standard
|
||||||
section numbering used in technical documents. Level values
|
section numbering used in technical documents. Level values
|
||||||
[1..3f] are used for common tags, values [41..9f] for the graph
|
[1..3f] are used for common tags, values [41..9f] for the notes
|
||||||
file and [a1..ff] for the counter file.
|
file and [a1..ff] for the data file.
|
||||||
|
|
||||||
The basic block graph file contains the following records
|
The basic block graph file contains the following records
|
||||||
bbg: unit function-graph*
|
note: unit function-graph*
|
||||||
unit: header int32:checksum string:source
|
unit: header int32:checksum string:source
|
||||||
function-graph: announce_function basic_blocks {arcs | lines}*
|
function-graph: announce_function basic_blocks {arcs | lines}*
|
||||||
announce_function: header int32:ident int32:checksum
|
announce_function: header int32:ident int32:checksum
|
||||||
@ -130,7 +130,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||||||
blocks they are for.
|
blocks they are for.
|
||||||
|
|
||||||
The data file contains the following records.
|
The data file contains the following records.
|
||||||
da: {unit function-data* summary:object summary:program*}*
|
data: {unit function-data* summary:object summary:program*}*
|
||||||
unit: header int32:checksum
|
unit: header int32:checksum
|
||||||
function-data: announce_function arc_counts
|
function-data: announce_function arc_counts
|
||||||
announce_function: header int32:ident int32:checksum
|
announce_function: header int32:ident int32:checksum
|
||||||
@ -139,17 +139,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||||||
count-summary: int32:num int32:runs int64:sum
|
count-summary: int32:num int32:runs int64:sum
|
||||||
int64:max int64:sum_max
|
int64:max int64:sum_max
|
||||||
|
|
||||||
The ANNOUNCE_FUNCTION record is the same as that in the BBG file,
|
The ANNOUNCE_FUNCTION record is the same as that in the note file,
|
||||||
but without the source location.
|
but without the source location. The ARC_COUNTS gives the counter
|
||||||
The ARC_COUNTS gives the counter values for those arcs that are
|
values for those arcs that are instrumented. The SUMMARY records
|
||||||
instrumented. The SUMMARY records give information about the whole
|
give information about the whole object file and about the whole
|
||||||
object file and about the whole program. The checksum is used for
|
program. The checksum is used for whole program summaries, and
|
||||||
whole program summaries, and disambiguates different programs which
|
disambiguates different programs which include the same
|
||||||
include the same instrumented object file. There may be several
|
instrumented object file. There may be several program summaries,
|
||||||
program summaries, each with a unique checksum. The object
|
each with a unique checksum. The object summary's checkum is zero.
|
||||||
summary's checkum is zero. Note that the da file might contain
|
Note that the data file might contain information from several runs
|
||||||
information from several runs concatenated, or the data might be
|
concatenated, or the data might be merged.
|
||||||
merged.
|
|
||||||
|
|
||||||
This file is included by both the compiler, gcov tools and the
|
This file is included by both the compiler, gcov tools and the
|
||||||
runtime support library libgcov. IN_LIBGCOV and IN_GCOV are used to
|
runtime support library libgcov. IN_LIBGCOV and IN_GCOV are used to
|
||||||
@ -231,7 +230,7 @@ typedef HOST_WIDEST_INT gcov_type;
|
|||||||
|
|
||||||
/* Poison these, so they don't accidentally slip in. */
|
/* 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_write_string gcov_write_tag gcov_write_length
|
||||||
#pragma GCC poison gcov_read_string gcov_sync gcov_time
|
#pragma GCC poison gcov_read_string gcov_sync gcov_time gcov_magic
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -240,21 +239,21 @@ typedef HOST_WIDEST_INT gcov_type;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* File suffixes. */
|
/* File suffixes. */
|
||||||
#define GCOV_DATA_SUFFIX ".da"
|
#define GCOV_DATA_SUFFIX ".gcda"
|
||||||
#define GCOV_GRAPH_SUFFIX ".bbg"
|
#define GCOV_NOTE_SUFFIX ".gcno"
|
||||||
|
|
||||||
/* File magic. */
|
/* File magic. Must not be palindromes. */
|
||||||
#define GCOV_DATA_MAGIC 0x67636f76 /* "gcov" */
|
#define GCOV_DATA_MAGIC ((gcov_unsigned_t)0x67636461) /* "gcda" */
|
||||||
#define GCOV_GRAPH_MAGIC 0x67626267 /* "gbbg" */
|
#define GCOV_NOTE_MAGIC ((gcov_unsigned_t)0x67636e6f) /* "gcno" */
|
||||||
|
|
||||||
/* gcov-iov.h is automatically generated by the makefile from
|
/* gcov-iov.h is automatically generated by the makefile from
|
||||||
version.c, it looks like
|
version.c, it looks like
|
||||||
#define GCOV_VERSION ((unsigned)0x89abcdef)
|
#define GCOV_VERSION ((gcov_unsigned_t)0x89abcdef)
|
||||||
*/
|
*/
|
||||||
#include "gcov-iov.h"
|
#include "gcov-iov.h"
|
||||||
|
|
||||||
/* The record tags. Values [1..3f] are for tags which may be in either
|
/* The record tags. Values [1..3f] are for tags which may be in either
|
||||||
file. Values [41..9f] for those in the bbg file and [a1..ff] for
|
file. Values [41..9f] for those in the note file and [a1..ff] for
|
||||||
the data file. */
|
the data file. */
|
||||||
|
|
||||||
#define GCOV_TAG_FUNCTION ((gcov_unsigned_t)0x01000000)
|
#define GCOV_TAG_FUNCTION ((gcov_unsigned_t)0x01000000)
|
||||||
@ -374,7 +373,7 @@ struct gcov_ctr_info
|
|||||||
struct gcov_info
|
struct gcov_info
|
||||||
{
|
{
|
||||||
gcov_unsigned_t version; /* expected version number */
|
gcov_unsigned_t version; /* expected version number */
|
||||||
struct gcov_info *next; /* link to next, used by libgcc */
|
struct gcov_info *next; /* link to next, used by libgcov */
|
||||||
|
|
||||||
gcov_unsigned_t stamp; /* uniquifying time stamp */
|
gcov_unsigned_t stamp; /* uniquifying time stamp */
|
||||||
const char *filename; /* output file name */
|
const char *filename; /* output file name */
|
||||||
@ -398,11 +397,11 @@ extern void __gcov_flush (void);
|
|||||||
/* The merge function that just sums the counters. */
|
/* The merge function that just sums the counters. */
|
||||||
extern void __gcov_merge_add (gcov_type *, unsigned);
|
extern void __gcov_merge_add (gcov_type *, unsigned);
|
||||||
|
|
||||||
/* The merge function to choose the most often value. */
|
/* The merge function to choose the most common value. */
|
||||||
extern void __gcov_merge_single (gcov_type *, unsigned);
|
extern void __gcov_merge_single (gcov_type *, unsigned);
|
||||||
|
|
||||||
/* The merge function to choose the most often difference between consecutive
|
/* The merge function to choose the most common difference between
|
||||||
values. */
|
consecutive values. */
|
||||||
extern void __gcov_merge_delta (gcov_type *, unsigned);
|
extern void __gcov_merge_delta (gcov_type *, unsigned);
|
||||||
#endif /* IN_LIBGCOV */
|
#endif /* IN_LIBGCOV */
|
||||||
|
|
||||||
@ -425,24 +424,31 @@ GCOV_LINKAGE struct gcov_var
|
|||||||
fit within this buffer and we always can transfer GCOV_BLOCK_SIZE
|
fit within this buffer and we always can transfer GCOV_BLOCK_SIZE
|
||||||
to and from the disk. libgcov never backtracks and only writes 4
|
to and from the disk. libgcov never backtracks and only writes 4
|
||||||
or 8 byte objects. */
|
or 8 byte objects. */
|
||||||
unsigned char buffer[GCOV_BLOCK_SIZE + 4];
|
char buffer[GCOV_BLOCK_SIZE + 4] __attribute__ ((aligned (4)));
|
||||||
#else
|
#else
|
||||||
|
int endian; /* Swap endianness. */
|
||||||
/* Holds a variable length block, as the compiler can write
|
/* Holds a variable length block, as the compiler can write
|
||||||
strings and needs to backtrack. */
|
strings and needs to backtrack. */
|
||||||
size_t alloc;
|
size_t alloc;
|
||||||
unsigned char *buffer;
|
char *buffer;
|
||||||
#endif
|
#endif
|
||||||
} gcov_var;
|
} gcov_var;
|
||||||
|
|
||||||
/* Functions for reading and writing gcov files. You can open a file
|
/* Functions for reading and writing gcov files. In libgcov you can
|
||||||
for (1) reading or (2) writing or (3) reading then rewriting. When
|
open the file for reading then writing. Elsewhere you can open the
|
||||||
reading a file you may use the gcov_read_* functions, gcov_sync,
|
file either for reading or for writing. When reading a file you may
|
||||||
gcov_position, & gcov_error. When writing a file you
|
use the gcov_read_* functions, gcov_sync, gcov_position, &
|
||||||
may use the gcov_write functions, gcov_seek & gcov_error. When a
|
gcov_error. When writing a file you may use the gcov_write
|
||||||
file is to be rewritten you use the functions for reading, then
|
functions, gcov_seek & gcov_error. When a file is to be rewritten
|
||||||
gcov_rewrite then the functions for writing. Your file may become
|
you use the functions for reading, then gcov_rewrite then the
|
||||||
corrupted if you break these invariants. */
|
functions for writing. Your file may become corrupted if you break
|
||||||
GCOV_LINKAGE int gcov_open (const char */*name*/, int /*truncate*/);
|
these invariants. */
|
||||||
|
#if IN_LIBGCOV
|
||||||
|
GCOV_LINKAGE int gcov_open (const char */*name*/);
|
||||||
|
#else
|
||||||
|
GCOV_LINKAGE int gcov_open (const char */*name*/, int /*direction*/);
|
||||||
|
GCOV_LINKAGE int gcov_magic (gcov_unsigned_t, gcov_unsigned_t);
|
||||||
|
#endif
|
||||||
GCOV_LINKAGE int gcov_close (void);
|
GCOV_LINKAGE int gcov_close (void);
|
||||||
|
|
||||||
/* Available everywhere. */
|
/* Available everywhere. */
|
||||||
|
@ -61,7 +61,7 @@ main (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
|
|||||||
printf ("/* Generated automatically by the program `%s'\n", argv[0]);
|
printf ("/* Generated automatically by the program `%s'\n", argv[0]);
|
||||||
printf (" from `%s'. */\n", version_string);
|
printf (" from `%s'. */\n", version_string);
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
printf ("#define GCOV_VERSION ((unsigned)%#08x) /* %.4s */\n",
|
printf ("#define GCOV_VERSION ((gcov_unsigned_t)%#08x) /* %.4s */\n",
|
||||||
version, v);
|
version, v);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
27
gcc/gcov.c
27
gcc/gcov.c
@ -417,13 +417,10 @@ print_usage (int error_p)
|
|||||||
static void
|
static void
|
||||||
print_version (void)
|
print_version (void)
|
||||||
{
|
{
|
||||||
char v[4];
|
|
||||||
unsigned version = GCOV_VERSION;
|
unsigned version = GCOV_VERSION;
|
||||||
unsigned ix;
|
|
||||||
|
|
||||||
for (ix = 4; ix--; version >>= 8)
|
fnotice (stdout, "gcov %.4s (GCC %s)\n",
|
||||||
v[ix] = version;
|
(const char *)&version, version_string);
|
||||||
fnotice (stdout, "gcov %.4s (GCC %s)\n", v, version_string);
|
|
||||||
fnotice (stdout, "Copyright (C) 2002 Free Software Foundation, Inc.\n");
|
fnotice (stdout, "Copyright (C) 2002 Free Software Foundation, Inc.\n");
|
||||||
fnotice (stdout,
|
fnotice (stdout,
|
||||||
"This is free software; see the source for copying conditions. There is NO\n\
|
"This is free software; see the source for copying conditions. There is NO\n\
|
||||||
@ -660,10 +657,10 @@ create_file_names (const char *file_name)
|
|||||||
*cptr = 0;
|
*cptr = 0;
|
||||||
|
|
||||||
length = strlen (name);
|
length = strlen (name);
|
||||||
|
|
||||||
bbg_file_name = xmalloc (length + strlen (GCOV_GRAPH_SUFFIX) + 1);
|
bbg_file_name = xmalloc (length + strlen (GCOV_NOTE_SUFFIX) + 1);
|
||||||
strcpy (bbg_file_name, name);
|
strcpy (bbg_file_name, name);
|
||||||
strcpy (bbg_file_name + length, GCOV_GRAPH_SUFFIX);
|
strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX);
|
||||||
|
|
||||||
da_file_name = xmalloc (length + strlen (GCOV_DATA_SUFFIX) + 1);
|
da_file_name = xmalloc (length + strlen (GCOV_DATA_SUFFIX) + 1);
|
||||||
strcpy (da_file_name, name);
|
strcpy (da_file_name, name);
|
||||||
@ -715,7 +712,7 @@ read_graph_file (void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
bbg_file_time = gcov_time ();
|
bbg_file_time = gcov_time ();
|
||||||
if (gcov_read_unsigned () != GCOV_GRAPH_MAGIC)
|
if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC))
|
||||||
{
|
{
|
||||||
fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
|
fnotice (stderr, "%s:not a gcov graph file\n", bbg_file_name);
|
||||||
gcov_close ();
|
gcov_close ();
|
||||||
@ -984,7 +981,7 @@ read_count_file (void)
|
|||||||
fnotice (stderr, "%s:cannot open data file\n", da_file_name);
|
fnotice (stderr, "%s:cannot open data file\n", da_file_name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
|
if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
|
||||||
{
|
{
|
||||||
fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
|
fnotice (stderr, "%s:not a gcov data file\n", da_file_name);
|
||||||
cleanup:;
|
cleanup:;
|
||||||
@ -994,16 +991,10 @@ read_count_file (void)
|
|||||||
version = gcov_read_unsigned ();
|
version = gcov_read_unsigned ();
|
||||||
if (version != GCOV_VERSION)
|
if (version != GCOV_VERSION)
|
||||||
{
|
{
|
||||||
char v[4], e[4];
|
|
||||||
unsigned desired = GCOV_VERSION;
|
unsigned desired = GCOV_VERSION;
|
||||||
|
|
||||||
for (ix = 4; ix--; desired >>= 8, version >>= 8)
|
|
||||||
{
|
|
||||||
v[ix] = version;
|
|
||||||
e[ix] = desired;
|
|
||||||
}
|
|
||||||
fnotice (stderr, "%s:version `%.4s', prefer version `%.4s'\n",
|
fnotice (stderr, "%s:version `%.4s', prefer version `%.4s'\n",
|
||||||
da_file_name, v, e);
|
da_file_name, (const char *)&version, (const char *)&desired);
|
||||||
}
|
}
|
||||||
tag = gcov_read_unsigned ();
|
tag = gcov_read_unsigned ();
|
||||||
if (tag != bbg_stamp)
|
if (tag != bbg_stamp)
|
||||||
|
@ -91,22 +91,19 @@ static struct gcov_info *gcov_list;
|
|||||||
object file included in multiple programs. */
|
object file included in multiple programs. */
|
||||||
static gcov_unsigned_t gcov_crc32;
|
static gcov_unsigned_t gcov_crc32;
|
||||||
|
|
||||||
static void
|
static int
|
||||||
gcov_version_mismatch (struct gcov_info *ptr, gcov_unsigned_t version)
|
gcov_version (struct gcov_info *ptr, gcov_unsigned_t version)
|
||||||
{
|
{
|
||||||
gcov_unsigned_t expected = GCOV_VERSION;
|
gcov_unsigned_t expected = GCOV_VERSION;
|
||||||
unsigned ix;
|
|
||||||
char e[4], v[4];
|
|
||||||
|
|
||||||
for (ix = 4; ix--; expected >>= 8, version >>= 8)
|
if (version != GCOV_VERSION)
|
||||||
{
|
{
|
||||||
e[ix] = expected;
|
fprintf (stderr,
|
||||||
v[ix] = version;
|
"profiling:%s:Version mismatch - expected %.4s got %.4s\n",
|
||||||
|
ptr->filename, (const char *)&expected, (const char *)&version);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
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
|
/* Dump the coverage counts. We merge with existing counts when
|
||||||
@ -163,7 +160,6 @@ gcov_exit (void)
|
|||||||
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 = 0;
|
int error = 0;
|
||||||
int merging;
|
|
||||||
gcov_unsigned_t tag, length;
|
gcov_unsigned_t tag, length;
|
||||||
gcov_position_t summary_pos = 0;
|
gcov_position_t summary_pos = 0;
|
||||||
|
|
||||||
@ -200,18 +196,17 @@ gcov_exit (void)
|
|||||||
fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
|
fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open for modification, if possible */
|
if (!gcov_open (gi_ptr->filename))
|
||||||
merging = gcov_open (gi_ptr->filename, 0);
|
|
||||||
if (!merging)
|
|
||||||
{
|
{
|
||||||
fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
|
fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (merging > 0)
|
tag = gcov_read_unsigned ();
|
||||||
|
if (tag)
|
||||||
{
|
{
|
||||||
/* Merge data from file. */
|
/* Merge data from file. */
|
||||||
if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
|
if (tag != GCOV_DATA_MAGIC)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "profiling:%s:Not a gcov data file\n",
|
fprintf (stderr, "profiling:%s:Not a gcov data file\n",
|
||||||
gi_ptr->filename);
|
gi_ptr->filename);
|
||||||
@ -220,11 +215,8 @@ gcov_exit (void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
length = gcov_read_unsigned ();
|
length = gcov_read_unsigned ();
|
||||||
if (length != GCOV_VERSION)
|
if (!gcov_version (gi_ptr, length))
|
||||||
{
|
goto read_fatal;
|
||||||
gcov_version_mismatch (gi_ptr, length);
|
|
||||||
goto read_fatal;
|
|
||||||
}
|
|
||||||
|
|
||||||
length = gcov_read_unsigned ();
|
length = gcov_read_unsigned ();
|
||||||
if (length != gi_ptr->stamp)
|
if (length != gi_ptr->stamp)
|
||||||
@ -299,16 +291,17 @@ gcov_exit (void)
|
|||||||
goto rewrite;
|
goto rewrite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 ();
|
||||||
if (!summary_pos)
|
if (!summary_pos)
|
||||||
memset (&program, 0, sizeof (program));
|
memset (&program, 0, sizeof (program));
|
||||||
|
|
||||||
@ -414,9 +407,7 @@ __gcov_init (struct gcov_info *info)
|
|||||||
{
|
{
|
||||||
if (!info->version)
|
if (!info->version)
|
||||||
return;
|
return;
|
||||||
if (info->version != GCOV_VERSION)
|
if (gcov_version (info, info->version))
|
||||||
gcov_version_mismatch (info, info->version);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
const char *ptr = info->filename;
|
const char *ptr = info->filename;
|
||||||
gcov_unsigned_t crc32 = gcov_crc32;
|
gcov_unsigned_t crc32 = gcov_crc32;
|
||||||
|
Loading…
Reference in New Issue
Block a user