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

Fangrui Song maskray@google.com
Thu May 20 06:05:02 GMT 2021


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



More information about the Binutils mailing list