This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Questions related to creation of libgcov.so
- From: Martin Liška <mliska at suse dot cz>
- To: Joseph Myers <joseph at codesourcery dot com>, Jakub Jelinek <jakub at redhat dot com>
- Cc: GCC Development <gcc at gcc dot gnu dot org>, Nathan Sidwell <nathan at acm dot org>, Alexander Monakov <amonakov at ispras dot ru>, Jan Hubicka <hubicka at ucw dot cz>
- Date: Tue, 14 Aug 2018 14:15:31 +0200
- Subject: Re: Questions related to creation of libgcov.so
- References: <2bf09eba-a704-8d10-0dd7-9900e275656a@suse.cz> <20180803093050.GL17988@tucnak> <alpine.DEB.2.20.1808031440500.25827@digraph.polyomino.org.uk>
On 08/03/2018 04:42 PM, Joseph Myers wrote:
> On Fri, 3 Aug 2018, Jakub Jelinek wrote:
>
>>> 3) Should I come up with a symbol versioning of the libgcov API?
>>
>> Certainly.
>
> Furthermore, make sure that the libgcov.a symbols remain hidden (via
> building the static objects with $(vis_hide), since you're removing
> ATTRIBUTE_HIDDEN).
>
Hello.
I'm sending second version of the patch candidate. I was able to create
a mapfile and generate versioned symbols for libgcov.so file.
Unresolved issues:
1) I still see linking with static library:
$ find /home/marxin/bin/gcc -name libgcov*
/home/marxin/bin/gcc/lib64/libgcov.so.1
/home/marxin/bin/gcc/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/libgcov.a
/home/marxin/bin/gcc/lib64/libgcov.so
$ export PATH=/home/marxin/bin/gcc/bin/:$PATH && export LD_LIBRARY_PATH=/home/marxin/bin/gcc/lib64/:$LD_LIBRARY_PATH
$ gcc main.c -fprofile-generate -Wl,--verbose | grep gcov
attempt to open /home/marxin/bin/gcc/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/libgcov.so failed
attempt to open /home/marxin/bin/gcc/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/libgcov.a succeeded
(/home/marxin/bin/gcc/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/libgcov.a)_gcov_merge_add.o
(/home/marxin/bin/gcc/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/libgcov.a)_gcov_merge_time_profile.o
(/home/marxin/bin/gcc/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/libgcov.a)_gcov_indirect_call_profiler_v2.o
(/home/marxin/bin/gcc/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/libgcov.a)_gcov_time_profiler.o
(/home/marxin/bin/gcc/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/libgcov.a)_gcov.o
2) Do I understand that correctly that I need to build .o files twice: once with hidden visibility and second time
without for the shared library?
3) I added t-libgcov t-libgcov-gld t-libgcov-elf-ver into *-linux for now. Am I right that it should be added
basically to all places where e.g. 't-slibgcc-elf-ver' is?
Alexander: I added the -Wl,-z,now.
Thanks,
Martin
>From 66ee61145c0bd864bb5046b7ce17344cf3c705ea Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Fri, 3 Aug 2018 11:14:15 +0200
Subject: [PATCH] Add libgcov.so: work in progress.
---
libgcc/Makefile.in | 38 +++++++++++++++++++++++++-
libgcc/config.host | 4 +--
libgcc/config/t-libgcov | 50 ++++++++++++++++++++++++++++++++++
libgcc/config/t-libgcov-gld | 5 ++++
libgcc/libgcov-profiler.c | 6 ++---
libgcc/libgcov-std.ver.in | 53 +++++++++++++++++++++++++++++++++++++
libgcc/libgcov.h | 31 +++++++++++-----------
7 files changed, 165 insertions(+), 22 deletions(-)
create mode 100644 libgcc/config/t-libgcov
create mode 100644 libgcc/config/t-libgcov-gld
create mode 100644 libgcc/libgcov-std.ver.in
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 0c5b264f717..63d18bf861b 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -944,7 +944,7 @@ libgcc.a libgcov.a libunwind.a libgcc_eh.a:
all: libgcc.a
ifeq ($(enable_gcov),yes)
-all: libgcov.a
+all: libgcov.a libgcov$(SHLIB_EXT)
endif
ifneq ($(LIBUNWIND),)
@@ -1006,6 +1006,38 @@ libunwind$(SHLIB_EXT): $(libunwind-s-objects) $(extra-parts)
@shlib_base_name@,libunwind,$(subst \
@shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIBUNWIND_LINK))))))
+# Map-file generation.
+libgcov.map.in: $(SHLIBGCOV_MAPFILES)
+ { cat $(SHLIBGCOV_MAPFILES) \
+ | sed -e '/^[ ]*#/d' \
+ -e 's/^%\(if\|else\|elif\|endif\|define\)/#\1/' \
+ | $(gcc_compile_bare) -E -xassembler-with-cpp -; \
+ } > tmp-$@
+ mv tmp-$@ $@
+libgcov.map: $(SHLIBGCOV_MKMAP) libgcov.map.in $(libgcov-objects)
+ { $(NM) $(SHLIBGCOV_NM_FLAGS) $(libgcov-objects); echo %%; \
+ cat libgcov.map.in; \
+ } | $(AWK) -f $(SHLIBGCOV_MKMAP) $(SHLIBGCOV_MKMAP_OPTS) > tmp-$@
+ mv tmp-$@ $@
+libgcov$(SHLIB_EXT): libgcov.map
+libgcov_mapfile = libgcov.map
+
+libgcov-std.ver: $(srcdir)/libgcov-std.ver.in
+ cat < $< > $@
+
+libgcov$(SHLIB_EXT): $(libgcov-objects) libgcc_s$(SHLIB_EXT)
+ # @multilib_flags@ is still needed because this may use
+ # $(GCC_FOR_TARGET) and $(LIBGCC2_CFLAGS) directly.
+ # @multilib_dir@ is not really necessary, but sometimes it has
+ # more uses than just a directory name.
+ $(mkinstalldirs) $(MULTIDIR)
+ $(subst @multilib_flags@,$(CFLAGS) -B./,$(subst \
+ @multilib_dir@,$(MULTIDIR),$(subst \
+ @shlib_objs@,$(objects),$(subst \
+ @shlib_base_name@,libgcov,$(subst \
+ @shlib_map_file@,$(libgcov_mapfile),$(subst \
+ @shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIBGCOV_LINK)))))))
+
endif
# Build the standard GCC startfiles and endfiles.
@@ -1172,6 +1204,10 @@ ifeq ($(enable_gcov),yes)
$(INSTALL_DATA) libgcov.a $(DESTDIR)$(inst_libdir)/
chmod 644 $(DESTDIR)$(inst_libdir)/libgcov.a
$(RANLIB) $(DESTDIR)$(inst_libdir)/libgcov.a
+
+ $(subst @multilib_dir@,$(MULTIDIR),$(subst \
+ @shlib_base_name@,libgcov,$(subst \
+ @shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIBGCOV_INSTALL))))
endif
parts="$(INSTALL_PARTS)"; \
diff --git a/libgcc/config.host b/libgcc/config.host
index 18cabaf24f6..2d32046e27f 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -236,7 +236,7 @@ case ${host} in
extra_parts="crtbegin.o crtend.o"
;;
*-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-gnu* | *-*-kopensolaris*-gnu)
- tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip t-slibgcc t-slibgcc-gld t-slibgcc-elf-ver t-linux"
+ tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip t-slibgcc t-slibgcc-gld t-slibgcc-elf-ver t-linux t-libgcov t-libgcov-gld t-libgcov-elf-ver"
extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
if test x$enable_vtable_verify = xyes; then
extra_parts="$extra_parts vtv_start.o vtv_end.o vtv_start_preinit.o vtv_end_preinit.o"
@@ -659,7 +659,7 @@ i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-gnu* | i[34567]86-*-kopensolaris*-gnu)
;;
x86_64-*-linux*)
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
- tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules"
+ tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprulesi"
tm_file="${tm_file} i386/elf-lib.h"
md_unwind_header=i386/linux-unwind.h
;;
diff --git a/libgcc/config/t-libgcov b/libgcc/config/t-libgcov
new file mode 100644
index 00000000000..5595d37ed96
--- /dev/null
+++ b/libgcc/config/t-libgcov
@@ -0,0 +1,50 @@
+# Copyright (C) 2018 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Build libgcov for ELF with the GNU linker.
+
+SHLIBGCOV_SOLINK = @shlib_base_name@.so
+SHLIBGCOV_OBJS = @shlib_objs@
+SHLIBGCOV_DIR = @multilib_dir@
+SHLIBGCOV_SLIBDIR_QUAL = @shlib_slibdir_qual@
+SHLIBGCOV_MAP = @shlib_map_file@
+
+SHLIBGCOV_SOVERSION = 1
+SHLIBGCOV_SONAME = @shlib_base_name@.so.$(SHLIBGCOV_SOVERSION)
+
+SHLIBGCOV_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared \
+ $(SHLIBGCOV_LDFLAGS) \
+ -nodefaultlibs -Wl,-h,$(SHLIBGCOV_SONAME) \
+ -Wl,-z,text -Wl,-z,defs -Wl,-z,now -o $(SHLIBGCOV_DIR)/$(SHLIBGCOV_SONAME).tmp \
+ @multilib_flags@ $(SHLIBGCOV_OBJS) -lc -lgcc && \
+ rm -f $(SHLIBGCOV_DIR)/$(SHLIBGCOV_SOLINK) && \
+ if [ -f $(SHLIBGCOV_DIR)/$(SHLIBGCOV_SONAME) ]; then \
+ mv -f $(SHLIBGCOV_DIR)/$(SHLIBGCOV_SONAME) \
+ $(SHLIBGCOV_DIR)/$(SHLIBGCOV_SONAME).backup; \
+ else true; fi && \
+ mv $(SHLIBGCOV_DIR)/$(SHLIBGCOV_SONAME).tmp \
+ $(SHLIBGCOV_DIR)/$(SHLIBGCOV_SONAME) && \
+ $(LN_S) $(SHLIBGCOV_SONAME) $(SHLIBGCOV_DIR)/$(SHLIBGCOV_SOLINK)
+
+SHLIBGCOV_INSTALL = \
+ $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$(slibdir)$(SHLIBGCOV_SLIBDIR_QUAL); \
+ $(INSTALL_DATA) $(SHLIBGCOV_DIR)/$(SHLIBGCOV_SONAME) \
+ $(DESTDIR)$(slibdir)$(SHLIBGCOV_SLIBDIR_QUAL)/$(SHLIBGCOV_SONAME); \
+ rm -f $(DESTDIR)$(slibdir)$(SHLIBGCOV_SLIBDIR_QUAL)/$(SHLIBGCOV_SOLINK); \
+ $(LN_S) $(SHLIBGCOV_SONAME) \
+ $(DESTDIR)$(slibdir)$(SHLIBGCOV_SLIBDIR_QUAL)/$(SHLIBGCOV_SOLINK)
diff --git a/libgcc/config/t-libgcov-gld b/libgcc/config/t-libgcov-gld
new file mode 100644
index 00000000000..3a00239e22e
--- /dev/null
+++ b/libgcc/config/t-libgcov-gld
@@ -0,0 +1,5 @@
+# Build a shared libgcov library for ELF with symbol versioning
+# with the GNU linker.
+
+SHLIBGCOV_LDFLAGS = -Wl,--soname=$(SHLIBGCOV_SONAME) \
+ -Wl,--version-script=$(SHLIBGCOV_MAP)
diff --git a/libgcc/libgcov-profiler.c b/libgcc/libgcov-profiler.c
index 7e208d75d86..df20e73b4e1 100644
--- a/libgcc/libgcov-profiler.c
+++ b/libgcc/libgcov-profiler.c
@@ -271,12 +271,12 @@ __gcov_topn_value_profiler_body (gcov_type *counters, gcov_type value)
#if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
__thread
#endif
-gcov_type *__gcov_indirect_call_topn_counters ATTRIBUTE_HIDDEN;
+gcov_type *__gcov_indirect_call_topn_counters;
#if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
__thread
#endif
-void *__gcov_indirect_call_topn_callee ATTRIBUTE_HIDDEN;
+void *__gcov_indirect_call_topn_callee;
#ifdef TARGET_VTABLE_USES_DESCRIPTORS
#define VTABLE_USES_DESCRIPTORS 1
@@ -344,7 +344,7 @@ __gcov_indirect_call_profiler_v2 (gcov_type value, void* cur_func)
#ifdef L_gcov_time_profiler
/* Counter for first visit of each function. */
-gcov_type __gcov_time_profiler_counter ATTRIBUTE_HIDDEN;
+gcov_type __gcov_time_profiler_counter;
#endif
diff --git a/libgcc/libgcov-std.ver.in b/libgcc/libgcov-std.ver.in
new file mode 100644
index 00000000000..71fa43e26c9
--- /dev/null
+++ b/libgcc/libgcov-std.ver.in
@@ -0,0 +1,53 @@
+# Copyright (C) 2018 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+GCC_9.1.0 {
+ __gcov_init
+ __gcov_exit
+ __gcov_merge_add
+ __gcov_merge_time_profile
+ __gcov_merge_single
+ __gcov_merge_ior
+ __gcov_merge_icall_topn
+ __gcov_interval_profiler
+ __gcov_interval_profiler_atomic
+ __gcov_pow2_profiler
+ __gcov_pow2_profiler_atomic
+ __gcov_one_value_profiler
+ __gcov_one_value_profiler_atomic
+ __gcov_indirect_call_profiler_v2
+ __gcov_time_profiler
+ __gcov_time_profiler_atomic
+ __gcov_average_profiler
+ __gcov_average_profiler_atomic
+ __gcov_ior_profiler
+ __gcov_ior_profiler_atomic
+ __gcov_indirect_call_topn_profiler
+
+ __gcov_fork
+ __gcov_execl
+ __gcov_execlp
+ __gcov_execle
+ __gcov_execv
+ __gcov_execvp
+ __gcov_execve
+
+ __gcov_indirect_call_callee
+ __gcov_indirect_call_counters
+ __gcov_time_profiler_counter
+}
diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h
index 21422873cf2..d47e3fec703 100644
--- a/libgcc/libgcov.h
+++ b/libgcc/libgcov.h
@@ -234,10 +234,10 @@ extern struct gcov_master __gcov_master;
extern void __gcov_dump_one (struct gcov_root *) ATTRIBUTE_HIDDEN;
/* Register a new object file module. */
-extern void __gcov_init (struct gcov_info *) ATTRIBUTE_HIDDEN;
+extern void __gcov_init (struct gcov_info *);
/* GCOV exit function registered via a static destructor. */
-extern void __gcov_exit (void) ATTRIBUTE_HIDDEN;
+extern void __gcov_exit (void);
/* Function to reset all counters to 0. Both externally visible (and
overridable) and internal version. */
@@ -247,19 +247,19 @@ extern void __gcov_reset_int (void) ATTRIBUTE_HIDDEN;
extern void __gcov_dump_int (void) ATTRIBUTE_HIDDEN;
/* The merge function that just sums the counters. */
-extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
+extern void __gcov_merge_add (gcov_type *, unsigned);
/* The merge function to select the minimum valid counter value. */
-extern void __gcov_merge_time_profile (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
+extern void __gcov_merge_time_profile (gcov_type *, unsigned);
/* The merge function to choose the most common value. */
-extern void __gcov_merge_single (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
+extern void __gcov_merge_single (gcov_type *, unsigned);
/* The merge function that just ors the counters together. */
-extern void __gcov_merge_ior (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
+extern void __gcov_merge_ior (gcov_type *, unsigned);
/* The merge function is used for topn indirect call counters. */
-extern void __gcov_merge_icall_topn (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
+extern void __gcov_merge_icall_topn (gcov_type *, unsigned);
/* The profiler functions. */
extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned);
@@ -277,18 +277,17 @@ 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);
extern void __gcov_indirect_call_topn_profiler (gcov_type, void *);
-extern void gcov_sort_n_vals (gcov_type *, int);
+extern void gcov_sort_n_vals (gcov_type *, int) ATTRIBUTE_HIDDEN;
#ifndef inhibit_libc
/* The wrappers around some library functions.. */
-extern pid_t __gcov_fork (void) ATTRIBUTE_HIDDEN;
-extern int __gcov_execl (const char *, char *, ...) ATTRIBUTE_HIDDEN;
-extern int __gcov_execlp (const char *, char *, ...) ATTRIBUTE_HIDDEN;
-extern int __gcov_execle (const char *, char *, ...) ATTRIBUTE_HIDDEN;
-extern int __gcov_execv (const char *, char *const []) ATTRIBUTE_HIDDEN;
-extern int __gcov_execvp (const char *, char *const []) ATTRIBUTE_HIDDEN;
-extern int __gcov_execve (const char *, char *const [], char *const [])
- ATTRIBUTE_HIDDEN;
+extern pid_t __gcov_fork (void);
+extern int __gcov_execl (const char *, char *, ...);
+extern int __gcov_execlp (const char *, char *, ...);
+extern int __gcov_execle (const char *, char *, ...);
+extern int __gcov_execv (const char *, char *const []);
+extern int __gcov_execvp (const char *, char *const []);
+extern int __gcov_execve (const char *, char *const [], char *const []);
/* Functions that only available in libgcov. */
GCOV_LINKAGE int gcov_open (const char */*name*/) ATTRIBUTE_HIDDEN;
--
2.18.0