Hi.

I've started working on introduction of a new shared library for GCOV.
Justification is PR84107 where libgcov does not properly work properly
for multiple DSOs.

I created a working prototype and as it's my first time I'm creating a shared
library in GCC, I've got multiple questions:

1) currently both libgcov.so and libgcov.a are installed in an install folder 
and
when using: gcc main.c -lcov the static one is preferred.
Do we need an option -static-libgcov?

2) I created libgcc/config/t-libgcov-elf file. It's currently added just for:
 x86_64-*-linux*)

What's the right placement of content added to t-libgcov-elf?

3) Should I come up with a symbol versioning of the libgcov API?

I'm attaching current patch, so any comment is welcomed.
Thanks,
Martin
>From 3ffb36795ea6999be34ce079c435b391d5db62cb Mon Sep 17 00:00:00 2001
From: marxin <mli...@suse.cz>
Date: Fri, 3 Aug 2018 11:14:15 +0200
Subject: [PATCH] Add libgcov.so: work in progress.

---
 libgcc/Makefile.in          | 18 +++++++++++++-
 libgcc/config.host          |  2 +-
 libgcc/config/t-libgcov-elf | 48 +++++++++++++++++++++++++++++++++++++
 libgcc/libgcov-profiler.c   |  6 ++---
 libgcc/libgcov.h            | 14 +++++------
 5 files changed, 76 insertions(+), 12 deletions(-)
 create mode 100644 libgcc/config/t-libgcov-elf

diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 0c5b264f717..530bc0dced4 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,18 @@ libunwind$(SHLIB_EXT): $(libunwind-s-objects) $(extra-parts)
 		@shlib_base_name@,libunwind,$(subst \
 		@shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIBUNWIND_LINK))))))
 
+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_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIBGCOV_LINK))))))
+
 endif
 
 # Build the standard GCC startfiles and endfiles.
@@ -1172,6 +1184,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..dca583b8110 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -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 t-libgcov-elf"
 	tm_file="${tm_file} i386/elf-lib.h"
 	md_unwind_header=i386/linux-unwind.h
 	;;
diff --git a/libgcc/config/t-libgcov-elf b/libgcc/config/t-libgcov-elf
new file mode 100644
index 00000000000..19ef3db47ab
--- /dev/null
+++ b/libgcc/config/t-libgcov-elf
@@ -0,0 +1,48 @@
+# Copyright (C) 2004-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 libunwind for ELF with the GNU linker.
+
+SHLIB_SOLINK = @shlib_base_name@.so
+SHLIB_OBJS = @shlib_objs@
+SHLIB_DIR = @multilib_dir@
+SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
+
+SHLIBGCOV_SOVERSION = 1
+SHLIBGCOV_SONAME = @shlib_base_name@.so.$(SHLIBGCOV_SOVERSION)
+
+SHLIBGCOV_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared \
+	-nodefaultlibs -Wl,-h,$(SHLIBGCOV_SONAME) \
+	-Wl,-z,text -Wl,-z,defs -o $(SHLIB_DIR)/$(SHLIBGCOV_SONAME).tmp \
+	@multilib_flags@ $(SHLIB_OBJS) -lc -lgcc && \
+	rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \
+	if [ -f $(SHLIB_DIR)/$(SHLIBGCOV_SONAME) ]; then \
+	  mv -f $(SHLIB_DIR)/$(SHLIBGCOV_SONAME) \
+		$(SHLIB_DIR)/$(SHLIBGCOV_SONAME).backup; \
+	else true; fi && \
+	mv $(SHLIB_DIR)/$(SHLIBGCOV_SONAME).tmp \
+	   $(SHLIB_DIR)/$(SHLIBGCOV_SONAME) && \
+	$(LN_S) $(SHLIBGCOV_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
+
+SHLIBGCOV_INSTALL = \
+	$(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
+	$(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIBGCOV_SONAME) \
+	  $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIBGCOV_SONAME); \
+	rm -f $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK); \
+	$(LN_S) $(SHLIBGCOV_SONAME) \
+	  $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
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.h b/libgcc/libgcov.h
index 21422873cf2..2e445b60bba 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);
-- 
2.18.0

Reply via email to