* Re: GCC's instrumentation and the target environment @ 2019-11-20 15:22 David Taylor 2019-11-21 12:43 ` Martin Liška 0 siblings, 1 reply; 8+ messages in thread From: David Taylor @ 2019-11-20 15:22 UTC (permalink / raw) To: Martin Liška; +Cc: gcc, dtaylor Sorry for not responding sooner. Thanks Martin. Like Joel we have a third party solution to instrumentation. Part of my objection to the third party solution is freedom. There are customizations we would like, but not having source we're at the mercy of the vendor both for whether it gets done and the timing. Part of the objection is the massive amount of changes I had to make to our build system to integrate it and the resulting feeling of fragility. They are reportedly addressing the latter in a future release. By contrast, looking at GCC based instrumentation, the changes required to our build system are very small and easy. Part of my purpose in posting was the belief that this problem -- wanting to instrument embedded code -- is not uncommon and has likely been solved already. And the hope that one of the solvers would feel that their existing solution was in a good enough shape to contribute back. Or that someone would point out that there is already an existing {Free | Open} source solution that I am overlooking. Since no one has mentioned an existing solution, here is a first draft of a proposed solution to GCC instrumentation not playing well with embedded... NOTE: *NONE* of the following has been implemented as yet. I would ulimately like this to be something that once implemented would be considered for becoming part of standard GCC. So, if you see something that would impede that goal or if changed would improve its chances, please speak up. Add a new configure options --{with|without}-libgcov-standalone-env Default: without (i.e., hosted) Question: should hosted libgcov be the default for all configuration tuples? Or should it only be the default when there are headers? Or...? When standalone, when building libgcov.a files, suppress -Dinhibit_libc and add -DLIBGCOV_STANDALONE_ENV to the command line switches. Then in libgcov-driver.c, libgcov-driver-system.c, gcov-io.c, replace all calls of fopen with calls of __gcov_open_int fread __gcov_read_int fwrite __gcov_write_int fclose __gcov_close_int fseek __gcov_seek_int ftell __gcov_tell_int setbuf __gcov_setbuf_int Probably belongs inside __gcov_open_int instead of as a separate routine. getenv __gcov_getenv_int abort __gcov_abort_int When the application is 'the kernel' or 'the system', abort isn't really an option. fprintf __gcov_fprintf_int This is called in two places -- gcov_error and gcov_exit_open_gcda_file. The latter hard codes the stream as stderr; the former calls get_gcov_error_file to get the stream (which defaults to stderr but can be overridded via an environment variable). I think that get_gcov_error_file should be renamed to __gcov_get_error_file, be made non-static, and be called by gcov_exit_open_gcda_file instead of hard coding stderr. For that matter, I feel that gcov_exit_open_gcda_file should just call __gcov_error instead of doing it's own error reporting. And __gcov_get_error_file and __gcov_error should be a replacable routines as embedded systems might well have a different way of reporting errors. vfprintf __gcov_vfprintf_int If gcov_open_gcda_file is altered to call __gcov_error and __gcov_error becomes a replacable routine, then fprintf and vfprintf do not need to be wrapped. malloc __gcov_malloc_int free __gcov_free_int Embedded applications often do memory allocation differently. While I think that the above list is complete, I wouldn't be surprised if I missed one or two. Other than __gcov_open_int, there would be no conflict if the _int was left off the end. I put it on to emphasize that these routines were not meant to be called by the user, but rather are provided by the user. Some other naming convention might be better. There would be a new header file, included as appropriate. If the normal (hosted) build was in effect, then some new (potentially one line static inline) functions would be defined for each of the above functions that just call the expected standard libc function. If the embedded (standalone) build was in effect, then there would be extern declarations for each of the above, but *NO* definition -- the definition would be the reposibility of the application. Comments? David ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: GCC's instrumentation and the target environment 2019-11-20 15:22 GCC's instrumentation and the target environment David Taylor @ 2019-11-21 12:43 ` Martin Liška 0 siblings, 0 replies; 8+ messages in thread From: Martin Liška @ 2019-11-21 12:43 UTC (permalink / raw) To: David Taylor; +Cc: gcc On 11/20/19 4:14 PM, David Taylor wrote: > Sorry for not responding sooner. > > Thanks Martin. > > Like Joel we have a third party solution to instrumentation. Part of > my objection to the third party solution is freedom. There are > customizations we would like, but not having source we're at the mercy > of the vendor both for whether it gets done and the timing. Part of > the objection is the massive amount of changes I had to make to our > build system to integrate it and the resulting feeling of fragility. > They are reportedly addressing the latter in a future release. > > By contrast, looking at GCC based instrumentation, the changes > required to our build system are very small and easy. Hello. That sounds promising to me! > > Part of my purpose in posting was the belief that this problem -- > wanting to instrument embedded code -- is not uncommon and has likely > been solved already. And the hope that one of the solvers would feel > that their existing solution was in a good enough shape to contribute > back. Or that someone would point out that there is already an > existing {Free | Open} source solution that I am overlooking. Well, one quite similar usage will be usage of gcov in linux kernel, please take a look at kernel/gcov subfolder. > > Since no one has mentioned an existing solution, here is a first draft > of a proposed solution to GCC instrumentation not playing well with > embedded... > > NOTE: *NONE* of the following has been implemented as yet. I would > ulimately like this to be something that once implemented would be > considered for becoming part of standard GCC. So, if you see something > that would impede that goal or if changed would improve its chances, > please speak up. > > Add a new configure options --{with|without}-libgcov-standalone-env > > Default: without (i.e., hosted) > > Question: should hosted libgcov be the default for all configuration > tuples? Or should it only be the default when there are headers? > Or...? That's a detail, so let's say we'll have an option that will come up with a wrappers (__gcov_ # fn). > > When standalone, when building libgcov.a files, suppress > -Dinhibit_libc and add -DLIBGCOV_STANDALONE_ENV to the command line > switches. > > Then in libgcov-driver.c, libgcov-driver-system.c, gcov-io.c, replace > > all calls of fopen with calls of __gcov_open_int > fread __gcov_read_int > fwrite __gcov_write_int > fclose __gcov_close_int > fseek __gcov_seek_int > ftell __gcov_tell_int > > setbuf __gcov_setbuf_int > > Probably belongs inside __gcov_open_int instead of as > a separate routine. > > getenv __gcov_getenv_int > > abort __gcov_abort_int > > When the application is 'the kernel' or 'the system', > abort isn't really an option. > > fprintf __gcov_fprintf_int > > This is called in two places -- gcov_error and > gcov_exit_open_gcda_file. The latter hard codes the > stream as stderr; the former calls get_gcov_error_file > to get the stream (which defaults to stderr but can be > overridded via an environment variable). > > I think that get_gcov_error_file should be renamed to > __gcov_get_error_file, be made non-static, and be > called by gcov_exit_open_gcda_file instead of hard > coding stderr. > > For that matter, I feel that gcov_exit_open_gcda_file > should just call __gcov_error instead of doing it's > own error reporting. And __gcov_get_error_file and > __gcov_error should be a replacable routines as > embedded systems might well have a different way of > reporting errors. > > vfprintf __gcov_vfprintf_int > > If gcov_open_gcda_file is altered to call > __gcov_error and __gcov_error becomes a replacable > routine, then fprintf and vfprintf do not need to be > wrapped. > > malloc __gcov_malloc_int > free __gcov_free_int > > Embedded applications often do memory allocation > differently. > > While I think that the above list is complete, I wouldn't be surprised > if I missed one or two. That seams reasonable to me and can be easily achieved by a macro that will either expand to __gcov # fn _ int, or to fn. I can imagine that. > > Other than __gcov_open_int, there would be no conflict if the _int was > left off the end. I put it on to emphasize that these routines were > not meant to be called by the user, but rather are provided by the > user. Some other naming convention might be better. > > There would be a new header file, included as appropriate. If the > normal (hosted) build was in effect, then some new (potentially one > line static inline) functions would be defined for each of the above > functions that just call the expected standard libc function. If the > embedded (standalone) build was in effect, then there would be extern > declarations for each of the above, but *NO* definition -- the > definition would be the reposibility of the application. As mentioned, a macro expansion can do that. And the last missing step, which you will use, will be linking with additional library that will implement all the __gcov_fn_int functions. The suggested approach will need only quite minimal changes to the current libgcov. Martin > > Comments? > > David > ^ permalink raw reply [flat|nested] 8+ messages in thread
* GCC's instrumentation and the target environment @ 2019-11-01 18:18 David Taylor 2019-11-04 9:19 ` Martin Liška 2020-11-14 13:04 ` Sebastian Huber 0 siblings, 2 replies; 8+ messages in thread From: David Taylor @ 2019-11-01 18:18 UTC (permalink / raw) To: gcc; +Cc: dtaylor I wish to use GCC based instrumentation on an embedded target. And I am finding that GCC's libgcov.a is not well suited to my needs. Ideally, all the application entry points and everthing that knows about the internals of the implementation would be in separate files from everything that does i/o or otherwise uses 'system services'. Right now GCC has libgcov-driver.c which includes both gcov-io.c and libgcov-driver-system.c. What I'd like is a stable API between the routines that 'collect' the data and the routines that do the i/o. With the i/o routines being non-static and in a separate file from the others that is not #include'd. I want them to be replaceable by the application. Depending upon circumstances I can imagine the routines doing network i/o, disk i/o, or using a serial port. I want one version of libgcov.a for all three with three different sets of i/o routines that I can build into the application. If the internals of instrumentation changes, I want to not have to change the i/o routines or anything in the application. If you think of it in disk driver terms, some of the routines in libgcov.a provide a DDI -- an interface of routines that the application call call. For applications that exit, one of the routines is called at program exit. For long running applications, there are routines in the DDI to dump and flush the accumulated information. And the i/o routines can be thought of as providing a DKI -- what the library libgcov.a expects of the environment -- for example, fopen and fwrite. There's also the inhibit_libc define. While if you don't have headers you might have a hard time including <stdio.h> or some of the other header files, if the environment has a way of doing i/o or saving the results, there is no real reason why it should not be possible to provide instrumentation. Comments? ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: GCC's instrumentation and the target environment 2019-11-01 18:18 David Taylor @ 2019-11-04 9:19 ` Martin Liška 2019-11-04 13:06 ` David.Taylor 2020-11-14 13:04 ` Sebastian Huber 1 sibling, 1 reply; 8+ messages in thread From: Martin Liška @ 2019-11-04 9:19 UTC (permalink / raw) To: David Taylor, gcc On 11/1/19 7:13 PM, David Taylor wrote: > I wish to use GCC based instrumentation on an embedded target. And I > am finding that GCC's libgcov.a is not well suited to my needs. > > Ideally, all the application entry points and everthing that knows > about the internals of the implementation would be in separate files > from everything that does i/o or otherwise uses 'system services'. > > Right now GCC has libgcov-driver.c which includes both gcov-io.c and > libgcov-driver-system.c. Hello. > > What I'd like is a stable API between the routines that 'collect' the > data and the routines that do the i/o. With the i/o routines being > non-static and in a separate file from the others that is not > #include'd. > > I want them to be replaceable by the application. Depending upon > circumstances I can imagine the routines doing network i/o, disk i/o, > or using a serial port. What's difference in between i/o and disk i/o? What about using a NFS file system into which you can save the data (via -fprofile-dir=/mnt/mynfs/...)? I can imagine dump into stderr for example. That can be quite easily doable. Martin > > I want one version of libgcov.a for all three with three different > sets of i/o routines that I can build into the application. If the > internals of instrumentation changes, I want to not have to change the > i/o routines or anything in the application. > > If you think of it in disk driver terms, some of the routines in > libgcov.a provide a DDI -- an interface of routines that the > application call call. For applications that exit, one of the > routines is called at program exit. For long running applications, > there are routines in the DDI to dump and flush the accumulated > information. > > And the i/o routines can be thought of as providing a DKI -- what the > library libgcov.a expects of the environment -- for example, fopen and > fwrite. > > There's also the inhibit_libc define. While if you don't have headers > you might have a hard time including <stdio.h> or some of the other > header files, if the environment has a way of doing i/o or saving the > results, there is no real reason why it should not be possible to > provide instrumentation. > > Comments? > ^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: GCC's instrumentation and the target environment 2019-11-04 9:19 ` Martin Liška @ 2019-11-04 13:06 ` David.Taylor 2019-11-04 13:45 ` Joel Sherrill 2019-11-06 8:04 ` Martin Liška 0 siblings, 2 replies; 8+ messages in thread From: David.Taylor @ 2019-11-04 13:06 UTC (permalink / raw) To: mliska, gcc > From: Martin Liška <mliska@suse.cz> > Sent: Monday, November 4, 2019 4:20 AM > To: taylor, david; gcc@gcc.gnu.org > Subject: Re: GCC's instrumentation and the target environment > On 11/1/19 7:13 PM, David Taylor wrote: > Hello. Hello. > > What I'd like is a stable API between the routines that 'collect' the > > data and the routines that do the i/o. With the i/o routines being > > non-static and in a separate file from the others that is not > > #include'd. > > > > I want them to be replaceable by the application. Depending upon > > circumstances I can imagine the routines doing network i/o, disk i/o, > > or using a serial port. > > What's difference in between i/o and disk i/o? What about using a NFS file > system into which you can save the data (via -fprofile-dir=/mnt/mynfs/...)? I/O encompasses more than just reading and writing a file in a file system. Depending on the embedded target you might not have the ability to NFS mount. You might not even have a file system accessible to instrumentation. By network I/O I'm thinking sockets. There's some code possibly run at 'boot' time or possibly run during the first __gcov_open that establishes a network connection with a process running on another system. There's some protocol, agreed to by the application and remote process, for communicating the data collected and which file it belongs to. By serial I/O, I'm thinking of a serial port. Hopefully that is clearer. > I can imagine dump into stderr for example. That can be quite easily doable. I don't think that the current implementation would make that easy. For us there are potentially over a thousand files being instrumented. You need to communicate which file the data belongs to. Whether it is via stderr, a serial port, or a network connection, the file name needs to be in the stream and there needs to be a way of determining when one file ends and the next one begins. For us, stderr and stdout, when defined, are used for communicating status and extraordinary events. And not well suited for transferring instrumentation data. > Martin David ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: GCC's instrumentation and the target environment 2019-11-04 13:06 ` David.Taylor @ 2019-11-04 13:45 ` Joel Sherrill 2019-11-06 8:04 ` Martin Liška 1 sibling, 0 replies; 8+ messages in thread From: Joel Sherrill @ 2019-11-04 13:45 UTC (permalink / raw) To: David.Taylor; +Cc: Martin Liška, GCC On Mon, Nov 4, 2019 at 7:06 AM <David.Taylor@dell.com> wrote: > > From: Martin Liška <mliska@suse.cz> > > Sent: Monday, November 4, 2019 4:20 AM > > To: taylor, david; gcc@gcc.gnu.org > > Subject: Re: GCC's instrumentation and the target environment > > > On 11/1/19 7:13 PM, David Taylor wrote: > > > Hello. > > Hello. > > > > What I'd like is a stable API between the routines that 'collect' the > > > data and the routines that do the i/o. With the i/o routines being > > > non-static and in a separate file from the others that is not > > > #include'd. > > > > > > I want them to be replaceable by the application. Depending upon > > > circumstances I can imagine the routines doing network i/o, disk i/o, > > > or using a serial port. > > > > What's difference in between i/o and disk i/o? What about using a NFS > file > > system into which you can save the data (via > -fprofile-dir=/mnt/mynfs/...)? > > I/O encompasses more than just reading and writing a file in a file system. > Depending on the embedded target you might not have the ability to NFS > mount. > You might not even have a file system accessible to instrumentation. > > By network I/O I'm thinking sockets. There's some code possibly run at > 'boot' time or possibly run during the first __gcov_open that establishes a > network connection with > a process running on another system. There's some protocol, agreed to by > the > application and remote process, for communicating the data collected and > which > file it belongs to. > > By serial I/O, I'm thinking of a serial port. > > Hopefully that is clearer. > > > I can imagine dump into stderr for example. That can be quite easily > doable. > > I don't think that the current implementation would make that easy. For > us there > are potentially over a thousand files being instrumented. You need to > communicate > which file the data belongs to. Whether it is via stderr, a serial port, > or a network > connection, the file name needs to be in the stream and there needs to be > a way > of determining when one file ends and the next one begins. > > For us, stderr and stdout, when defined, are used for communicating > status and extraordinary events. And not well suited for transferring > instrumentation > data. > And I generally agree with that statement but I am also on a project evaluating the use of a commercial tool which does coverage and includes MCDC analysis. It has a very flexible plugin for this specific purpose. You can dump in any format you can decode to any output destination. They have many standard implementations and plenty of examples you can tailor. It wouldn't be terribly difficult to multiplex the console and filter it. I would suggest consideration for dumping into a buffer and having an external agent (e.g. debugger, JTAG based program, etc) retrieve it. RTEMS programs generally don't exit and often have no networking. You have to have flexibility. No one is forcing a singular output media -- just flexibility. <hint> I'd love to see decision and MCDC coverage support </hint>. --joel > > > Martin > > David > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: GCC's instrumentation and the target environment 2019-11-04 13:06 ` David.Taylor 2019-11-04 13:45 ` Joel Sherrill @ 2019-11-06 8:04 ` Martin Liška 1 sibling, 0 replies; 8+ messages in thread From: Martin Liška @ 2019-11-06 8:04 UTC (permalink / raw) To: David.Taylor, gcc On 11/4/19 2:06 PM, David.Taylor@dell.com wrote: >> From: Martin LiÅ¡ka <mliska@suse.cz> >> Sent: Monday, November 4, 2019 4:20 AM >> To: taylor, david; gcc@gcc.gnu.org >> Subject: Re: GCC's instrumentation and the target environment > >> On 11/1/19 7:13 PM, David Taylor wrote: > >> Hello. > > Hello. > >>> What I'd like is a stable API between the routines that 'collect' the >>> data and the routines that do the i/o. With the i/o routines being >>> non-static and in a separate file from the others that is not >>> #include'd. >>> >>> I want them to be replaceable by the application. Depending upon >>> circumstances I can imagine the routines doing network i/o, disk i/o, >>> or using a serial port. >> >> What's difference in between i/o and disk i/o? What about using a NFS file >> system into which you can save the data (via -fprofile-dir=/mnt/mynfs/...)? > > I/O encompasses more than just reading and writing a file in a file system. > Depending on the embedded target you might not have the ability to NFS mount. > You might not even have a file system accessible to instrumentation. > > By network I/O I'm thinking sockets. There's some code possibly run at 'boot' time or possibly run during the first __gcov_open that establishes a network connection with > a process running on another system. There's some protocol, agreed to by the > application and remote process, for communicating the data collected and which > file it belongs to. > > By serial I/O, I'm thinking of a serial port. Hello. I see your needs. I would recommend to come up with patches that will enable such a communication channel. I can review the patches or help you with obstacles. Martin > > Hopefully that is clearer. > >> I can imagine dump into stderr for example. That can be quite easily doable. > > I don't think that the current implementation would make that easy. For us there > are potentially over a thousand files being instrumented. You need to communicate > which file the data belongs to. Whether it is via stderr, a serial port, or a network > connection, the file name needs to be in the stream and there needs to be a way > of determining when one file ends and the next one begins. > > For us, stderr and stdout, when defined, are used for communicating > status and extraordinary events. And not well suited for transferring instrumentation > data. > >> Martin > > David > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: GCC's instrumentation and the target environment 2019-11-01 18:18 David Taylor 2019-11-04 9:19 ` Martin Liška @ 2020-11-14 13:04 ` Sebastian Huber 1 sibling, 0 replies; 8+ messages in thread From: Sebastian Huber @ 2020-11-14 13:04 UTC (permalink / raw) To: gcc [-- Attachment #1: Type: text/plain, Size: 833 bytes --] Hello David, I also would like to use GCC to get code coverage on an embedded system. My approach would be to place the gcov information in a dedicated linker set: https://gcc.gnu.org/pipermail/gcc-patches/2020-November/559004.html Please have a look at the attached patches for a proposal to get the data from the target. -- embedded brains GmbH Sebastian HUBER Dornierstr. 4 82178 Puchheim Germany email: sebastian.huber@embedded-brains.de Phone: +49-89-18 94 741 - 16 Fax: +49-89-18 94 741 - 08 PGP: Public key available on request. embedded brains GmbH 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/ [-- Attachment #2: 0001-gcov-Add-and-use-gcov_are_all_counters_zero.patch --] [-- Type: text/x-patch, Size: 2010 bytes --] From ace43807e322dbdb075e507d9a84e676d4c34c64 Mon Sep 17 00:00:00 2001 From: Sebastian Huber <sebastian.huber@embedded-brains.de> Date: Sat, 14 Nov 2020 13:51:09 +0100 Subject: [PATCH 1/2] gcov: Add and use gcov_are_all_counters_zero() libgcc/ libgcov.h (gcov_are_all_counters_zero): New. libgcov-driver.c (write_one_data): Use gcov_are_all_counters_zero(). --- libgcc/libgcov-driver.c | 12 ++---------- libgcc/libgcov.h | 12 ++++++++++++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c index e53e4dc392a..ba308438474 100644 --- a/libgcc/libgcov-driver.c +++ b/libgcc/libgcov-driver.c @@ -428,16 +428,8 @@ write_one_data (const struct gcov_info *gi_ptr, write_top_counters (ci_ptr, t_ix, n_counts); else { - /* Do not stream when all counters are zero. */ - int all_zeros = 1; - for (unsigned i = 0; i < n_counts; i++) - if (ci_ptr->values[i] != 0) - { - all_zeros = 0; - break; - } - - if (all_zeros) + if (gcov_are_all_counters_zero (ci_ptr)) + /* Do not stream when all counters are zero. */ gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), GCOV_TAG_COUNTER_LENGTH (-n_counts)); else diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h index e70cf63b414..915a1b1530d 100644 --- a/libgcc/libgcov.h +++ b/libgcc/libgcov.h @@ -304,6 +304,18 @@ extern void __gcov_average_profiler_atomic (gcov_type *, gcov_type); extern void __gcov_ior_profiler (gcov_type *, gcov_type); extern void __gcov_ior_profiler_atomic (gcov_type *, gcov_type); +/* Return 1, if all counter values are zero, otherwise 0. */ + +static inline int +gcov_are_all_counters_zero (const struct gcov_ctr_info *ci_ptr) +{ + for (unsigned i = 0; i < ci_ptr->num; i++) + if (ci_ptr->values[i] != 0) + return 0; + + return 1; +} + #ifndef inhibit_libc /* The wrappers around some library functions.. */ extern pid_t __gcov_fork (void) ATTRIBUTE_HIDDEN; -- 2.26.2 [-- Attachment #3: 0002-gcov-Add-__gcov_info_to_gdca.patch --] [-- Type: text/x-patch, Size: 6580 bytes --] From 9235be68b52ee7b321d985fe2d82a38d685ffb4f Mon Sep 17 00:00:00 2001 From: Sebastian Huber <sebastian.huber@embedded-brains.de> Date: Fri, 13 Nov 2020 22:01:14 +0100 Subject: [PATCH 2/2] gcov: Add __gcov_info_to_gdca() libgcc/ Makefile.in: Add libgcov-info-to-gcda.c to libgcov.a. gcov.h (gcov_info): Declare. (__gcov_info_to_gdca): Likewise. libgcov-info-to-gcda.c: New. --- libgcc/Makefile.in | 7 ++- libgcc/gcov.h | 9 +++ libgcc/libgcov-info-to-gcda.c | 106 ++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 libgcc/libgcov-info-to-gcda.c diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index d6075d32bd4..ae8ddc23955 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -909,13 +909,16 @@ LIBGCOV_INTERFACE = _gcov_dump _gcov_fork \ _gcov_execle _gcov_execv _gcov_execvp _gcov_execve _gcov_reset \ _gcov_lock_unlock LIBGCOV_DRIVER = _gcov +LIBGCOV_INFO_TO_GCDA = _gcov_info_to_gcda libgcov-merge-objects = $(patsubst %,%$(objext),$(LIBGCOV_MERGE)) libgcov-profiler-objects = $(patsubst %,%$(objext),$(LIBGCOV_PROFILER)) libgcov-interface-objects = $(patsubst %,%$(objext),$(LIBGCOV_INTERFACE)) libgcov-driver-objects = $(patsubst %,%$(objext),$(LIBGCOV_DRIVER)) +libgcov-info-to-gcda-objects = $(patsubst %,%$(objext),$(LIBGCOV_INFO_TO_GCDA)) libgcov-objects = $(libgcov-merge-objects) $(libgcov-profiler-objects) \ - $(libgcov-interface-objects) $(libgcov-driver-objects) + $(libgcov-interface-objects) $(libgcov-driver-objects) \ + $(libgcov-info-to-gcda-objects) $(libgcov-merge-objects): %$(objext): $(srcdir)/libgcov-merge.c $(srcdir)/gcov.h $(srcdir)/libgcov.h $(gcc_compile) -DL$* -c $(srcdir)/libgcov-merge.c @@ -926,6 +929,8 @@ $(libgcov-interface-objects): %$(objext): $(srcdir)/libgcov-interface.c $(srcdir $(libgcov-driver-objects): %$(objext): $(srcdir)/libgcov-driver.c \ $(srcdir)/libgcov-driver-system.c $(srcdir)/gcov.h $(srcdir)/libgcov.h $(gcc_compile) -DL$* -c $(srcdir)/libgcov-driver.c +$(libgcov-info-to-gcda-objects): %$(objext): $(srcdir)/libgcov-info-to-gcda.c $(srcdir)/gcov.h $(srcdir)/libgcov.h + $(gcc_compile) -DL$* -c $(srcdir)/libgcov-info-to-gcda.c # Static libraries. diff --git a/libgcc/gcov.h b/libgcc/gcov.h index 0e3eed31032..f5ee7d49052 100644 --- a/libgcc/gcov.h +++ b/libgcc/gcov.h @@ -25,6 +25,8 @@ #ifndef GCC_GCOV_H #define GCC_GCOV_H +struct gcov_info; + /* Set all counters to zero. */ extern void __gcov_reset (void); @@ -33,4 +35,11 @@ extern void __gcov_reset (void); extern void __gcov_dump (void); +/* Output gcov information as gcda data stream. */ + +extern void __gcov_info_to_gcda (const struct gcov_info *, + void (*) (const char *, void *), + void (*) (const void *, unsigned, void *), + void *); + #endif /* GCC_GCOV_H */ diff --git a/libgcc/libgcov-info-to-gcda.c b/libgcc/libgcov-info-to-gcda.c new file mode 100644 index 00000000000..d40d279b372 --- /dev/null +++ b/libgcc/libgcov-info-to-gcda.c @@ -0,0 +1,106 @@ +/* Routines required for instrumenting a program. */ +/* Compile this one with gcc. */ +/* Copyright (C) 2020 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#include "libgcov.h" + +static void +gcov_fn_info_to_gcda (const struct gcov_info *gi_ptr, + const struct gcov_fn_info *gfi_ptr, + void (*dump) (const void *, unsigned, void *), + void *arg) +{ + const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs; + + for (unsigned t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) + { + if (!gi_ptr->merge[t_ix]) + continue; + + if (t_ix != GCOV_COUNTER_V_TOPN && t_ix != GCOV_COUNTER_V_INDIR) + { + gcov_unsigned_t word = GCOV_TAG_FOR_COUNTER (t_ix); + (*dump) (&word, sizeof (word), arg); + gcov_position_t n_counts = ci_ptr->num; + + if (gcov_are_all_counters_zero (ci_ptr)) + { + /* Do not stream when all counters are zero. */ + word = GCOV_TAG_COUNTER_LENGTH (-n_counts); + (*dump) (&word, sizeof (word), arg); + } + else + { + word = GCOV_TAG_COUNTER_LENGTH (n_counts); + (*dump) (&word, sizeof (word), arg); + + for (unsigned i = 0; i < n_counts; i++) + { + gcov_type value = ci_ptr->values[i]; + word = (gcov_unsigned_t) value; + (*dump) (&word, sizeof (word), arg); + + if (sizeof (value) > sizeof (word)) + word = (gcov_unsigned_t) (value >> 32); + else + word = 0; + + (*dump) (&word, sizeof (word), arg); + } + } + } + + ci_ptr++; + } +} + +void +__gcov_info_to_gcda (const struct gcov_info *gi_ptr, + void (*filename) (const char *, void *), + void (*dump) (const void *, unsigned, void *), + void *arg) +{ + (*filename) (gi_ptr->filename, arg); + gcov_unsigned_t word = GCOV_DATA_MAGIC; + (*dump) (&word, sizeof (word), arg); + (*dump) (&gi_ptr->version, sizeof (gi_ptr->version), arg); + (*dump) (&gi_ptr->stamp, sizeof (gi_ptr->stamp), arg); + + for (unsigned f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++) + { + const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix]; + word = GCOV_TAG_FUNCTION; + (*dump) (&word, sizeof (word), arg); + word = GCOV_TAG_FUNCTION_LENGTH; + (*dump) (&word, sizeof (word), arg); + (*dump) (&gfi_ptr->ident, sizeof (gfi_ptr->ident), arg); + (*dump) (&gfi_ptr->lineno_checksum, + sizeof (gfi_ptr->lineno_checksum), arg); + (*dump) (&gfi_ptr->cfg_checksum, sizeof (gfi_ptr->cfg_checksum), arg); + gcov_fn_info_to_gcda (gi_ptr, gfi_ptr, dump, arg); + } + + word = 0; + (*dump) (&word, sizeof (word), arg); +} -- 2.26.2 ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2020-11-14 13:04 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-11-20 15:22 GCC's instrumentation and the target environment David Taylor 2019-11-21 12:43 ` Martin Liška -- strict thread matches above, loose matches on Subject: below -- 2019-11-01 18:18 David Taylor 2019-11-04 9:19 ` Martin Liška 2019-11-04 13:06 ` David.Taylor 2019-11-04 13:45 ` Joel Sherrill 2019-11-06 8:04 ` Martin Liška 2020-11-14 13:04 ` Sebastian Huber
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).