gcov: Add __gcov_filename_to_gcfn()

gcc/

	* doc/invoke.texi (fprofile-info-section): Mention
	__gcov_filename_to_gcfn().  Use "freestanding" to match with C11
	standard language.  Fix minor example code issues.
	* gcov-io.h (GCOV_FILENAME_MAGIC): Define and document.

gcc/testsuite/

	* gcc.dg/gcov-info-to-gcda.c: Test __gcov_filename_to_gcfn().

libgcc/

	* gcov.h (__gcov_info_to_gcda): Mention __gcov_filename_to_gcfn().
	(__gcov_filename_to_gcfn): Declare and document.
	* libgcov-driver.c (dump_string): New.
	(__gcov_filename_to_gcfn): Likewise.
	(__gcov_info_to_gcda): Adjust comment to match C11 standard language.
This commit is contained in:
Sebastian Huber 2022-03-30 21:45:23 +02:00
parent 68a4673fe2
commit 39d80300b3
5 changed files with 105 additions and 30 deletions

View File

@ -15462,7 +15462,7 @@ profile information generated by @option{-fprofile-arcs} is placed in the
specified section for each translation unit. This option disables the profile
information registration through a constructor and it disables the profile
information processing through a destructor. This option is not intended to be
used in hosted environments such as GNU/Linux. It targets free-standing
used in hosted environments such as GNU/Linux. It targets freestanding
environments (for example embedded systems) with limited resources which do not
support constructors/destructors or the C library file I/O.
@ -15487,14 +15487,8 @@ for example like this:
#include <stdio.h>
#include <stdlib.h>
extern const struct gcov_info *__gcov_info_start[];
extern const struct gcov_info *__gcov_info_end[];
static void
filename (const char *f, void *arg)
@{
puts (f);
@}
extern const struct gcov_info *const __gcov_info_start[];
extern const struct gcov_info *const __gcov_info_end[];
static void
dump (const void *d, unsigned n, void *arg)
@ -15505,6 +15499,12 @@ dump (const void *d, unsigned n, void *arg)
printf ("%02x", c[i]);
@}
static void
filename (const char *f, void *arg)
@{
__gcov_filename_to_gcfn (f, dump, arg );
@}
static void *
allocate (unsigned length, void *arg)
@{
@ -15514,8 +15514,8 @@ allocate (unsigned length, void *arg)
static void
dump_gcov_info (void)
@{
const struct gcov_info **info = __gcov_info_start;
const struct gcov_info **end = __gcov_info_end;
const struct gcov_info *const *info = __gcov_info_start;
const struct gcov_info *const *end = __gcov_info_end;
/* Obfuscate variable to prevent compiler optimizations. */
__asm__ ("" : "+r" (info));
@ -15530,9 +15530,9 @@ dump_gcov_info (void)
@}
int
main()
main (void)
@{
dump_gcov_info();
dump_gcov_info ();
return 0;
@}
@end smallexample

View File

@ -60,14 +60,21 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
file : int32:magic int32:version int32:stamp record*
The magic ident is different for the notes and the data files. The
magic ident is used to determine the endianness of the file, when
reading. The version is the same for both files and is derived
from gcc's version number. The stamp value is used to synchronize
note and data files and to synchronize merging within a data
file. It need not be an absolute time stamp, merely a ticker that
increments fast enough and cycles slow enough to distinguish
different compile/run/compile cycles.
A filename header may be used to provide a filename for the data in
a stream of data to support gcov in freestanding environments. This
header is used by the merge-stream subcommand of the gcov-tool. The
format of the filename header is
filename-header : int32:magic int32:version string
The magic ident is different for the notes and the data files as
well as the filename header. The magic ident is used to determine
the endianness of the file, when reading. The version is the same
for both files and is derived from gcc's version number. The stamp
value is used to synchronize note and data files and to synchronize
merging within a data file. It need not be an absolute time stamp,
merely a ticker that increments fast enough and cycles slow enough
to distinguish different compile/run/compile cycles.
Although the ident and version are formally 32 bit numbers, they
are derived from 4 character ASCII strings. The version number
@ -228,6 +235,7 @@ typedef uint64_t gcov_type_unsigned;
/* File magic. Must not be palindromes. */
#define GCOV_DATA_MAGIC ((gcov_unsigned_t)0x67636461) /* "gcda" */
#define GCOV_NOTE_MAGIC ((gcov_unsigned_t)0x67636e6f) /* "gcno" */
#define GCOV_FILENAME_MAGIC ((gcov_unsigned_t)0x6763666e) /* "gcfn" */
#include "version.h"

View File

@ -17,16 +17,20 @@ __gcov_info_to_gcda (const struct gcov_info *__info,
void *(*__allocate_fn) (unsigned, void *),
void *__arg);
extern void
__gcov_filename_to_gcfn (const char *__filename,
void (*__dump_fn) (const void *, unsigned, void *),
void *__arg);
extern const struct gcov_info *my_info;
static unsigned counter;
static void
filename (const char *f, void *arg)
{
assert (arg == &counter);
assert (__builtin_strstr (f, "gcov-info-to-gcda.c") == 0);
}
static unsigned counter_after_filename;
static int check_zero;
static int check_after_filename;
static void
dump (const void *d, unsigned n, void *arg)
@ -35,14 +39,30 @@ dump (const void *d, unsigned n, void *arg)
assert (arg == &counter);
if (*m == 0)
{
const unsigned *u = d;
assert (*u == 0x6763666e);
check_zero = 1;
}
else if (*m == counter_after_filename)
{
const unsigned *u = d;
assert (*u == 0x67636461);
check_after_filename = 1;
}
*m += n;
}
static void
filename (const char *f, void *arg)
{
assert (arg == &counter);
assert (__builtin_strstr (f, "gcov-info-to-gcda.c") == 0);
__gcov_filename_to_gcfn (f, dump, arg);
counter_after_filename = counter;
}
static void *
allocate (unsigned length, void *arg)
{
@ -54,6 +74,8 @@ int main()
{
__asm__ volatile (".set my_info, .LPBX2");
__gcov_info_to_gcda (my_info, filename, dump, allocate, &counter);
assert (counter > 4);
assert (counter > 8);
assert (check_zero);
assert (check_after_filename);
return 0;
}

View File

@ -43,7 +43,8 @@ extern void __gcov_dump (void);
stream. The ALLOCATE_FN callback shall allocate memory with a size in
characters specified by the first callback parameter. The ARG parameter is
a user-provided argument passed as the last argument to the callback
functions. */
functions. It is recommended to use the __gcov_filename_to_gcfn()
in the filename callback function. */
extern void
__gcov_info_to_gcda (const struct gcov_info *__info,
@ -52,4 +53,18 @@ __gcov_info_to_gcda (const struct gcov_info *__info,
void *(*__allocate_fn) (unsigned, void *),
void *__arg);
/* Convert the FILENAME to a gcfn data stream. The DUMP_FN callback is
subsequently called with chunks (the begin and length of the chunk are
passed as the first two callback parameters) of the gcfn data stream.
The ARG parameter is a user-provided argument passed as the last
argument to the DUMP_FN callback function. This function is intended
to be used by the filename callback of __gcov_info_to_gcda(). The gcfn
data stream is used by the merge-stream subcommand of the gcov-tool to
get the filename associated with a gcda data stream. */
extern void
__gcov_filename_to_gcfn (const char *__filename,
void (*__dump_fn) (const void *, unsigned, void *),
void *__arg);
#endif /* GCC_GCOV_H */

View File

@ -410,6 +410,23 @@ dump_counter (gcov_type counter,
dump_unsigned (0, dump_fn, arg);
}
/* Dump the STRING using the DUMP handler called with ARG. */
static inline void
dump_string (const char *string,
void (*dump_fn) (const void *, unsigned, void *),
void *arg)
{
unsigned length = 0;
if (string)
length = strlen (string) + 1;
dump_unsigned (length, dump_fn, arg);
if (string)
(*dump_fn) (string, length, arg);
}
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
/* Store all TOP N counters where each has a dynamic length. */
@ -768,7 +785,7 @@ __gcov_init (struct gcov_info *info)
#ifdef NEED_L_GCOV_INFO_TO_GCDA
/* Convert the gcov info to a gcda data stream. It is intended for
free-standing environments which do not support the C library file I/O. */
freestanding environments which do not support the C library file I/O. */
void
__gcov_info_to_gcda (const struct gcov_info *gi_ptr,
@ -780,4 +797,17 @@ __gcov_info_to_gcda (const struct gcov_info *gi_ptr,
(*filename_fn) (gi_ptr->filename, arg);
write_one_data (gi_ptr, NULL, dump_fn, allocate_fn, arg);
}
/* Convert the filename to a gcfn data stream. It is intended for
freestanding environments which do not support the C library file I/O. */
void
__gcov_filename_to_gcfn (const char *filename,
void (*dump_fn) (const void *, unsigned, void *),
void *arg)
{
dump_unsigned (GCOV_FILENAME_MAGIC, dump_fn, arg);
dump_unsigned (GCOV_VERSION, dump_fn, arg);
dump_string (filename, dump_fn, arg);
}
#endif /* NEED_L_GCOV_INFO_TO_GCDA */