This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Introduce libgcov.so run-time library (PR gcov-profile/84107).


On 08/29/2018 11:17 AM, Richard Biener wrote:
> On Wed, Aug 29, 2018 at 10:31 AM Martin Liška <mliska@suse.cz> wrote:
>>
>> Hello.
>>
>> Moving the thread from gcc ML into gcc-patches. That's first implementation
>> of shared libgcov library. Currently inclusion of t-libgcov is added only
>> to *-linux targets. Is it fine to add to all configurations that already
>> include 't-slibgcc t-slibgcc-elf-ver'?
>>
>> Patch can bootstrap on ppc64le-redhat-linux and survives regression tests.
> 
> I understand this is to make profiling work with multiple DSOs (all
> instrumented).

Yes.

> But does this also make the case work when those DSOs are dlopened/dlclosed
> multiple times?

That works fine even now, when a DSO is loaded, __gcov_init is called and
it registers gcov_info into __gcov_root.

Following sample:

#include <dlfcn.h>
#include <assert.h>
#include <unistd.h>

int main()
{
  for (int i = 0; i < 10; i++)
  {
    void *handle = dlopen ("libfoo.so", RTLD_NOW);
    assert (handle);

    void (*fn) (void) = dlsym (handle, "foo");
    assert (fn);

    fn ();
    sleep (1);
  }

  return 0;
}

has:

$ gcov-dump -l foo.gcda 
foo.gcda:data:magic `gcda':version `A82*'
foo.gcda:stamp 2235622999
foo.gcda:  a3000000:  22:PROGRAM_SUMMARY checksum=0x02bfe640
foo.gcda:                counts=2, runs=1, sum_all=20, run_max=10, sum_max=10
foo.gcda:                counter histogram:
foo.gcda:                 9: num counts=2, min counter=10, cum_counter=20
foo.gcda:  01000000:   3:FUNCTION ident=1636255671, lineno_checksum=0x2172766e, cfg_checksum=0xc0bbb23e
foo.gcda:    01a10000:   4:COUNTERS arcs 2 counts
foo.gcda:                   0: 10 10 
foo.gcda:    01af0000:   2:COUNTERS time_profiler 1 counts
foo.gcda:                   0: 1 

which is fine, runs == 1 and arcs counter executed 10x.


  I understand that with the shared libgcov implementation this
> library must be finalized last? 

If you do profiling, then you depend on libgcov, thus it's loaded before a DSO (or executable)
is loaded.

 Wouldn't it be better to have some additional
> object that lives in an executable only?  Or do we want profiled DSOs without
> profiling the executable using it? 

That should be rare, but it will be possible as __gcov_exit will be eventually called.

 Does that case work with the shared libgcov
> (with dlopen/dlclose)? 

Yes, I've just tested that.

 Does it work when DSO1 is compiled with GCC N
> and DSO2 is compiled with GCC N+1 where the libgcov ABI changed?

For such case we have:

/* Exactly one of these will be live in the process image.  */
struct gcov_master __gcov_master = 
  {GCOV_VERSION, 0};
...
and it's check in __gcov_init.

> 
> I think we need a better understanding of the situation before jumping to
> the conclusion that a shared libgcov is the solution.  Maybe better isolating
> the individual instances is better?

It's undesired as seen in the PR. When doing profiling of indirect jumps
we need have exactly one __gcov_indirect_call_callee. That's because one can
do indirect calls that cross DSO boundaries.

Martin

> 
> Richard.
> 
>> Martin
>>
>> libgcc/ChangeLog:
>>
>> 2018-08-28  Martin Liska  <mliska@suse.cz>
>>
>>         PR gcov-profile/84107
>>         * Makefile.in: Build libgcov.so objects separately,
>>         add rule for libgcov.map and how the library
>>         is linked.
>>         * config.host: Add t-libgcov and t-libgcov-elf-ver
>>         to *-linux targets.
>>         * config/t-libgcov: New file.
>>         * config/t-libgcov-elf-ver: New file.
>>         * libgcov-driver.c: Declare function if new L_gcov_shared
>>         is defined.
>>         * libgcov-interface.c: Likewise.
>>         * libgcov-merge.c: Likewise.
>>         * libgcov-profiler.c: Likewise.
>>         * libgcov-std.ver.in: New file.
>>         * libgcov.h (__gcov_init): Remove ATTRIBUTE_HIDDEN.
>>         (__gcov_exit): Likewise.
>>         (__gcov_merge_add): Likewise.
>>         (__gcov_merge_time_profile): Likewise.
>>         (__gcov_merge_single): Likewise.
>>         (__gcov_merge_ior): Likewise.
>>         (__gcov_merge_icall_topn): Likewise.
>>         (gcov_sort_n_vals): Likewise.
>>         (__gcov_fork): Likewise.
>>         (__gcov_execl): Likewise.
>>         (__gcov_execlp): Likewise.
>>         (__gcov_execle): Likewise.
>>         (__gcov_execv): Likewise.
>>         (__gcov_execvp): Likewise.
>>         (__gcov_execve): Likewise.
>> ---
>>  libgcc/Makefile.in              | 56 ++++++++++++++++++++++++++++++---
>>  libgcc/config.host              |  2 +-
>>  libgcc/config/t-libgcov         | 46 +++++++++++++++++++++++++++
>>  libgcc/config/t-libgcov-elf-ver |  3 ++
>>  libgcc/libgcov-driver.c         |  4 +--
>>  libgcc/libgcov-interface.c      | 28 ++++++++---------
>>  libgcc/libgcov-merge.c          | 14 ++++-----
>>  libgcc/libgcov-profiler.c       | 34 ++++++++++----------
>>  libgcc/libgcov-std.ver.in       | 53 +++++++++++++++++++++++++++++++
>>  libgcc/libgcov.h                | 31 +++++++++---------
>>  10 files changed, 209 insertions(+), 62 deletions(-)
>>  create mode 100644 libgcc/config/t-libgcov
>>  create mode 100644 libgcc/config/t-libgcov-elf-ver
>>  create mode 100644 libgcc/libgcov-std.ver.in
>>
>>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]