[PATCH] ld: Add --export-dynamic-symbol

Fangrui Song maskray@google.com
Sun May 3 06:11:42 GMT 2020


	PR ld/25910
	* ldlang.c (export_dynamic_symbol_list): New.
	(ldlang_add_export_dynamic_symbol): New.
	(lang_place_export_dynamic_symbols): New.
	(lang_process): Handle export_dynamic_symbol_list.
	* ldlang.h (ldlang_add_export_dynamic_symbol): New.
	* ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL.
	* lexsup.c (ld_options): Add entry for OPTION_EXPORT_DYNAMIC_SYMBOL.
	(parse_args): Handle it.
	* ld.texi: Add --export-dynamic-symbol documentation.
	* testsuite/ld-undefined/export-dynamic-symbol.exp: Run new test.
	* testsuite/ld-undefined/export-dynamic-symbol-1.d: New.
---
 ld/ld.texi                                    |  8 +++++
 ld/ldlang.c                                   | 26 ++++++++++++++
 ld/ldlang.h                                   |  2 ++
 ld/ldlex.h                                    |  1 +
 ld/lexsup.c                                   |  7 ++++
 .../ld-undefined/export-dynamic-symbol-1.d    |  8 +++++
 .../ld-undefined/export-dynamic-symbol.exp    | 35 +++++++++++++++++++
 7 files changed, 87 insertions(+)
 create mode 100644 ld/testsuite/ld-undefined/export-dynamic-symbol-1.d
 create mode 100644 ld/testsuite/ld-undefined/export-dynamic-symbol.exp

diff --git a/ld/ld.texi b/ld/ld.texi
index 4dc78e65fa..b3dc95f314 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -569,6 +569,14 @@ Note that this option is specific to ELF targeted ports.  PE targets
 support a similar function to export all symbols from a DLL or EXE; see
 the description of @samp{--export-all-symbols} below.
 
+@kindex --export-dynamic-symbol=@var{symbol}
+@cindex export dynamic symbol
+@item --export-dynamic-symbol=@var{symbol}
+Specify a symbol that should be added to the dynamic symbol table.
+Additionally, force @var{symbol} to be entered in the output file as an
+undefined symbol.  Doing this may, for example, trigger linking of additional
+modules from archives.
+
 @ifclear SingleFormat
 @cindex big-endian objects
 @cindex endianness
diff --git a/ld/ldlang.c b/ld/ldlang.c
index b2cdb3603a..e7ecdfeaf0 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -3910,6 +3910,26 @@ lang_place_undefineds (void)
     insert_undefined (ptr->name);
 }
 
+static struct bfd_sym_chain export_dynamic_symbol_list = { NULL, NULL };
+
+void
+ldlang_add_export_dynamic_symbol (const char *const name)
+{
+  struct bfd_sym_chain *sym;
+  sym = stat_alloc (sizeof (*sym));
+  sym->name = xstrdup (name);
+  sym->next = export_dynamic_symbol_list.next;
+  export_dynamic_symbol_list.next = sym;
+}
+
+static void
+lang_place_export_dynamic_symbols (void)
+{
+  struct bfd_sym_chain *sym;
+  for (sym = export_dynamic_symbol_list.next; sym != NULL; sym = sym->next)
+    insert_undefined (sym->name);
+}
+
 /* Structure used to build the list of symbols that the user has required
    be defined.  */
 
