Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-23 Thread Sebastian Huber

On 23/07/2021 09:16, Martin Liška wrote:

On 7/23/21 9:06 AM, Sebastian Huber wrote:

On 23/07/2021 08:52, Martin Liška wrote:

+#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.  */

+
+void
+__gcov_info_to_gcda (const struct gcov_info *gi_ptr,
+ void (*filename) (const char *, void *),


What about begin_finaname_fn?


+ void (*dump) (const void *, unsigned, void *),
+ void *(*allocate) (unsigned, void *),
+ void *arg)
+{
+  (*filename) (gi_ptr->filename, arg);
+  write_one_data (gi_ptr, NULL, dump, allocate, arg);
+}
+#endif /* NEED_L_GCOV_INFO_TO_GCDA */



About gcov_write_summary: it should be also dumped in order to have 
a complete .gcda file, right?


How can I get access to the summary information? Here it is not 
available:


You only need to change gcov_write_summary in gcov-io.c.


Sorry, I still don't know how I can get the summary information if I 
only have a pointer to the gcov_info structure which does not contain 
a summary member.


You're right, sorry! But in your case, it will be simple to re-created 
it by the script at a host system.



gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary 
*summary)

{
   gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH);
   gcov_write_unsigned (summary->runs);
   gcov_write_unsigned (summary->sum_max);
}

Where summary->runs will be 1 and sum_max is maximum counter during the 
run.


This __gcov_info_to_gcda() is just a low-level piece which is necessary 
to get the gcda stream from an embedded system to a host without having 
to know the details of gcov. In follow up patches we could think about a 
standard format to serialize the gcda stream.  For this format we could 
add support to the host gcov tools. One of the tools could read this 
stream and output proper *.gcda files.


--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.hu...@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax:   +49-89-18 94 741 - 08

Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/


Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-23 Thread Sebastian Huber




On 23/07/2021 11:17, Sebastian Huber wrote:

On 23/07/2021 08:52, Martin Liška wrote:



It would be nice having a test-case that can test your approach.


The problem is that you need the linker set to get access to the gcov 
information. The test program of the commit message works on my Linux 
machine. I am not sure if it is generic enough for the test suite. 
Instead of printing the information we could compare it against an 
expected output so that we have a self-contained test program.


Yep, that would be nice.


I tried to run the attached test case as 
"gcc/testsuite/gcc.dg/gcov-info-to-gcda.c". However, I get this error:


Invoking the compiler as /tmp/sh/b-gcc-git-linux/gcc/xgcc 
-B/tmp/sh/b-gcc-git-linux/gcc/ 
/home/EB/sebastian_h/src/gcc/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c 
  -fdiagnostics-plain-output   -fprofile-arcs -fprofile-info-section 
-lm  -o ./gcov-info-to-gcda.exe

Setting timeout to 300
Executing on host: /tmp/sh/b-gcc-git-linux/gcc/xgcc 
-B/tmp/sh/b-gcc-git-linux/gcc/ 
/home/EB/sebastian_h/src/gcc/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c 
  -fdiagnostics-plain-output   -fprofile-arcs -fprofile-info-section 
-lm  -o ./gcov-info-to-gcda.exe    (timeout = 300)
spawn -ignore SIGHUP /tmp/sh/b-gcc-git-linux/gcc/xgcc 
-B/tmp/sh/b-gcc-git-linux/gcc/ 
/home/EB/sebastian_h/src/gcc/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c 
-fdiagnostics-plain-output -fprofile-arcs -fprofile-info-section -lm -o 
./gcov-info-to-gcda.exe


pid is 79704 -79704
/home/EB/sebastian_h/src/gcc/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c:5:10: 
fatal error: gcov.h: No such file or directory


compilation terminated.


Is it possible to do such kind of tests? I also have to link to -lgcov?


Ok, the linking is not the problem. If I declare __gcov_info_to_gcda() 
locally, the test runs.


--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.hu...@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax:   +49-89-18 94 741 - 08

Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/


Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-23 Thread Sebastian Huber

On 23/07/2021 08:52, Martin Liška wrote:



It would be nice having a test-case that can test your approach.


The problem is that you need the linker set to get access to the gcov 
information. The test program of the commit message works on my Linux 
machine. I am not sure if it is generic enough for the test suite. 
Instead of printing the information we could compare it against an 
expected output so that we have a self-contained test program.


Yep, that would be nice.


I tried to run the attached test case as 
"gcc/testsuite/gcc.dg/gcov-info-to-gcda.c". However, I get this error:


