diff mbox series

gcov: Add -fprofile-info-section support

Message ID 20201113164740.4568-1-sebastian.huber@embedded-brains.de
State New
Headers show
Series gcov: Add -fprofile-info-section support | expand

Commit Message

Sebastian Huber Nov. 13, 2020, 4:47 p.m. UTC
Register the profile information in the specified section instead of using a
constructor/destructor.  A pointer to the profile information generated by
-fprofile-arcs or -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.

I am not sure how I can test this option.  One approach would be to assemble a
test file, then scan it and check that a .gcov_info section is present and no
__gcov_init() and __gcov_exit() calls are present.  Is there an example for
this in the test suite?

gcc/

	* gcc/common.opt (fprofile-info-section): New.
	* gcc/coverage.c (build_gcov_info_var_registration): New.
	(coverage_obj_init): Evaluate profile_info_section and use
	build_gcov_info_var_registration().
	* gcc/doc/invoke.texi (fprofile-info-section): Document.
	* gcc/opts.c (common_handle_option): Process fprofile-info-section
	option.
---
 gcc/common.opt      |  8 ++++++++
 gcc/coverage.c      | 28 ++++++++++++++++++++++++++--
 gcc/doc/invoke.texi | 29 +++++++++++++++++++++++++++++
 gcc/opts.c          |  4 ++++
 4 files changed, 67 insertions(+), 2 deletions(-)

Comments

Martin Liška Nov. 16, 2020, 10:26 a.m. UTC | #1
On 11/13/20 5:47 PM, Sebastian Huber wrote:

Hello.

Sorry for slow response.

> Register the profile information in the specified section instead of using a
> constructor/destructor.  A pointer to the profile information generated by
> -fprofile-arcs or -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.

The patch is fine.

> 
> I am not sure how I can test this option.  One approach would be to assemble a
> test file, then scan it and check that a .gcov_info section is present and no
> __gcov_init() and __gcov_exit() calls are present.  Is there an example for
> this in the test suite?

I'm going to add a test for it. I'm going to test your patch and will install
it after it finishes the tests.

Thanks for working on that. What will be your next steps in order to support
profiling of your embedded target? Something I can help with?

Martin
Sebastian Huber Nov. 16, 2020, 11:02 a.m. UTC | #2
Hello Martin,

On 16/11/2020 11:26, Martin Liška wrote:
>
> Sorry for slow response.
>
>> Register the profile information in the specified section instead of 
>> using a
>> constructor/destructor.  A pointer to the profile information 
>> generated by
>> -fprofile-arcs or -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.
>
> The patch is fine.
thanks for having a look at it.
>
>>
>> I am not sure how I can test this option.  One approach would be to 
>> assemble a
>> test file, then scan it and check that a .gcov_info section is 
>> present and no
>> __gcov_init() and __gcov_exit() calls are present.  Is there an 
>> example for
>> this in the test suite?
>
> I'm going to add a test for it. I'm going to test your patch and will 
> install
> it after it finishes the tests.
>
> Thanks for working on that. What will be your next steps in order to 
> support
> profiling of your embedded target? Something I can help with? 

I sent a proposal for a simple function to convert a gcov info to a gcda 
byte stream:

https://lists.rtems.org/mailman/listinfo

It could be used for something like this:

#include <gcov.h>
#include <stdio.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)
{
     printf("filename: %s\n", f);
}

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

     c = d;

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

static void dump_all(void)
{
     const struct gcov_info **info;
     const struct gcov_info **end;

     info = __gcov_info_start;
     end = __gcov_info_end;

     /* Obfuscate variable to prevent compiler optimizations */
     __asm__("" : "+r" (end));

     while (info != end) {
         __gcov_info_to_gcda(*info, filename, dump, NULL);
         putchar('\n');
         ++info;
     }
}

int main()
{
     dump_all();
     return 0;
}

In the linker command file you need these directives in a read-only 
memory area:

PROVIDE (__gcov_info_start = .);
KEEP (*(.gcov_info))
PROVIDE (__gcov_info_end = .);
Sebastian Huber Nov. 16, 2020, 11:07 a.m. UTC | #3
On 16/11/2020 12:02, Sebastian Huber wrote:

>
> I sent a proposal for a simple function to convert a gcov info to a 
> gcda byte stream:
>
> https://lists.rtems.org/mailman/listinfo

Sorry, wrong URL. This is the right one:

https://gcc.gnu.org/pipermail/gcc/2020-November/234213.html
Martin Liška Nov. 16, 2020, 11:54 a.m. UTC | #4
On 11/16/20 12:02 PM, Sebastian Huber wrote:
> Hello Martin,
> 
> On 16/11/2020 11:26, Martin Liška wrote:
>>
>> Sorry for slow response.
>>
>>> Register the profile information in the specified section instead of using a
>>> constructor/destructor.  A pointer to the profile information generated by
>>> -fprofile-arcs or -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.
>>
>> The patch is fine.
> thanks for having a look at it.

I've just pushed the commit/