@@ -7795,6 +7815,10 @@ void
 lang_process (void)
 {
   /* Finalize dynamic list.  */
+  struct bfd_sym_chain *sym;
+  for (sym = export_dynamic_symbol_list.next; sym != NULL; sym = sym->next)
+    lang_append_dynamic_list (
+        lang_new_vers_pattern (NULL, sym->name, NULL, FALSE));
   if (link_info.dynamic_list)
     lang_finalize_version_expr_head (&link_info.dynamic_list->head);
 
@@ -7808,6 +7832,8 @@ lang_process (void)
 
   /* Add to the hash table all undefineds on the command line.  */
   lang_place_undefineds ();
+  /* Add --export-dynamic-symbol symbols to the hash table.  */
+  lang_place_export_dynamic_symbols ();
 
   if (!bfd_section_already_linked_table_init ())
     einfo (_("%F%P: can not create hash table: %E\n"));
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 2aa3930f95..8c004b173c 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -606,6 +606,8 @@ extern lang_output_section_statement_type *next_matching_output_section_statemen
   (lang_output_section_statement_type *, int);
 extern void ldlang_add_undef
   (const char *const, bfd_boolean);
+extern void ldlang_add_export_dynamic_symbol
+  (const char *const);
 extern void ldlang_add_require_defined
   (const char *const);
 extern void lang_add_output_format
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 22b928d2d9..70f2da5636 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -81,6 +81,7 @@ enum option_values
   OPTION_DYNAMIC_LIST_CPP_NEW,
   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
   OPTION_DYNAMIC_LIST_DATA,
+  OPTION_EXPORT_DYNAMIC_SYMBOL,
   OPTION_WARN_COMMON,
   OPTION_WARN_CONSTRUCTORS,
   OPTION_WARN_FATAL,
diff --git a/ld/lexsup.c b/ld/lexsup.c
index d1955b9afa..0a0c2f2873 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -504,6 +504,8 @@ static const struct ld_option ld_options[] =
     '\0', NULL, N_("Use C++ typeinfo dynamic list"), TWO_DASHES },
   { {"dynamic-list", required_argument, NULL, OPTION_DYNAMIC_LIST},
     '\0', N_("FILE"), N_("Read dynamic list"), TWO_DASHES },
+  { {"export-dynamic-symbol", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL},
+    '\0', N_("SYMBOL"), N_("Read dynamic list"), TWO_DASHES },
   { {"warn-common", no_argument, NULL, OPTION_WARN_COMMON},
     '\0', NULL, N_("Warn about duplicate common symbols"), TWO_DASHES },
   { {"warn-constructors", no_argument, NULL, OPTION_WARN_CONSTRUCTORS},
@@ -1425,6 +1427,11 @@ parse_args (unsigned argc, char **argv)
 	  if (opt_symbolic == symbolic)
 	    opt_symbolic = symbolic_unset;
 	  break;
+	case OPTION_EXPORT_DYNAMIC_SYMBOL:
+	  ldlang_add_export_dynamic_symbol (optarg);
+	  if (opt_dynamic_list != dynamic_list_data)
+	    opt_dynamic_list = dynamic_list;
+	  break;
 	case OPTION_WARN_COMMON:
 	  config.warn_common = TRUE;
 	  break;
diff --git a/ld/testsuite/ld-undefined/export-dynamic-symbol-1.d b/ld/testsuite/ld-undefined/export-dynamic-symbol-1.d
new file mode 100644
index 0000000000..768bf0abd6
--- /dev/null
+++ b/ld/testsuite/ld-undefined/export-dynamic-symbol-1.d
@@ -0,0 +1,8 @@
+#name: --export-dynamic-symbol foo archive
+#source: require-defined.s
+#ld: -pie --export-dynamic-symbol foo tmpdir/libentry.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-undefined/export-dynamic-symbol.exp b/ld/testsuite/ld-undefined/export-dynamic-symbol.exp
new file mode 100644
index 0000000000..247ccf2660
--- /dev/null
+++ b/ld/testsuite/ld-undefined/export-dynamic-symbol.exp
@@ -0,0 +1,35 @@
+# Expect script for ld --export-dynamic-symbol tests
+#   Copyright (C) 2020 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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.
+#
+
+set build_tests {
+  {"Build libentry.a"
+   "" "" ""
+   {entry.s} {} "libentry.a"}
+}
+
+run_ld_link_tests $build_tests
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/export-dynamic-symbol-*.d]]
+foreach t $test_list {
+    # We need to strip the ".d", but can leave the dirname.
+    verbose [file rootname $t]
+    run_dump_test [file rootname $t]
+}
-- 
2.26.2.526.g744177e7f7-goog



More information about the Binutils mailing list