Invoking the compiler as /tmp/sh/b-gcc-git-linux/gcc/xgcc 
-B/tmp/sh/b-gcc-git-linux/gcc/ 
/home/EB/sebastian_h/src/gcc/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c 
 -fdiagnostics-plain-output   -fprofile-arcs -fprofile-info-section 
-lm  -o ./gcov-info-to-gcda.exe

Setting timeout to 300
Executing on host: /tmp/sh/b-gcc-git-linux/gcc/xgcc 
-B/tmp/sh/b-gcc-git-linux/gcc/ 
/home/EB/sebastian_h/src/gcc/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c 
 -fdiagnostics-plain-output   -fprofile-arcs -fprofile-info-section 
-lm  -o ./gcov-info-to-gcda.exe(timeout = 300)
spawn -ignore SIGHUP /tmp/sh/b-gcc-git-linux/gcc/xgcc 
-B/tmp/sh/b-gcc-git-linux/gcc/ 
/home/EB/sebastian_h/src/gcc/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c 
-fdiagnostics-plain-output -fprofile-arcs -fprofile-info-section -lm -o 
./gcov-info-to-gcda.exe


pid is 79704 -79704
/home/EB/sebastian_h/src/gcc/gcc/testsuite/gcc.dg/gcov-info-to-gcda.c:5:10: 
fatal error: gcov.h: No such file or directory


compilation terminated.


Is it possible to do such kind of tests? I also have to link to -lgcov?

--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.hu...@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax:   +49-89-18 94 741 - 08

Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/
/* { dg-do run } */
/* { dg-skip-if "profile-info-section" { powerpc-ibm-aix* } } */
/* { dg-options "-fprofile-arcs -fprofile-info-section" } */

#include 

extern const struct gcov_info *my_info;

static unsigned counter;

static void
filename (const char *f, void *arg)
{
  if (arg != )
__builtin_abort ();

  if (__builtin_strcmp (f, __FILE__) != 0)
__builtin_abort ();
}

static void
dump (const void *d, unsigned n, void *arg)
{
  unsigned *m = (unsigned *)arg;
  if (m != )
__builtin_abort ();

  if (*m == 0)
  {
const unsigned *u = d;
if (*u != 0x67636461)
  __builtin_abort ();
  }

  *m += n;
}

static void *
allocate (unsigned length, void *arg)
{
  if (arg != )
__builtin_abort ();

  return __builtin_malloc (length);
}

int main()
{
  __asm__ volatile (".set my_info, .LPBX2");
  __gcov_info_to_gcda (my_info, filename, dump, allocate, );
  return 0;
}


Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-23 Thread Martin Liška

On 7/23/21 9:06 AM, Sebastian Huber wrote:

On 23/07/2021 08:52, Martin Liška wrote:

+#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.  */
+
+void
+__gcov_info_to_gcda (const struct gcov_info *gi_ptr,
+ void (*filename) (const char *, void *),


What about begin_finaname_fn?


+ void (*dump) (const void *, unsigned, void *),
+ void *(*allocate) (unsigned, void *),
+ void *arg)
+{
+  (*filename) (gi_ptr->filename, arg);
+  write_one_data (gi_ptr, NULL, dump, allocate, arg);
+}
+#endif /* NEED_L_GCOV_INFO_TO_GCDA */



About gcov_write_summary: it should be also dumped in order to have a complete 
.gcda file, right?


How can I get access to the summary information? Here it is not available:


You only need to change gcov_write_summary in gcov-io.c.


Sorry, I still don't know how I can get the summary information if I only have 
a pointer to the gcov_info structure which does not contain a summary member.


You're right, sorry! But in your case, it will be simple to re-created it by 
the script at a host system.


gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary)
{
  gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH);
  gcov_write_unsigned (summary->runs);
  gcov_write_unsigned (summary->sum_max);
}

Where summary->runs will be 1 and sum_max is maximum counter during the run.

Cheers,
Martin


Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-23 Thread Sebastian Huber

On 23/07/2021 08:52, Martin Liška wrote:

+#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.  */

+
+void
+__gcov_info_to_gcda (const struct gcov_info *gi_ptr,
+ void (*filename) (const char *, void *),


What about begin_finaname_fn?


+ void (*dump) (const void *, unsigned, void *),
+ void *(*allocate) (unsigned, void *),
+ void *arg)
+{
+  (*filename) (gi_ptr->filename, arg);
+  write_one_data (gi_ptr, NULL, dump, allocate, arg);
+}
+#endif /* NEED_L_GCOV_INFO_TO_GCDA */