>>
>>>
>>> I am not sure how I can test this option.  One approach would be to assemble a
>>> test file, then scan it and check that a .gcov_info section is present and no
>>> __gcov_init() and __gcov_exit() calls are present.  Is there an example for
>>> this in the test suite?
>>
>> I'm going to add a test for it. I'm going to test your patch and will install
>> it after it finishes the tests.
>>
>> Thanks for working on that. What will be your next steps in order to support
>> profiling of your embedded target? Something I can help with? 
> 
> I sent a proposal for a simple function to convert a gcov info to a gcda byte stream:
> 
> https://lists.rtems.org/mailman/listinfo
> 
> It could be used for something like this:
> 
> #include <gcov.h>
> #include <stdio.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)
> {
>      printf("filename: %s\n", f);
> }
> 
> static void
> dump(const void *d, unsigned n, void *arg)
> {
>      const unsigned char *c;
>      unsigned i;
> 
>      c = d;
> 
>      for (i = 0; i < n; ++i) {
>          printf("%02x", c[i]);
>      }
> }
> 
> static void dump_all(void)
> {
>      const struct gcov_info **info;
>      const struct gcov_info **end;
> 
>      info = __gcov_info_start;
>      end = __gcov_info_end;
> 
>      /* Obfuscate variable to prevent compiler optimizations */
>      __asm__("" : "+r" (end));
> 
>      while (info != end) {
>          __gcov_info_to_gcda(*info, filename, dump, NULL);
>          putchar('\n');
>          ++info;
>      }
> }
> 
> int main()
> {
>      dump_all();
>      return 0;
> }
> 
> In the linker command file you need these directives in a read-only memory area:
> 
> PROVIDE (__gcov_info_start = .);
> KEEP (*(.gcov_info))
> PROVIDE (__gcov_info_end = .);
> 

All right!

Martin
diff mbox series

Patch

diff --git a/gcc/common.opt b/gcc/common.opt
index 7d0e0d9c88a..114fe15e3c6 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -2268,6 +2268,14 @@  fprofile-generate=
 Common Joined RejectNegative
 Enable common options for generating profile info for profile feedback directed optimizations, and set -fprofile-dir=.
 
+fprofile-info-section
+Common RejectNegative
+Register the profile information in the .gcov_info section instead of using a constructor/destructor.
+
+fprofile-info-section=
+Common Joined RejectNegative Var(profile_info_section)
+Register the profile information in the specified section instead of using a constructor/destructor.
+
 fprofile-partial-training
 Common Report Var(flag_profile_partial_training) Optimization
 Do not assume that functions never executed during the train run are cold.
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 7711412c3be..d299e48d591 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -1097,6 +1097,25 @@  build_gcov_exit_decl (void)
   cgraph_build_static_cdtor ('D', dtor, priority);
 }
 
+/* Generate the pointer to the gcov_info_var in a dedicated section.  */
+
+static void
+build_gcov_info_var_registration (tree gcov_info_type)
+{
+  tree var = build_decl (BUILTINS_LOCATION,
+			 VAR_DECL, NULL_TREE,
+			 build_pointer_type (gcov_info_type));
+  TREE_STATIC (var) = 1;
+  TREE_READONLY (var) = 1;
+  char name_buf[32];
+  ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 2);
+  DECL_NAME (var) = get_identifier (name_buf);
+  get_section (profile_info_section, SECTION_UNNAMED, NULL);
+  set_decl_section_name (var, profile_info_section);
+  DECL_INITIAL (var) = build_fold_addr_expr (gcov_info_var);
+  varpool_node::finalize_decl (var);
+}
+
 /* Create the gcov_info types and object.  Generate the constructor
    function to call __gcov_init.  Does not generate the initializer
    for the object.  Returns TRUE if coverage data is being emitted.  */
@@ -1151,8 +1170,13 @@  coverage_obj_init (void)
   ASM_GENERATE_INTERNAL_LABEL (name_buf, "LPBX", 0);
   DECL_NAME (gcov_info_var) = get_identifier (name_buf);
 
-  build_init_ctor (gcov_info_type);
-  build_gcov_exit_decl ();
+  if (profile_info_section)
+    build_gcov_info_var_registration (gcov_info_type);
+  else
+    {
+      build_init_ctor (gcov_info_type);
+      build_gcov_exit_decl ();
+    }
 
   return true;
 }
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d01beb248e1..e78c3c23ad2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -564,6 +564,7 @@  Objective-C and Objective-C++ Dialects}.
 @gccoptlist{-p  -pg  -fprofile-arcs  --coverage  -ftest-coverage @gol
 -fprofile-abs-path @gol
 -fprofile-dir=@var{path}  -fprofile-generate  -fprofile-generate=@var{path} @gol
+-fprofile-info-section  -fprofile-info-section=@var{name} @gol
 -fprofile-note=@var{path} -fprofile-prefix-path=@var{path} @gol
 -fprofile-update=@var{method} -fprofile-filter-files=@var{regex} @gol
 -fprofile-exclude-files=@var{regex} @gol
@@ -14183,6 +14184,34 @@  the profile feedback data files. See @option{-fprofile-dir}.
 To optimize the program based on the collected profile information, use
 @option{-fprofile-use}.  @xref{Optimize Options}, for more information.
 
+@item -fprofile-info-section
+@itemx -fprofile-info-section=@var{name}
+@opindex fprofile-info-section
+
+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:
+
+@smallexample
+  .gcov_info      :
+  {
+    PROVIDE (__gcov_info_start = .);
+    KEEP (*(.gcov_info))
+    PROVIDE (__gcov_info_end = .);
+  }
+@end smallexample
+
 @item -fprofile-note=@var{path}
 @opindex fprofile-note
 
diff --git a/gcc/opts.c b/gcc/opts.c
index 96291e89a49..fd6e669471e 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -2602,6 +2602,10 @@  common_handle_option (struct gcc_options *opts,
       SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, value);
       break;
 
+    case OPT_fprofile_info_section:
+      opts->x_profile_info_section = ".gcov_info";
+      break;
+
     case OPT_fpatchable_function_entry_:
       {
 	char *patch_area_arg = xstrdup (arg);