[PATCH] gold: Add -Bsymbolic-non-weak-functions

Fangrui Song i@maskray.me
Wed May 26 23:22:46 GMT 2021


On Wed, May 19, 2021 at 11:05 PM Fangrui Song via Binutils
<binutils@sourceware.org> wrote:
>
> This option is a subset of -Bsymbolic-functions: only STB_GLOBAL are
> considered. Vague linkage functions are STB_WEAK. A vague linkage
> function may have different addresses in a -Bsymbolic-functions linked
> shared object and outside the shared object.
> -Bsymbolic-non-weak-functions can keep pointer equality while providing
> most benefits: (a) fewer JUMP_SLOT (symbol lookups) (b) avoid PLT
> entries for default visibility defined functions.
>
> [Hope a maintainer can implement this for GNU ld.
> The code is too difficult for me to implement:)]
>
> gold/
>     PR 27871
>     * options.h (General_options): Add -Bsymbolic-non-weak-functions.
>     * options.cc (General_options): Define
>     parse_Bsymbols_non_weak_functions.
>     * symtab.h (Symbol::is_preemptible): Check -Bsymbolic-non-weak-functions.
>     * testsuite/Makefile.am (check_SCRIPTS): Add bsymbolic_non_weak_functions.sh.
>     (check_DATA): Add bsymbolic_non_weak_functions.stdout.
>     (MOSTLYCLEANFILES): Add bsymbolic_non_weak_functions.
>     * testsuite/Makefile.in: Regenerate.
>     * testsuite/bsymbolic_non_weak_functions.sh: New file.
>     * testsuite/bsymbolic_non_weak_functions.c: New file.
> ---
>  gold/options.cc                               |  7 +++
>  gold/options.h                                | 10 ++++
>  gold/symtab.h                                 |  4 +-
>  gold/testsuite/Makefile.am                    | 10 ++++
>  gold/testsuite/Makefile.in                    | 22 +++++++--
>  gold/testsuite/bsymbolic_non_weak_functions.c | 46 +++++++++++++++++++
>  .../testsuite/bsymbolic_non_weak_functions.sh | 46 +++++++++++++++++++
>  7 files changed, 141 insertions(+), 4 deletions(-)
>  create mode 100644 gold/testsuite/bsymbolic_non_weak_functions.c
>  create mode 100755 gold/testsuite/bsymbolic_non_weak_functions.sh
>
> diff --git a/gold/options.cc b/gold/options.cc
> index 5a55bd8ba6d..2335dbccc03 100644
> --- a/gold/options.cc
> +++ b/gold/options.cc
> @@ -347,6 +347,13 @@ General_options::parse_Bno_symbolic(const char*, const char*,
>    this->bsymbolic_ = BSYMBOLIC_NONE;
>  }
>
> +void
> +General_options::parse_Bsymbolic_non_weak_functions(const char*, const char*,
> +                                          Command_line*)
> +{
> +  this->bsymbolic_ = BSYMBOLIC_NON_WEAK_FUNCTIONS;
> +}
> +
>  void
>  General_options::parse_Bsymbolic_functions(const char*, const char*,
>                                            Command_line*)
> diff --git a/gold/options.h b/gold/options.h
> index 757ebf18fec..b14503ce23f 100644
> --- a/gold/options.h
> +++ b/gold/options.h
> @@ -752,6 +752,11 @@ class General_options
>                       "for -shared (default)"),
>                   NULL);
>
> +  DEFINE_special (Bsymbolic_non_weak_functions, options::ONE_DASH, '\0',
> +                 N_ ("Bind default visibility defined STB_GLOBAL function symbols "
> +                     "locally for -shared"),
> +                 NULL);
> +
>    DEFINE_special (Bsymbolic_functions, options::ONE_DASH, '\0',
>                   N_ ("Bind default visibility defined function symbols "
>                       "locally for -shared"),
> @@ -1752,6 +1757,7 @@ class General_options
>    enum Bsymbolic_kind
>    {
>      BSYMBOLIC_NONE,
> +    BSYMBOLIC_NON_WEAK_FUNCTIONS,
>      BSYMBOLIC_FUNCTIONS,
>      BSYMBOLIC_ALL,
>    };
> @@ -1760,6 +1766,10 @@ class General_options
>    Bsymbolic() const
>    { return this->bsymbolic_ == BSYMBOLIC_ALL; }
>
> +  bool
> +  Bsymbolic_non_weak_functions() const
> +  { return this->bsymbolic_ == BSYMBOLIC_NON_WEAK_FUNCTIONS; }
> +
>    bool
>    Bsymbolic_functions() const
>    { return this->bsymbolic_ == BSYMBOLIC_FUNCTIONS; }
> diff --git a/gold/symtab.h b/gold/symtab.h
> index 104429a5af1..b1dce1961bb 100644
> --- a/gold/symtab.h
> +++ b/gold/symtab.h
> @@ -628,7 +628,9 @@ class Symbol
>      // rather than for being STT_FUNC, because that is what the GNU
>      // linker does.
>      if (this->type() != elfcpp::STT_OBJECT
> -       && parameters->options().Bsymbolic_functions())
> +       && (parameters->options().Bsymbolic_functions()
> +           || (parameters->options().Bsymbolic_non_weak_functions()
> +               && this->binding() != elfcpp::STB_WEAK)))
>        return false;
>
>      // Otherwise the symbol is preemptible.
> diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
> index 38e54818f48..bea11a0675e 100644
> --- a/gold/testsuite/Makefile.am
> +++ b/gold/testsuite/Makefile.am
> @@ -4434,4 +4434,14 @@ retain_2: retain_2.o ../ld-new
>  retain_2.o: retain_2.s
>         $(TEST_AS) -o $@ $<
>
> +check_SCRIPTS += bsymbolic_non_weak_functions.sh
> +check_DATA += bsymbolic_non_weak_functions.stdout
> +MOSTLYCLEANFILES += bsymbolic_non_weak_functions
> +bsymbolic_non_weak_functions: bsymbolic_non_weak_functions.o gcctestdir/ld
> +       $(CXXLINK) $< -shared -Wl,-Bsymbolic-non-weak-functions
> +bsymbolic_non_weak_functions.o: bsymbolic_non_weak_functions.c
> +       $(COMPILE) -c -fpic -o $@ $<
> +bsymbolic_non_weak_functions.stdout: bsymbolic_non_weak_functions
> +       $(TEST_READELF) -rW $< > $@
> +
>  endif DEFAULT_TARGET_X86_64
> diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
> index 7b4b7832d38..792e4cd63e7 100644
> --- a/gold/testsuite/Makefile.in
> +++ b/gold/testsuite/Makefile.in
> @@ -1130,13 +1130,16 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
>  @DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390x_z4_ns split_s390x_n1_ns split_s390x_n2_ns split_s390x_r
>
>  @DEFAULT_TARGET_X86_64_TRUE@am__append_114 = *.dwo *.dwp pr26936a \
> -@DEFAULT_TARGET_X86_64_TRUE@   pr26936b retain_1 retain_2
> +@DEFAULT_TARGET_X86_64_TRUE@   pr26936b retain_1 retain_2 \
> +@DEFAULT_TARGET_X86_64_TRUE@   bsymbolic_non_weak_functions
>  @DEFAULT_TARGET_X86_64_TRUE@am__append_115 = dwp_test_1.sh \
> -@DEFAULT_TARGET_X86_64_TRUE@   dwp_test_2.sh pr26936.sh retain.sh
> +@DEFAULT_TARGET_X86_64_TRUE@   dwp_test_2.sh pr26936.sh retain.sh \
> +@DEFAULT_TARGET_X86_64_TRUE@   bsymbolic_non_weak_functions.sh
>  @DEFAULT_TARGET_X86_64_TRUE@am__append_116 = dwp_test_1.stdout \
>  @DEFAULT_TARGET_X86_64_TRUE@   dwp_test_2.stdout pr26936a.stdout \
>  @DEFAULT_TARGET_X86_64_TRUE@   pr26936b.stdout retain_1.out \
> -@DEFAULT_TARGET_X86_64_TRUE@   retain_2.out
> +@DEFAULT_TARGET_X86_64_TRUE@   retain_2.out \
> +@DEFAULT_TARGET_X86_64_TRUE@   bsymbolic_non_weak_functions.stdout
>  subdir = testsuite
>  ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
>  am__aclocal_m4_deps = $(top_srcdir)/../config/ax_pthread.m4 \
> @@ -6459,6 +6462,13 @@ retain.sh.log: retain.sh
>         --log-file $$b.log --trs-file $$b.trs \
>         $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
>         "$$tst" $(AM_TESTS_FD_REDIRECT)
> +bsymbolic_non_weak_functions.sh.log: bsymbolic_non_weak_functions.sh
> +       @p='bsymbolic_non_weak_functions.sh'; \
> +       b='bsymbolic_non_weak_functions.sh'; \
> +       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
> +       --log-file $$b.log --trs-file $$b.trs \
> +       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
> +       "$$tst" $(AM_TESTS_FD_REDIRECT)
>  object_unittest.log: object_unittest$(EXEEXT)
>         @p='object_unittest$(EXEEXT)'; \
>         b='object_unittest'; \
> @@ -10414,6 +10424,12 @@ uninstall-am:
>  @DEFAULT_TARGET_X86_64_TRUE@   ../ld-new -pie -e _start --gc-sections -o $@  retain_2.o
>  @DEFAULT_TARGET_X86_64_TRUE@retain_2.o: retain_2.s
>  @DEFAULT_TARGET_X86_64_TRUE@   $(TEST_AS) -o $@ $<
> +@DEFAULT_TARGET_X86_64_TRUE@bsymbolic_non_weak_functions: bsymbolic_non_weak_functions.o gcctestdir/ld
> +@DEFAULT_TARGET_X86_64_TRUE@   $(CXXLINK) $< -shared -Wl,-Bsymbolic-non-weak-functions
> +@DEFAULT_TARGET_X86_64_TRUE@bsymbolic_non_weak_functions.o: bsymbolic_non_weak_functions.c
> +@DEFAULT_TARGET_X86_64_TRUE@   $(COMPILE) -c -fpic -o $@ $<
> +@DEFAULT_TARGET_X86_64_TRUE@bsymbolic_non_weak_functions.stdout: bsymbolic_non_weak_functions
> +@DEFAULT_TARGET_X86_64_TRUE@   $(TEST_READELF) -rW $< > $@
>
>  # Tell versions [3.59,3.63) of GNU make to not export all variables.
>  # Otherwise a system limit (for SysV at least) may be exceeded.
> diff --git a/gold/testsuite/bsymbolic_non_weak_functions.c b/gold/testsuite/bsymbolic_non_weak_functions.c
> new file mode 100644
> index 00000000000..d2002696658
> --- /dev/null
> +++ b/gold/testsuite/bsymbolic_non_weak_functions.c
> @@ -0,0 +1,46 @@
> +// bsymbolic_non_weak_functions.cc -- Test -Bsymbolic-non-weak-functions
> +
> +// Copyright (C) 2021 Free Software Foundation, Inc.
> +
> +// This file is part of gold.
> +
> +// This program 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 of the License, or
> +// (at your option) any later version.
> +
> +// This program 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 this program; if not, write to the Free Software
> +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
> +// MA 02110-1301, USA.
> +
> +// The goal of this program is to verify that the --dynamic-list option
> +// allows overrides for symbols listed in the file, and does symbolic
> +// binding for symbols not listed.
> +
> +#include <stdint.h>
> +
> +int global_data = 0;
> +
> +__attribute__ ((noinline)) void global_fun (void);
> +void global_fun (void) { }
> +
> +__attribute__ ((weak, noinline)) void weak_fun (void);
> +void weak_fun (void) { }
> +
> +uintptr_t test (void);
> +
> +uintptr_t test (void)
> +{
> +  uintptr_t x = global_data;
> +  x += (uintptr_t)&global_fun;
> +  x += (uintptr_t)&weak_fun;
> +  global_fun ();
> +  weak_fun ();
> +  return x;
> +}
> diff --git a/gold/testsuite/bsymbolic_non_weak_functions.sh b/gold/testsuite/bsymbolic_non_weak_functions.sh
> new file mode 100755
> index 00000000000..b64d478a8d6
> --- /dev/null
> +++ b/gold/testsuite/bsymbolic_non_weak_functions.sh
> @@ -0,0 +1,46 @@
> +#!/bin/sh
> +
> +# bsymbolic_non_weak_functions.sh -- Test -Bsymbolic-non-weak-functions
> +
> +# Copyright (C) 2021 Free Software Foundation, Inc.
> +
> +# This file is part of gold.
> +
> +# This program 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 of the License, or
> +# (at your option) any later version.
> +
> +# This program 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 this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
> +# MA 02110-1301, USA.
> +
> +check_present()
> +{
> +    if ! grep -q "$1" bsymbolic_non_weak_functions.stdout
> +    then
> +        echo "Did not find $1"
> +        exit 1
> +    fi
> +}
> +
> +check_absent()
> +{
> +    if grep -q "$1" bsymbolic_non_weak_functions.stdout
> +    then
> +        echo "Found unexpected $1"
> +        exit 1
> +    fi
> +}
> +
> +check_present 'GLOB_DAT.*global_data'
> +check_present 'GLOB_DAT.*weak_fun'
> +
> +check_present 'JUMP_SLOT.*weak_fun'
> +check_absent  'JUMP_SLOT.*global_fun'
> --
> 2.31.1.751.gd2f1c929bd-goog
>

Ping this and the GNU ld patch
https://sourceware.org/pipermail/binutils/2021-May/116703.html

This will be a great addition to the ELF world. (My libLLVM.so
libclang-cpp.so linked clang is more than 15% faster due to saved
dynamic relocations)


More information about the Binutils mailing list