About gcov_write_summary: it should be also dumped in order to have a 
complete .gcda file, right?


How can I get access to the summary information? Here it is not 
available:


You only need to change gcov_write_summary in gcov-io.c.


Sorry, I still don't know how I can get the summary information if I 
only have a pointer to the gcov_info structure which does not contain a 
summary member.


--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.hu...@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax:   +49-89-18 94 741 - 08

Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/


Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-23 Thread Martin Liška

On 7/23/21 8:21 AM, Sebastian Huber wrote:

On 23/07/2021 07:31, Martin Liška wrote:

+static void *
+allocate_handler (unsigned size, void *unused)
+{
+  (void)unused;
+  return xmalloc (size);
+}
+#endif /* NEED_L_GCOV */
+
+#if defined(NEED_L_GCOV) || defined(NEED_L_GCOV_INFO_TO_GCDA)
+static inline void


Likewise here.


+dump_unsigned (gcov_unsigned_t word,
+   void (*dump) (const void *, unsigned, void *),
+   void *arg)
+{
+  (*dump) (, sizeof (word), arg);
+}


Likewise here.


Adding the gcov_ prefix would make some lines longer than 79 characters. We 
already have several functions in this file without a gocv_ prefix, for example 
write_one_data(), write_topn_counters().



All right, I don't insist on that.

Cheers,
Martin


Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-23 Thread Martin Liška

On 7/23/21 8:14 AM, Sebastian Huber wrote:

On 23/07/2021 07:31, Martin Liška wrote:

  write_topn_counters (const struct gcov_ctr_info *ci_ptr,
   unsigned t_ix,
- gcov_unsigned_t n_counts)
+ gcov_unsigned_t n_counts,
+ void (*dump) (const void *, unsigned, void *),
+ void *(*allocate)(unsigned, void *),
+ void *arg)


I would likely prefer dump_fn and allocate_fn argumen t names.


If I use dump_fn and allocate_fn throughout the code, then several lines would 
exceed 79 characters.  This needs more vertical space. Should I still add the 
_fn postfix?



Yes, please do so.

Martin


Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-23 Thread Martin Liška

On 7/23/21 8:10 AM, Sebastian Huber wrote:

Hallo Martin,


Hello.



thanks for your review.

On 23/07/2021 07:31, Martin Liška wrote:

On 7/13/21 10:15 PM, Sebastian Huber wrote:

Hello.

Thanks for working on that, there's my review:


Add __gcov_info_to_gcda() to libgcov to get the gcda data for a gcda info in a
freestanding environment.  It is intended to be used with the
-fprofile-info-section option.  A crude test program which doesn't use a linker
script is (use "gcc -coverage -fprofile-info-section -lgcc test.c" to compile
it):

[...]>> @@ -365,46 +426,48 @@ write_topn_counters (const struct gcov_ctr_info

*ci_ptr,
    if (list_sizes == NULL || counters > list_size_length)
  {
    list_size_length = MAX (LIST_SIZE_MIN_LENGTH, 2 * counters);
-#if HAVE_SYS_MMAN_H
+#if !defined(inhibit_libc) && HAVE_SYS_MMAN_H
    list_sizes
  = (unsigned *)malloc_mmap (list_size_length * sizeof (unsigned));
  #endif
    /* Malloc fallback.  */
    if (list_sizes == NULL)
-    list_sizes = (unsigned *)xmalloc (list_size_length * sizeof (unsigned));
+    list_sizes =
+  (unsigned *)(*allocate) (list_size_length * sizeof (unsigned), arg);
  }
-  memset (list_sizes, 0, counters * sizeof (unsigned));


Are you sure we don't need this zeroing?


The list_sizes array is iterated two times using the same "counters" limit. In 
the first iteration ...




    unsigned pair_total = 0;
    for (unsigned i = 0; i < counters; i++)
  {
    gcov_type start = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 2];
+  unsigned sizes = 0;
+


... the sizes is initialized to zero here and ...


    for (struct gcov_kvp *node = (struct gcov_kvp *)(intptr_t)start;
 node != NULL; node = node->next)
-    {
-  ++pair_total;
-  ++list_sizes[i];
-    }
+    ++sizes;
+
+  pair_total += sizes;
+  list_sizes[i] = sizes;


... written to the array here.


Oh, good then!




  }
    unsigned disk_size = GCOV_TOPN_DISK_COUNTERS * counters + 2 * pair_total;
