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