From 60f18cd09d771eceb8762af2c46f27ae75b72422 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 8 Apr 2020 16:11:41 +0200 Subject: [PATCH] lib: Use attribute symver when available to define symbol versioning. GCC 10 introduces a function attribute to define symbol versioning. Add a configure check to see if __attribute__((symver)) is supported. If it is then define the OLD_VERSION, NEW_VERSION, COMPAT_VERSION and COMPAT_VERSION_NEWPROTO macros using just attribute symver, attribute alias and typeof function names. And avoid defining symbols in asm statements. The attribute doesn't accept triple @ symver definitions. The special foo@@@VERSION_XY version replaces all symbol references to foo with foo@@VERSION_XY in the file, so there is no bare foo symbol anymore. When there is still a bare foo symbol the linker creates a default version for the first section it sees in the version script. This might create duplicate default versions of the symbol. we use a trick by placing a non-default alias of the symbol in ELFUTILS_0 version section (which doesn't have any global symbols). This prevents the linker from adding an (extra) default version of the symbol. Signed-off-by: Mark Wielaard --- ChangeLog | 4 ++++ configure.ac | 13 +++++++++++++ lib/ChangeLog | 5 +++++ lib/eu-config.h | 23 +++++++++++++++++++++-- libdw/ChangeLog | 10 ++++++++++ libdw/libdw.map | 17 ++++------------- 6 files changed, 57 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 854568e0..bff3bdef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2020-04-10 Mark Wielaard + + * configure.ac: Add __attribute__((symver)) check. + 2020-03-30 Mark Wielaard * configure.ac: Set version to 0.179. diff --git a/configure.ac b/configure.ac index a39e800f..2a0aaca8 100644 --- a/configure.ac +++ b/configure.ac @@ -158,6 +158,19 @@ if test "$ac_cv_gcc_struct" = "yes"; then [Defined if __attribute__((gcc_struct)) is supported]) fi +AC_CACHE_CHECK([whether gcc supports __attribute__((symver))], + ac_cv_gcc_symver, [dnl +save_CFLAGS="$CFLAGS" +CFLAGS="$save_CFLAGS -Werror" +AC_COMPILE_IFELSE([AC_LANG_SOURCE([dnl +__attribute__ ((__symver__ ("foo@VERS_1"))) int foo_v1 (void) { } +])], ac_cv_gcc_symver=yes, ac_cv_gcc_symver=no) +CFLAGS="$save_CFLAGS"]) +if test "$ac_cv_gcc_symver" = "yes"; then + AC_DEFINE([HAVE_GCC_SYMVER], [1], + [Defined if __attribute__((symver)) is supported]) +fi + AC_CACHE_CHECK([whether gcc supports -fPIC], ac_cv_fpic, [dnl save_CFLAGS="$CFLAGS" CFLAGS="$save_CFLAGS -fPIC -Werror" diff --git a/lib/ChangeLog b/lib/ChangeLog index 51c79841..07837cce 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,8 @@ +2020-04-10 Mark Wielaard + + * eu-config.h: If HAVE_GCC_SYMVER define symbol versioning macros + using attribute symver. + 2019-08-25 Srđan Milaković * dynamicsizehash_concurrent.{c,h}: New files. diff --git a/lib/eu-config.h b/lib/eu-config.h index 84b22d7c..f5a6be22 100644 --- a/lib/eu-config.h +++ b/lib/eu-config.h @@ -177,6 +177,24 @@ asm (".section predict_data, \"aw\"; .previous\n" #ifdef SYMBOL_VERSIONING +#ifdef HAVE_GCC_SYMVER +# define OLD_VERSION(name, version) \ + __attribute__((__symver__(#name "@" #version))) \ + __attribute__((__alias__(#name))) \ + __typeof__(name) _compat_##version_##name; +#define NEW_VERSION(name, version) \ + __attribute__((__symver__(#name "@@" #version))) \ + __typeof__(name) name; \ + __attribute__((__symver__(#name "@ELFUTILS_0"))) \ + __attribute__((__alias__(#name))) \ + __typeof__(name) _local_##name; +# define COMPAT_VERSION_NEWPROTO(name, version, prefix) \ + __attribute__((__symver__(#name "@" #version))) \ + __typeof__(_compat_##prefix##_##name) _compat_##prefix##_##name; +# define COMPAT_VERSION(name, version, prefix) \ + __attribute__((__symver__(#name "@" #version))) \ + __typeof__(name) _compat_##prefix##_##name; +#else /* HAVE_GCC_SYMVER */ # define OLD_VERSION(name, version) \ asm (".globl _compat." #version "." #name "\n" \ "_compat." #version "." #name " = " #name "\n" \ @@ -190,13 +208,14 @@ asm (".section predict_data, \"aw\"; .previous\n" # define COMPAT_VERSION(name, version, prefix) \ asm (".symver _compat." #version "." #name "," #name "@" #version); \ __typeof (name) _compat_##prefix##_##name asm ("_compat." #version "." #name); -#else +#endif /* HAVE_GCC_SYMVER */ +#else /* SYMBOL_VERSIONING */ # define OLD_VERSION(name, version) /* Nothing for static linking. */ # define NEW_VERSION(name, version) /* Nothing for static linking. */ # define COMPAT_VERSION_NEWPROTO(name, version, prefix) \ error "should use #ifdef SYMBOL_VERSIONING" # define COMPAT_VERSION(name, version, prefix) error "should use #ifdef SYMBOL_VERSIONING" -#endif +#endif /* SYMBOL_VERSIONING */ #ifndef FALLTHROUGH # ifdef HAVE_FALLTHROUGH diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 59f33f9e..dae71b78 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,13 @@ +2020-04-14 Mark Wielaard + + * libdw.map (ELFUTILS_0): Explicitly mark everything local. + (ELFUTILS_0.122): Remove local wildcard. + (ELFUTILS_0.126): Likewise. + (ELFUTILS_0.127): Likewise. + (ELFUTILS_0.130): Likewise. + (ELFUTILS_0.136): Likewise. + (ELFUTILS_0.138): Likewise. + 2019-10-28 Aaron Merey * Makefile.am (libdw_so_LDLIBS): Add -ldl for libdebuginfod.so dlopen. diff --git a/libdw/libdw.map b/libdw/libdw.map index decac05c..20009868 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -1,4 +1,7 @@ -ELFUTILS_0 { }; +ELFUTILS_0 { + local: *; +}; + ELFUTILS_0.122 { global: dwarf_abbrevhaschildren; @@ -141,16 +144,12 @@ ELFUTILS_0.122 { dwfl_standard_find_debuginfo; dwfl_version; - local: - *; } ELFUTILS_0; ELFUTILS_0.126 { global: dwarf_getelf; - local: - *; } ELFUTILS_0.122; ELFUTILS_0.127 { @@ -161,8 +160,6 @@ ELFUTILS_0.127 { dwfl_report_begin_add; dwfl_module_address_section; - local: - *; } ELFUTILS_0.126; ELFUTILS_0.130 { @@ -172,8 +169,6 @@ ELFUTILS_0.130 { dwfl_module_build_id; dwfl_module_report_build_id; - local: - *; } ELFUTILS_0.127; ELFUTILS_0.136 { @@ -181,8 +176,6 @@ ELFUTILS_0.136 { dwfl_addrsegment; dwfl_report_segment; - local: - *; } ELFUTILS_0.130; ELFUTILS_0.138 { @@ -190,8 +183,6 @@ ELFUTILS_0.138 { # Replaced ELFUTILS_0.130 version, which has bug-compatibility wrapper. dwfl_module_build_id; - local: - *; } ELFUTILS_0.136; ELFUTILS_0.142 { -- 2.18.2