-  gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
- GCOV_TAG_COUNTER_LENGTH (disk_size));
+  dump_unsigned (GCOV_TAG_FOR_COUNTER (t_ix), dump, arg),
+  dump_unsigned (GCOV_TAG_COUNTER_LENGTH (disk_size), dump, arg);
    for (unsigned i = 0; i < counters; i++)
  {
-  gcov_write_counter (ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i]);
-  gcov_write_counter (list_sizes[i]);
+  dump_counter (ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i], dump, arg);
+  dump_counter (list_sizes[i], dump, arg);
    gcov_type start = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 2];
    unsigned j = 0;
    for (struct gcov_kvp *node = (struct gcov_kvp *)(intptr_t)start;
 j < list_sizes[i]; node = node->next, j++)
  {
-  gcov_write_counter (node->value);
-  gcov_write_counter (node->count);
+  dump_counter (node->value, dump, arg);
+  dump_counter (node->count, dump, arg);
  }
  }
  }

[...]

+#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.  */
+
+void
+__gcov_info_to_gcda (const struct gcov_info *gi_ptr,
+ void (*filename) (const char *, void *),


What about begin_finaname_fn?


+ void (*dump) (const void *, unsigned, void *),
+ void *(*allocate) (unsigned, void *),
+ void *arg)
+{
+  (*filename) (gi_ptr->filename, arg);
+  write_one_data (gi_ptr, NULL, dump, allocate, arg);
+}
+#endif /* NEED_L_GCOV_INFO_TO_GCDA */



About gcov_write_summary: it should be also dumped in order to have a complete 
.gcda file, right?


How can I get access to the summary information? Here it is not available:


You only need to change gcov_write_summary in gcov-io.c.



/* Information about a single object file.  */
struct gcov_info
{
[...]
#ifndef IN_GCOV_TOOL
   const struct gcov_fn_info *const *functions; /* pointer to pointers
   to function information  */
#else
   struct gcov_fn_info **functions;
   struct gcov_summary summary;
#endif /* !IN_GCOV_TOOL */
};

Should we dump a memset(, 0, summary) summary?


Can we remove gcov_write_counter function?


It is no longer used. What is the policy to remove functions?


We can remove it if it's unused :)




I think it can be handy having a script that creates a .gcda file from your 
reference dump output,
what do you think?


I think the dump output from the example is not useful for real applications. 
In an embedded system you would probably dump the information via a serial 
interface. The dump could be compressed and base64 encoded with some sort of 
EDAC.


Sure, but a host system needs to take such a stream and reconstruct .gcda 
files. That's what I mean. Btw. do you use the created .gcda files only for 
gcov (coverage reports), or
do you use it for -fprofile-use (PGO/FDO)? Btw. the generated .gcda files 
should 

Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-23 Thread Sebastian Huber

On 23/07/2021 07:31, Martin Liška wrote:

+static void *
+allocate_handler (unsigned size, void *unused)
+{
+  (void)unused;
+  return xmalloc (size);
+}
+#endif /* NEED_L_GCOV */
+
+#if defined(NEED_L_GCOV) || defined(NEED_L_GCOV_INFO_TO_GCDA)
+static inline void


Likewise here.


+dump_unsigned (gcov_unsigned_t word,
+   void (*dump) (const void *, unsigned, void *),
+   void *arg)
+{
+  (*dump) (, sizeof (word), arg);
+}


Likewise here.


Adding the gcov_ prefix would make some lines longer than 79 characters. 
We already have several functions in this file without a gocv_ prefix, 
for example write_one_data(), write_topn_counters().


--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.hu...@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax:   +49-89-18 94 741 - 08

Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/


Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-23 Thread Sebastian Huber

On 23/07/2021 07:31, Martin Liška wrote:

  write_topn_counters (const struct gcov_ctr_info *ci_ptr,
   unsigned t_ix,
- gcov_unsigned_t n_counts)
+ gcov_unsigned_t n_counts,
+ void (*dump) (const void *, unsigned, void *),
+ void *(*allocate)(unsigned, void *),
+ void *arg)


I would likely prefer dump_fn and allocate_fn argumen t names.


If I use dump_fn and allocate_fn throughout the code, then several lines 
would exceed 79 characters.  This needs more vertical space. Should I 
still add the _fn postfix?


--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.hu...@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax:   +49-89-18 94 741 - 08

Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/


Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-23 Thread Sebastian Huber

Hallo Martin,

thanks for your review.

On 23/07/2021 07:31, Martin Liška wrote:

On 7/13/21 10:15 PM, Sebastian Huber wrote:

Hello.

Thanks for working on that, there's my review:

Add __gcov_info_to_gcda() to libgcov to get the gcda data for a gcda 
info in a

freestanding environment.  It is intended to be used with the
-fprofile-info-section option.  A crude test program which doesn't use 
a linker
script is (use "gcc -coverage -fprofile-info-section -lgcc test.c" to 
compile

it):
[...]>> @@ -365,46 +426,48 @@ write_topn_counters (const struct 
gcov_ctr_info

*ci_ptr,
    if (list_sizes == NULL || counters > list_size_length)
  {
    list_size_length = MAX (LIST_SIZE_MIN_LENGTH, 2 * counters);
-#if HAVE_SYS_MMAN_H
+#if !defined(inhibit_libc) && HAVE_SYS_MMAN_H
    list_sizes
  = (unsigned *)malloc_mmap (list_size_length * sizeof (unsigned));
  #endif
    /* Malloc fallback.  */
    if (list_sizes == NULL)
-    list_sizes = (unsigned *)xmalloc (list_size_length * sizeof 
(unsigned));

+    list_sizes =
+  (unsigned *)(*allocate) (list_size_length * sizeof (unsigned), 
arg);

  }
-  memset (list_sizes, 0, counters * sizeof (unsigned));


Are you sure we don't need this zeroing?


The list_sizes array is iterated two times using the same "counters" 
limit. In the first iteration ...





    unsigned pair_total = 0;
    for (unsigned i = 0; i < counters; i++)
  {
    gcov_type start = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 2];
+  unsigned sizes = 0;
+


... the sizes is initialized to zero here and ...


    for (struct gcov_kvp *node = (struct gcov_kvp *)(intptr_t)start;
 node != NULL; node = node->next)
-    {
-  ++pair_total;
-  ++list_sizes[i];
-    }
+    ++sizes;
+
+  pair_total += sizes;
+  list_sizes[i] = sizes;


... written to the array here.


  }
    unsigned disk_size = GCOV_TOPN_DISK_COUNTERS * counters + 2 * 
pair_total;

-  gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
- GCOV_TAG_COUNTER_LENGTH (disk_size));
+  dump_unsigned (GCOV_TAG_FOR_COUNTER (t_ix), dump, arg),
+  dump_unsigned (GCOV_TAG_COUNTER_LENGTH (disk_size), dump, arg);
    for (unsigned i = 0; i < counters; i++)
  {
-  gcov_write_counter (ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i]);
-  gcov_write_counter (list_sizes[i]);
+  dump_counter (ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i], dump, 
arg);

+  dump_counter (list_sizes[i], dump, arg);
    gcov_type start = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 2];
    unsigned j = 0;
    for (struct gcov_kvp *node = (struct gcov_kvp *)(intptr_t)start;
 j < list_sizes[i]; node = node->next, j++)
  {
-  gcov_write_counter (node->value);
-  gcov_write_counter (node->count);
+  dump_counter (node->value, dump, arg);
+  dump_counter (node->count, dump, arg);
  }
  }
  }

[...]

+#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.  */

+
+void
+__gcov_info_to_gcda (const struct gcov_info *gi_ptr,
+ void (*filename) (const char *, void *),


What about begin_finaname_fn?


+ void (*dump) (const void *, unsigned, void *),
+ void *(*allocate) (unsigned, void *),
+ void *arg)
+{
+  (*filename) (gi_ptr->filename, arg);
+  write_one_data (gi_ptr, NULL, dump, allocate, arg);
+}
+#endif /* NEED_L_GCOV_INFO_TO_GCDA */



About gcov_write_summary: it should be also dumped in order to have a 
complete .gcda file, right?


How can I get access to the summary information? Here it is not available:

/* Information about a single object file.  */
struct gcov_info
{
[...]
#ifndef IN_GCOV_TOOL
  const struct gcov_fn_info *const *functions; /* pointer to pointers
  to function 
information  */

#else
  struct gcov_fn_info **functions;
  struct gcov_summary summary;
#endif /* !IN_GCOV_TOOL */
};

Should we dump a memset(, 0, summary) summary?


Can we remove gcov_write_counter function?


It is no longer used. What is the policy to remove functions?

I think it can be handy having a script that creates a .gcda file from 
your reference dump output,

what do you think?


I think the dump output from the example is not useful for real 
applications. In an embedded system you would probably dump the 
information via a serial interface. The dump could be compressed and 
base64 encoded with some sort of EDAC.



It would be nice having a test-case that can test your approach.


The problem is that you need the linker set to get access to the gcov 
information. The test program of the commit message works on my Linux 
machine. I am not sure if it is generic enough for the test suite. 
Instead of printing the information we could compare it against an 
expected output so that we have a self-contained test program.


--
embedded 

Re: [PATCH v2] gcov: Add __gcov_info_to_gdca()

2021-07-22 Thread Martin Liška

On 7/13/21 10:15 PM, Sebastian Huber wrote:

Hello.

Thanks for working on that, there's my review:


Add __gcov_info_to_gcda() to libgcov to get the gcda data for a gcda info in a
freestanding environment.  It is intended to be used with the
-fprofile-info-section option.  A crude test program which doesn't use a linker
script is (use "gcc -coverage -fprofile-info-section -lgcc test.c" to compile
it):

   #include 
   #include 
   #include 

   extern const struct gcov_info *my_info;

   static void
   filename (const char *f, void *arg)
   {
 printf("filename: %s\n", f);
   }

   static void
   dump (const void *d, unsigned n, void *arg)
   {
 const unsigned char *c = d;

 for (unsigned i = 0; i < n; ++i)
   printf ("%02x", c[i]);
   }

   static void *
   allocate (unsigned length, void *arg)
   {
 return malloc (length);
   }

   int main()
   {
 __asm__ volatile (".set my_info, .LPBX2");
 __gcov_info_to_gcda (my_info, filename, dump, allocate, NULL);
 return 0;
   }

With this patch,  is included in libgcov-driver.c even if
inhibit_libc is defined.  This header file should be also available for
freestanding environments.  If this is not the case, then we have to define
intptr_t somehow.

The patch removes one use of memset() which makes the  include
superfluous.

gcc/

* gcc/gcov-io.h (gcov_write): Declare.
* gcc/gcov-io.c (gcov_write): New.
* doc/invoke.texi (fprofile-info-section): Mention
__gcov_info_to_gdca().

libgcc/

Makefile.in (LIBGCOV_DRIVER): Add _gcov_info_to_gcda.
gcov.h (gcov_info): Declare.
(__gcov_info_to_gdca): Likewise.
libgcov-driver.c (#include ): New.
(#include ): Remove.
(NEED_L_GCOV): Conditionally define.
(NEED_L_GCOV_INFO_TO_GCDA): Likewise.
(are_all_counters_zero): New.
(dump_handler): Likewise.
(allocate_handler): Likewise.
(dump_unsigned): Likewise.
(dump_counter): Likewise.
(write_topn_counters): Add dump, allocate, and arg parameters.  Use
dump_unsigned() and dump_counter().
(write_one_data): Add dump, allocate, and arg parameters.  Use
dump_unsigned(), dump_counter(), and are_all_counters_zero().
(__gcov_info_to_gcda): New.
---
  gcc/doc/invoke.texi |  80 +++---
  gcc/gcov-io.c   |  10 +++
  gcc/gcov-io.h   |   1 +
  libgcc/Makefile.in  |   2 +-
  libgcc/gcov.h   |  17 
  libgcc/libgcov-driver.c | 176 ++--
  6 files changed, 230 insertions(+), 56 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e67d47af676d..2c514acf2003 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -14782,17 +14782,17 @@ To optimize the program based on the collected 
profile information, use
  Register the profile information in the specified section instead of using a
  constructor/destructor.  The section name is @var{name} if it is specified,
  otherwise the section name defaults to @code{.gcov_info}.  A pointer to the
-profile information generated by @option{-fprofile-arcs} or
-@option{-ftest-coverage} 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 systems with limited resources
-which do not support constructors and destructors.  The linker could collect
-the input sections in a continuous memory block and define start and end
-symbols.  The runtime support could dump the profiling information registered
-in this linker set during program termination to a serial line for example.  A
-GNU linker script example which defines a linker output section follows:
+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
+environments (for example embedded systems) with limited resources which do not
+support constructors/destructors or the C library file I/O.
+
+The linker could collect the input sections in a continuous memory block and
+define start and end symbols.  A GNU linker script example which defines a
+linker output section follows:
  
  @smallexample

.gcov_info  :
@@ -14803,6 +14803,64 @@ GNU linker script example which defines a linker 
output section follows:
@}
  @end smallexample
  
+The program could dump the profiling information registered in this linker set

+for example like this:
+
+@smallexample
+#include 
+#include 
+#include 
+
+extern const struct gcov_info