public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* V2 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list
@ 2020-05-23 14:47 H.J. Lu
  2020-05-23 18:29 ` Fangrui Song
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2020-05-23 14:47 UTC (permalink / raw)
  To: binutils; +Cc: Fangrui Song

From: Fangrui Song <maskray@google.com>

--export-dynamic-symbol-list is like a dynamic list, but without
the symbolic property for unspecified symbols.

When creating an executable, --export-dynamic-symbol-list is treated
like --dynamic-list.

When creating a shared library, it is treated like --dynamic-list if
-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
that references to matched symbols will not be bound to the definitions
within the shared library.

2020-05-XX  Fangrui Song  <maskray@google.com>
	    H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/25910
	* NEWS: Mention --export-dynamic-symbol[-list].
	* ld.texi: Document --export-dynamic-symbol[-list].
	* ldgram.y: Pass current_dynamic_list_p to
	lang_append_dynamic_list.
	* ldlang.c (current_dynamic_list_p): New.
	(ang_append_dynamic_list): Updated to take a pointer to
	struct bfd_elf_dynamic_list * argument instead of using
	link_info.dynamic_list.
	(lang_append_dynamic_list_cpp_typeinfo): Pass
	&link_info.dynamic_list to ang_append_dynamic_list.
	(lang_append_dynamic_list_cpp_new): Likewise.
	* ldlang.h (current_dynamic_list_p): New.
	(lang_append_dynamic_list): Add a pointer to
	struct bfd_elf_dynamic_list * argument.
	* ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
	* lexsup.c (ld_options): Add entries for
	OPTION_EXPORT_DYNAMIC_SYMBOL and
	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
	(parse_args): Handle --export-dynamic-symbol and
	--export-dynamic-symbol-list.
	* testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
	* testsuite/ld-dynamic/export-dynamic-symbol.s: New.
	* testsuite/ld-dynamic/foo-bar.list: New.
	* testsuite/ld-dynamic/foo.list: New.
	* testsuite/ld-dynamic/foo.s: New.
	* testsuite/ld-dynamic/fstar.list: New.
	* testsuite/ld-elf/dlempty.list: New.
	* testsuite/ld-elf/shared.exp: Add tests for
	--export-dynamic-symbol and --export-dynamic-symbol-list.
---
 ld/NEWS                                       |  3 +
 ld/ld.texi                                    | 18 +++++
 ld/ldgram.y                                   |  2 +-
 ld/ldlang.c                                   | 16 ++--
 ld/ldlang.h                                   |  5 +-
 ld/ldlex.h                                    |  2 +
 ld/lexsup.c                                   | 75 +++++++++++++++++++
 .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
 .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
 .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 ++
 .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
 .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
 .../export-dynamic-symbol-list-glob.d         |  8 ++
 .../ld-dynamic/export-dynamic-symbol.exp      | 39 ++++++++++
 .../ld-dynamic/export-dynamic-symbol.s        |  9 +++
 ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
 ld/testsuite/ld-dynamic/foo.list              |  1 +
 ld/testsuite/ld-dynamic/foo.s                 |  4 +
 ld/testsuite/ld-dynamic/fstar.list            |  1 +
 ld/testsuite/ld-elf/dlempty.list              |  3 +
 ld/testsuite/ld-elf/shared.exp                | 36 +++++++++
 21 files changed, 258 insertions(+), 9 deletions(-)
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
 create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
 create mode 100644 ld/testsuite/ld-dynamic/foo.list
 create mode 100644 ld/testsuite/ld-dynamic/foo.s
 create mode 100644 ld/testsuite/ld-dynamic/fstar.list
 create mode 100644 ld/testsuite/ld-elf/dlempty.list

diff --git a/ld/NEWS b/ld/NEWS
index 9f5bbe51cf..870c480bde 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add ELF linker command-line options, --export-dynamic-symbol and
+  --export-dynamic-symbol-list, to make symbols dynamic.
+
 * Add command-line options --enable-non-contiguous-regions and
   --enable-non-contiguous-regions-warnings.
 
diff --git a/ld/ld.texi b/ld/ld.texi
index 4dc78e65fa..92e47c6324 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -569,6 +569,24 @@ 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{glob}
+@cindex export dynamic symbol
+@item --export-dynamic-symbol=@var{glob}
+When creating a dynamically linked executable, symbols matching
+@var{glob} will be added to the dynamic symbol table. When creating a
+shared library, references to symbols matching @var{glob} will not be
+bound to the definitions within the shared library. This option is a
+no-op when creating a shared library and @samp{-Bsymbolic} or
+@samp{--dynamic-list} are not specified. This option is only meaningful
+on ELF platforms which support shared libraries.
+
+@kindex --export-dynamic-symbol-list=@var{file}
+@cindex export dynamic symbol list
+@item --export-dynamic-symbol-list=@var{file}
+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
+The format of the file is the same as the version node without
+scope and node name.  See @ref{VERSION} for more information.
+
 @ifclear SingleFormat
 @cindex big-endian objects
 @cindex endianness
diff --git a/ld/ldgram.y b/ld/ldgram.y
index df5c035c03..36845c4c30 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -1313,7 +1313,7 @@ dynamic_list_node:
 dynamic_list_tag:
 		vers_defns ';'
 		{
-		  lang_append_dynamic_list ($1);
+		  lang_append_dynamic_list (current_dynamic_list_p, $1);
 		}
 	;
 
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 3d653d460d..14a6a577d2 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
    lang_statement_union).  */
 lang_statement_list_type input_file_chain;
 static const char *current_input_file;
+struct bfd_elf_dynamic_list **current_dynamic_list_p;
 struct bfd_sym_chain entry_symbol = { NULL, NULL };
 const char *entry_section = ".text";
 struct lang_input_statement_flags input_flags;
@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
 /* Append the list of dynamic symbols to the existing one.  */
 
 void
-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
+			  struct bfd_elf_version_expr *dynamic)
 {
-  if (link_info.dynamic_list)
+  if (*list_p)
     {
       struct bfd_elf_version_expr *tail;
       for (tail = dynamic; tail->next != NULL; tail = tail->next)
 	;
-      tail->next = link_info.dynamic_list->head.list;
-      link_info.dynamic_list->head.list = dynamic;
+      tail->next = (*list_p)->head.list;
+      (*list_p)->head.list = dynamic;
     }
   else
     {
@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
       d->head.list = dynamic;
       d->match = lang_vers_match;
-      link_info.dynamic_list = d;
+      *list_p = d;
     }
 }
 
@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
 				     FALSE);
 
-  lang_append_dynamic_list (dynamic);
+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
 }
 
 /* Append the list of C++ operator new and delete dynamic symbols to the
@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
 				     FALSE);
 
-  lang_append_dynamic_list (dynamic);
+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
 }
 
 /* Scan a space and/or comma separated string of features.  */
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 3018c3e2ba..529ccd1585 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
 extern lang_statement_list_type file_chain;
 extern lang_statement_list_type input_file_chain;
 
+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
+
 extern int lang_statement_iteration;
 extern struct asneeded_minfo **asneeded_list_tail;
 
@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
   (struct bfd_elf_version_deps *, const char *);
 extern void lang_register_vers_node
   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
+				      struct bfd_elf_version_expr *);
 extern void lang_append_dynamic_list_cpp_typeinfo (void);
 extern void lang_append_dynamic_list_cpp_new (void);
 extern void lang_add_unique
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 22b928d2d9..2c8d043a09 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -81,6 +81,8 @@ enum option_values
   OPTION_DYNAMIC_LIST_CPP_NEW,
   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
   OPTION_DYNAMIC_LIST_DATA,
+  OPTION_EXPORT_DYNAMIC_SYMBOL,
+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
   OPTION_WARN_COMMON,
   OPTION_WARN_CONSTRUCTORS,
   OPTION_WARN_FATAL,
diff --git a/ld/lexsup.c b/ld/lexsup.c
index fe9526b527..2bac1631d6 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
@@ -581,6 +585,7 @@ parse_args (unsigned argc, char **argv)
     dynamic_list_data,
     dynamic_list
   } opt_dynamic_list = dynamic_list_unset;
+  struct bfd_elf_dynamic_list *export_list = NULL;
 
   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
   longopts = (struct option *)
@@ -1418,6 +1423,7 @@ parse_args (unsigned argc, char **argv)
 	    ldfile_open_command_file (optarg);
 	    saved_script_handle = hold_script_handle;
 	    parser_input = input_dynamic_list;
+	    current_dynamic_list_p = &link_info.dynamic_list;
 	    yyparse ();
 	  }
 	  if (opt_dynamic_list != dynamic_list_data)
@@ -1425,6 +1431,29 @@ parse_args (unsigned argc, char **argv)
 	  if (opt_symbolic == symbolic)
 	    opt_symbolic = symbolic_unset;
 	  break;
+	case OPTION_EXPORT_DYNAMIC_SYMBOL:
+	  {
+	    struct bfd_elf_version_expr *expr
+	      = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
+				       FALSE);
+	    lang_append_dynamic_list (&export_list, expr);
+          }
+	  break;
+	case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
+	  /* This option indicates a small script that only specifies
+	     an export list.  Read it, but don't assume that we've
+	     seen a linker script.  */
+	  {
+	    FILE *hold_script_handle;
+
+	    hold_script_handle = saved_script_handle;
+	    ldfile_open_command_file (optarg);
+	    saved_script_handle = hold_script_handle;
+	    parser_input = input_dynamic_list;
+	    current_dynamic_list_p = &export_list;
+	    yyparse ();
+	  }
+	  break;
 	case OPTION_WARN_COMMON:
 	  config.warn_common = TRUE;
 	  break;
@@ -1632,6 +1661,52 @@ parse_args (unsigned argc, char **argv)
       && command_line.check_section_addresses < 0)
     command_line.check_section_addresses = 0;
 
+  if (export_list && !bfd_link_relocatable (&link_info))
+    {
+      struct bfd_elf_version_expr *head = export_list->head.list;
+      struct bfd_elf_version_expr *next;
+
+      /* For --export-dynamic-symbol[-list]:
+	 1. When building executable, treat like --dynamic-list.
+	 2. When building shared object:
+	    a. If -Bsymbolic or --dynamic-list are used, treat like
+	       --dynamic-list.
+	    b. Otherwise, ignored.
+       */
+      bfd_boolean kept = (bfd_link_executable (&link_info)
+			  || opt_symbolic != symbolic_unset
+			  || opt_dynamic_list != dynamic_list_unset);
+
+      if (kept)
+	{
+	  /* Append the export list to link_info.dynamic_list.  */
+	  if (link_info.dynamic_list)
+	    {
+	      for (next = head; next->next != NULL; next = next->next)
+		;
+	      next->next = link_info.dynamic_list->head.list;
+	      link_info.dynamic_list->head.list = head;
+	    }
+	  else
+	    link_info.dynamic_list = export_list;
+
+	  if (opt_dynamic_list != dynamic_list_data)
+	    opt_dynamic_list = dynamic_list;
+	  if (opt_symbolic == symbolic)
+	    opt_symbolic = symbolic_unset;
+	}
+      else
+	{
+	  /* Free the export list.  */
+	  for (; head->next != NULL; head = next)
+	    {
+	      next = head->next;
+	      free (head);
+	    }
+	  free (export_list);
+	}
+    }
+
   /* -Bsymbolic and -Bsymbols-functions are for shared library output.  */
   if (bfd_link_dll (&link_info))
     switch (opt_symbolic)
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
new file mode 100644
index 0000000000..c1dd4e2f55
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
@@ -0,0 +1,9 @@
+#name: --export-dynamic-symbol foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie --export-dynamic-symbol foo tmpdir/libfoo.a
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
new file mode 100644
index 0000000000..7ec4eed3ed
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
@@ -0,0 +1,9 @@
+#name: -u --export-dynamic-symbol foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol foo --export-dynamic-symbol=bar tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +bar
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
new file mode 100644
index 0000000000..05a6e15b3b
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
@@ -0,0 +1,8 @@
+#name: -u --export-dynamic-symbol f* archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol f* tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
new file mode 100644
index 0000000000..aa1b8839e6
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
@@ -0,0 +1,9 @@
+#name: --export-dynamic-symbol-list foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie --export-dynamic-symbol-list foo.list tmpdir/libfoo.a
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
new file mode 100644
index 0000000000..367a07c1bb
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
@@ -0,0 +1,9 @@
+#name: -u --export-dynamic-symbol-list foo bar archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol-list foo-bar.list tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +bar
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
new file mode 100644
index 0000000000..f0e3427306
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
@@ -0,0 +1,8 @@
+#name: -u --export-dynamic-symbol-list fstar archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol-list fstar.list tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
new file mode 100644
index 0000000000..d0b4bc4eb0
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
@@ -0,0 +1,39 @@
+# 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.
+#
+
+if ![is_elf_format] {
+    return
+}
+
+set build_tests {
+  {"Build libfoo.a"
+   "" "" ""
+   {foo.s} {} "libfoo.a"}
+}
+
+run_ld_link_tests $build_tests
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/export-dynamic-symbol-*.d]]
+foreach test_file $test_list {
+    set test_name [file rootname $test_file]
+    verbose $test_name
+    run_dump_test $test_name
+}
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
new file mode 100644
index 0000000000..4b1b8ebd5c
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
@@ -0,0 +1,9 @@
+	.text
+	.global _start
+_start:
+	.word 0
+
+	.section .text.1, "ax"
+	.global bar
+bar:
+	.word 0
diff --git a/ld/testsuite/ld-dynamic/foo-bar.list b/ld/testsuite/ld-dynamic/foo-bar.list
new file mode 100644
index 0000000000..87732e1de4
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo-bar.list
@@ -0,0 +1 @@
+{ foo; bar; };
diff --git a/ld/testsuite/ld-dynamic/foo.list b/ld/testsuite/ld-dynamic/foo.list
new file mode 100644
index 0000000000..f89f569438
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo.list
@@ -0,0 +1 @@
+{ foo; };
diff --git a/ld/testsuite/ld-dynamic/foo.s b/ld/testsuite/ld-dynamic/foo.s
new file mode 100644
index 0000000000..4a70181776
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo.s
@@ -0,0 +1,4 @@
+	.text
+	.globl foo
+foo:
+	.byte 0
diff --git a/ld/testsuite/ld-dynamic/fstar.list b/ld/testsuite/ld-dynamic/fstar.list
new file mode 100644
index 0000000000..330d1dd2b8
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/fstar.list
@@ -0,0 +1 @@
+{ f*; };
diff --git a/ld/testsuite/ld-elf/dlempty.list b/ld/testsuite/ld-elf/dlempty.list
new file mode 100644
index 0000000000..9b3884b10e
--- /dev/null
+++ b/ld/testsuite/ld-elf/dlempty.list
@@ -0,0 +1,3 @@
+{
+  empty;
+};
diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
index 3366430515..cb25ad19ff 100644
--- a/ld/testsuite/ld-elf/shared.exp
+++ b/ld/testsuite/ld-elf/shared.exp
@@ -598,6 +598,24 @@ set build_tests {
   {"Build libdl2c.so with --dynamic-list-data and dl2xxx.list"
    "-shared -Wl,--dynamic-list-data,--dynamic-list=dl2xxx.list" "-fPIC"
    {dl2.c dl2xxx.c} {} "libdl2c.so"}
+  {"Build libdl2d.so with --export-dynamic-symbol=foo"
+   "-shared -Wl,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2d.so"}
+  {"Build libdl2e.so with --dynamic-list=dlempty.list and --export-dynamic-symbol=foo"
+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2e.so"}
+  {"Build libdl2f.so with --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2f.so"}
+  {"Build libdl2g.so with --dynamic-list=dlempty.list and --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2g.so"}
+  {"Build libdl2h.so with -Bsymbolic and --export-dynamic-symbol=foo"
+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2h.so"}
+  {"Build libdl2i.so with -Bsymbolic and --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2i.so"}
   {"Build libdl4a.so with --dynamic-list=dl4.list"
    "-shared -Wl,--dynamic-list=dl4.list" "-fPIC"
    {dl4.c dl4xxx.c} {} "libdl4a.so"}
@@ -874,6 +892,24 @@ set run_tests [list \
     [list "Run with libdl2c.so" \
      "-Wl,--no-as-needed tmpdir/libdl2c.so" "" \
      {dl2main.c} "dl2c" "dl2b.out" ] \
+    [list "Run with libdl2d.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2d.so" "" \
+     {dl2main.c} "dl2d" "dl2b.out" ] \
+    [list "Run with libdl2e.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2e.so" "" \
+     {dl2main.c} "dl2e" "dl2a.out" ] \
+    [list "Run with libdl2f.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2f.so" "" \
+     {dl2main.c} "dl2f" "dl2b.out" ] \
+    [list "Run with libdl2g.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2g.so" "" \
+     {dl2main.c} "dl2g" "dl2a.out" ] \
+    [list "Run with libdl2h.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2h.so" "" \
+     {dl2main.c} "dl2h" "dl2a.out" ] \
+    [list "Run with libdl2i.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2i.so" "" \
+     {dl2main.c} "dl2i" "dl2a.out" ] \
     [list "Run with libdl4a.so" \
      "-Wl,--no-as-needed tmpdir/libdl4a.so" "" \
      {dl4main.c} "dl4a" "dl4a.out" ] \
-- 
2.26.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: V2 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list
  2020-05-23 14:47 V2 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list H.J. Lu
@ 2020-05-23 18:29 ` Fangrui Song
  2020-05-23 19:50   ` V3 " H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: Fangrui Song @ 2020-05-23 18:29 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

On 2020-05-23, H.J. Lu wrote:
>From: Fangrui Song <maskray@google.com>
>
>--export-dynamic-symbol-list is like a dynamic list, but without
>the symbolic property for unspecified symbols.
>
>When creating an executable, --export-dynamic-symbol-list is treated
>like --dynamic-list.
>
>When creating a shared library, it is treated like --dynamic-list if
>-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
>that references to matched symbols will not be bound to the definitions
>within the shared library.
>
>2020-05-XX  Fangrui Song  <maskray@google.com>
>	    H.J. Lu  <hongjiu.lu@intel.com>
>
>	PR ld/25910
>	* NEWS: Mention --export-dynamic-symbol[-list].
>	* ld.texi: Document --export-dynamic-symbol[-list].
>	* ldgram.y: Pass current_dynamic_list_p to
>	lang_append_dynamic_list.
>	* ldlang.c (current_dynamic_list_p): New.
>	(ang_append_dynamic_list): Updated to take a pointer to
>	struct bfd_elf_dynamic_list * argument instead of using
>	link_info.dynamic_list.
>	(lang_append_dynamic_list_cpp_typeinfo): Pass
>	&link_info.dynamic_list to ang_append_dynamic_list.
>	(lang_append_dynamic_list_cpp_new): Likewise.
>	* ldlang.h (current_dynamic_list_p): New.
>	(lang_append_dynamic_list): Add a pointer to
>	struct bfd_elf_dynamic_list * argument.
>	* ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
>	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
>	* lexsup.c (ld_options): Add entries for
>	OPTION_EXPORT_DYNAMIC_SYMBOL and
>	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
>	(parse_args): Handle --export-dynamic-symbol and
>	--export-dynamic-symbol-list.
>	* testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
>	* testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
>	* testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
>	* testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
>	* testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
>	* testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
>	* testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
>	* testsuite/ld-dynamic/export-dynamic-symbol.s: New.
>	* testsuite/ld-dynamic/foo-bar.list: New.
>	* testsuite/ld-dynamic/foo.list: New.
>	* testsuite/ld-dynamic/foo.s: New.
>	* testsuite/ld-dynamic/fstar.list: New.
>	* testsuite/ld-elf/dlempty.list: New.
>	* testsuite/ld-elf/shared.exp: Add tests for
>	--export-dynamic-symbol and --export-dynamic-symbol-list.
>---
> ld/NEWS                                       |  3 +
> ld/ld.texi                                    | 18 +++++
> ld/ldgram.y                                   |  2 +-
> ld/ldlang.c                                   | 16 ++--
> ld/ldlang.h                                   |  5 +-
> ld/ldlex.h                                    |  2 +
> ld/lexsup.c                                   | 75 +++++++++++++++++++
> .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
> .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
> .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 ++
> .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
> .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
> .../export-dynamic-symbol-list-glob.d         |  8 ++
> .../ld-dynamic/export-dynamic-symbol.exp      | 39 ++++++++++
> .../ld-dynamic/export-dynamic-symbol.s        |  9 +++
> ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
> ld/testsuite/ld-dynamic/foo.list              |  1 +
> ld/testsuite/ld-dynamic/foo.s                 |  4 +
> ld/testsuite/ld-dynamic/fstar.list            |  1 +
> ld/testsuite/ld-elf/dlempty.list              |  3 +
> ld/testsuite/ld-elf/shared.exp                | 36 +++++++++
> 21 files changed, 258 insertions(+), 9 deletions(-)
> create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
> create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
> create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
> create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
> create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
> create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
> create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
> create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
> create mode 100644 ld/testsuite/ld-dynamic/foo.list
> create mode 100644 ld/testsuite/ld-dynamic/foo.s
> create mode 100644 ld/testsuite/ld-dynamic/fstar.list
> create mode 100644 ld/testsuite/ld-elf/dlempty.list
>
>diff --git a/ld/NEWS b/ld/NEWS
>index 9f5bbe51cf..870c480bde 100644
>--- a/ld/NEWS
>+++ b/ld/NEWS
>@@ -1,5 +1,8 @@
> -*- text -*-
>
>+* Add ELF linker command-line options, --export-dynamic-symbol and
>+  --export-dynamic-symbol-list, to make symbols dynamic.
>+
> * Add command-line options --enable-non-contiguous-regions and
>   --enable-non-contiguous-regions-warnings.
>
>diff --git a/ld/ld.texi b/ld/ld.texi
>index 4dc78e65fa..92e47c6324 100644
>--- a/ld/ld.texi
>+++ b/ld/ld.texi
>@@ -569,6 +569,24 @@ 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{glob}
>+@cindex export dynamic symbol
>+@item --export-dynamic-symbol=@var{glob}
>+When creating a dynamically linked executable, symbols matching
>+@var{glob} will be added to the dynamic symbol table. When creating a
>+shared library, references to symbols matching @var{glob} will not be
>+bound to the definitions within the shared library. This option is a
>+no-op when creating a shared library and @samp{-Bsymbolic} or
>+@samp{--dynamic-list} are not specified. This option is only meaningful
>+on ELF platforms which support shared libraries.

Is --export-dynamic-symbol still effective for -shared?
I think either way is ok.

>+@kindex --export-dynamic-symbol-list=@var{file}
>+@cindex export dynamic symbol list
>+@item --export-dynamic-symbol-list=@var{file}
>+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
>+The format of the file is the same as the version node without
>+scope and node name.  See @ref{VERSION} for more information.
>+
> @ifclear SingleFormat
> @cindex big-endian objects
> @cindex endianness
>diff --git a/ld/ldgram.y b/ld/ldgram.y
>index df5c035c03..36845c4c30 100644
>--- a/ld/ldgram.y
>+++ b/ld/ldgram.y
>@@ -1313,7 +1313,7 @@ dynamic_list_node:
> dynamic_list_tag:
> 		vers_defns ';'
> 		{
>-		  lang_append_dynamic_list ($1);
>+		  lang_append_dynamic_list (current_dynamic_list_p, $1);
> 		}
> 	;
>
>diff --git a/ld/ldlang.c b/ld/ldlang.c
>index 3d653d460d..14a6a577d2 100644
>--- a/ld/ldlang.c
>+++ b/ld/ldlang.c
>@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
>    lang_statement_union).  */
> lang_statement_list_type input_file_chain;
> static const char *current_input_file;
>+struct bfd_elf_dynamic_list **current_dynamic_list_p;
> struct bfd_sym_chain entry_symbol = { NULL, NULL };
> const char *entry_section = ".text";
> struct lang_input_statement_flags input_flags;
>@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
> /* Append the list of dynamic symbols to the existing one.  */
>
> void
>-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
>+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
>+			  struct bfd_elf_version_expr *dynamic)
> {
>-  if (link_info.dynamic_list)
>+  if (*list_p)
>     {
>       struct bfd_elf_version_expr *tail;
>       for (tail = dynamic; tail->next != NULL; tail = tail->next)
> 	;
>-      tail->next = link_info.dynamic_list->head.list;
>-      link_info.dynamic_list->head.list = dynamic;
>+      tail->next = (*list_p)->head.list;
>+      (*list_p)->head.list = dynamic;
>     }
>   else
>     {
>@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
>       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
>       d->head.list = dynamic;
>       d->match = lang_vers_match;
>-      link_info.dynamic_list = d;
>+      *list_p = d;
>     }
> }
>
>@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
>     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
> 				     FALSE);
>
>-  lang_append_dynamic_list (dynamic);
>+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
> }
>
> /* Append the list of C++ operator new and delete dynamic symbols to the
>@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
>     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
> 				     FALSE);
>
>-  lang_append_dynamic_list (dynamic);
>+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
> }
>
> /* Scan a space and/or comma separated string of features.  */
>diff --git a/ld/ldlang.h b/ld/ldlang.h
>index 3018c3e2ba..529ccd1585 100644
>--- a/ld/ldlang.h
>+++ b/ld/ldlang.h
>@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
> extern lang_statement_list_type file_chain;
> extern lang_statement_list_type input_file_chain;
>
>+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
>+
> extern int lang_statement_iteration;
> extern struct asneeded_minfo **asneeded_list_tail;
>
>@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
>   (struct bfd_elf_version_deps *, const char *);
> extern void lang_register_vers_node
>   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
>-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
>+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
>+				      struct bfd_elf_version_expr *);
> extern void lang_append_dynamic_list_cpp_typeinfo (void);
> extern void lang_append_dynamic_list_cpp_new (void);
> extern void lang_add_unique
>diff --git a/ld/ldlex.h b/ld/ldlex.h
>index 22b928d2d9..2c8d043a09 100644
>--- a/ld/ldlex.h
>+++ b/ld/ldlex.h
>@@ -81,6 +81,8 @@ enum option_values
>   OPTION_DYNAMIC_LIST_CPP_NEW,
>   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
>   OPTION_DYNAMIC_LIST_DATA,
>+  OPTION_EXPORT_DYNAMIC_SYMBOL,
>+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
>   OPTION_WARN_COMMON,
>   OPTION_WARN_CONSTRUCTORS,
>   OPTION_WARN_FATAL,
>diff --git a/ld/lexsup.c b/ld/lexsup.c
>index fe9526b527..2bac1631d6 100644
>--- a/ld/lexsup.c
>+++ b/ld/lexsup.c
>@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
>+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
>+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
>@@ -581,6 +585,7 @@ parse_args (unsigned argc, char **argv)
>     dynamic_list_data,
>     dynamic_list
>   } opt_dynamic_list = dynamic_list_unset;
>+  struct bfd_elf_dynamic_list *export_list = NULL;
>
>   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
>   longopts = (struct option *)
>@@ -1418,6 +1423,7 @@ parse_args (unsigned argc, char **argv)
> 	    ldfile_open_command_file (optarg);
> 	    saved_script_handle = hold_script_handle;
> 	    parser_input = input_dynamic_list;
>+	    current_dynamic_list_p = &link_info.dynamic_list;
> 	    yyparse ();
> 	  }
> 	  if (opt_dynamic_list != dynamic_list_data)
>@@ -1425,6 +1431,29 @@ parse_args (unsigned argc, char **argv)
> 	  if (opt_symbolic == symbolic)
> 	    opt_symbolic = symbolic_unset;
> 	  break;
>+	case OPTION_EXPORT_DYNAMIC_SYMBOL:
>+	  {
>+	    struct bfd_elf_version_expr *expr
>+	      = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
>+				       FALSE);
>+	    lang_append_dynamic_list (&export_list, expr);
>+          }
>+	  break;
>+	case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
>+	  /* This option indicates a small script that only specifies
>+	     an export list.  Read it, but don't assume that we've
>+	     seen a linker script.  */
>+	  {
>+	    FILE *hold_script_handle;
>+
>+	    hold_script_handle = saved_script_handle;
>+	    ldfile_open_command_file (optarg);
>+	    saved_script_handle = hold_script_handle;
>+	    parser_input = input_dynamic_list;
>+	    current_dynamic_list_p = &export_list;
>+	    yyparse ();
>+	  }
>+	  break;
> 	case OPTION_WARN_COMMON:
> 	  config.warn_common = TRUE;
> 	  break;
>@@ -1632,6 +1661,52 @@ parse_args (unsigned argc, char **argv)
>       && command_line.check_section_addresses < 0)
>     command_line.check_section_addresses = 0;
>
>+  if (export_list && !bfd_link_relocatable (&link_info))
>+    {
>+      struct bfd_elf_version_expr *head = export_list->head.list;
>+      struct bfd_elf_version_expr *next;
>+
>+      /* For --export-dynamic-symbol[-list]:
>+	 1. When building executable, treat like --dynamic-list.
>+	 2. When building shared object:
>+	    a. If -Bsymbolic or --dynamic-list are used, treat like
>+	       --dynamic-list.
>+	    b. Otherwise, ignored.
>+       */
>+      bfd_boolean kept = (bfd_link_executable (&link_info)
>+			  || opt_symbolic != symbolic_unset
>+			  || opt_dynamic_list != dynamic_list_unset);
>+
>+      if (kept)
>+	{
>+	  /* Append the export list to link_info.dynamic_list.  */
>+	  if (link_info.dynamic_list)
>+	    {
>+	      for (next = head; next->next != NULL; next = next->next)
>+		;
>+	      next->next = link_info.dynamic_list->head.list;
>+	      link_info.dynamic_list->head.list = head;
>+	    }
>+	  else
>+	    link_info.dynamic_list = export_list;
>+
>+	  if (opt_dynamic_list != dynamic_list_data)
>+	    opt_dynamic_list = dynamic_list;
>+	  if (opt_symbolic == symbolic)
>+	    opt_symbolic = symbolic_unset;

The interaction with -Bsymbolic appears to be more complex now.
I think users will pretty much avoid the combination of -Bsymbolic and
(--dynamic-list or --export-dynamic-symbol or --export-dynamic-symbol-list).

So I beg for a re-consideration of
https://sourceware.org/bugzilla/show_bug.cgi?id=26018
https://sourceware.org/pipermail/binutils/2020-May/111223.html

>+	}
>+      else
>+	{
>+	  /* Free the export list.  */
>+	  for (; head->next != NULL; head = next)
>+	    {
>+	      next = head->next;
>+	      free (head);
>+	    }
>+	  free (export_list);
>+	}
>+    }
>+
>   /* -Bsymbolic and -Bsymbols-functions are for shared library output.  */
>   if (bfd_link_dll (&link_info))
>     switch (opt_symbolic)
>diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
>new file mode 100644
>index 0000000000..c1dd4e2f55
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
>@@ -0,0 +1,9 @@
>+#name: --export-dynamic-symbol foo archive
>+#source: export-dynamic-symbol.s
>+#ld: -pie --export-dynamic-symbol foo tmpdir/libfoo.a
>+#nm: -n
>+
>+#failif
>+#...
>+[0-9a-f]+ T +foo
>+#...
>diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
>new file mode 100644
>index 0000000000..7ec4eed3ed
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
>@@ -0,0 +1,9 @@
>+#name: -u --export-dynamic-symbol foo archive
>+#source: export-dynamic-symbol.s
>+#ld: -pie -u foo --export-dynamic-symbol foo --export-dynamic-symbol=bar tmpdir/libfoo.a
>+#nm: -D
>+
>+#...
>+[0-9a-f]+ T +bar
>+[0-9a-f]+ T +foo
>+#...
>diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
>new file mode 100644
>index 0000000000..05a6e15b3b
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
>@@ -0,0 +1,8 @@
>+#name: -u --export-dynamic-symbol f* archive
>+#source: export-dynamic-symbol.s
>+#ld: -pie -u foo --export-dynamic-symbol f* tmpdir/libfoo.a
>+#nm: -D
>+
>+#...
>+[0-9a-f]+ T +foo
>+#...
>diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
>new file mode 100644
>index 0000000000..aa1b8839e6
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
>@@ -0,0 +1,9 @@
>+#name: --export-dynamic-symbol-list foo archive
>+#source: export-dynamic-symbol.s
>+#ld: -pie --export-dynamic-symbol-list foo.list tmpdir/libfoo.a
>+#nm: -n
>+
>+#failif
>+#...
>+[0-9a-f]+ T +foo
>+#...
>diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
>new file mode 100644
>index 0000000000..367a07c1bb
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
>@@ -0,0 +1,9 @@
>+#name: -u --export-dynamic-symbol-list foo bar archive
>+#source: export-dynamic-symbol.s
>+#ld: -pie -u foo --export-dynamic-symbol-list foo-bar.list tmpdir/libfoo.a
>+#nm: -D
>+
>+#...
>+[0-9a-f]+ T +bar
>+[0-9a-f]+ T +foo
>+#...
>diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
>new file mode 100644
>index 0000000000..f0e3427306
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
>@@ -0,0 +1,8 @@
>+#name: -u --export-dynamic-symbol-list fstar archive
>+#source: export-dynamic-symbol.s
>+#ld: -pie -u foo --export-dynamic-symbol-list fstar.list tmpdir/libfoo.a
>+#nm: -D
>+
>+#...
>+[0-9a-f]+ T +foo
>+#...
>diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
>new file mode 100644
>index 0000000000..d0b4bc4eb0
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
>@@ -0,0 +1,39 @@
>+# 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.
>+#
>+
>+if ![is_elf_format] {
>+    return
>+}
>+
>+set build_tests {
>+  {"Build libfoo.a"
>+   "" "" ""
>+   {foo.s} {} "libfoo.a"}
>+}
>+
>+run_ld_link_tests $build_tests
>+
>+set test_list [lsort [glob -nocomplain $srcdir/$subdir/export-dynamic-symbol-*.d]]
>+foreach test_file $test_list {
>+    set test_name [file rootname $test_file]
>+    verbose $test_name
>+    run_dump_test $test_name
>+}
>diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
>new file mode 100644
>index 0000000000..4b1b8ebd5c
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
>@@ -0,0 +1,9 @@
>+	.text
>+	.global _start
>+_start:
>+	.word 0
>+
>+	.section .text.1, "ax"
>+	.global bar
>+bar:
>+	.word 0
>diff --git a/ld/testsuite/ld-dynamic/foo-bar.list b/ld/testsuite/ld-dynamic/foo-bar.list
>new file mode 100644
>index 0000000000..87732e1de4
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/foo-bar.list
>@@ -0,0 +1 @@
>+{ foo; bar; };
>diff --git a/ld/testsuite/ld-dynamic/foo.list b/ld/testsuite/ld-dynamic/foo.list
>new file mode 100644
>index 0000000000..f89f569438
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/foo.list
>@@ -0,0 +1 @@
>+{ foo; };
>diff --git a/ld/testsuite/ld-dynamic/foo.s b/ld/testsuite/ld-dynamic/foo.s
>new file mode 100644
>index 0000000000..4a70181776
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/foo.s
>@@ -0,0 +1,4 @@
>+	.text
>+	.globl foo
>+foo:
>+	.byte 0
>diff --git a/ld/testsuite/ld-dynamic/fstar.list b/ld/testsuite/ld-dynamic/fstar.list
>new file mode 100644
>index 0000000000..330d1dd2b8
>--- /dev/null
>+++ b/ld/testsuite/ld-dynamic/fstar.list
>@@ -0,0 +1 @@
>+{ f*; };
>diff --git a/ld/testsuite/ld-elf/dlempty.list b/ld/testsuite/ld-elf/dlempty.list
>new file mode 100644
>index 0000000000..9b3884b10e
>--- /dev/null
>+++ b/ld/testsuite/ld-elf/dlempty.list
>@@ -0,0 +1,3 @@
>+{
>+  empty;
>+};
>diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
>index 3366430515..cb25ad19ff 100644
>--- a/ld/testsuite/ld-elf/shared.exp
>+++ b/ld/testsuite/ld-elf/shared.exp
>@@ -598,6 +598,24 @@ set build_tests {
>   {"Build libdl2c.so with --dynamic-list-data and dl2xxx.list"
>    "-shared -Wl,--dynamic-list-data,--dynamic-list=dl2xxx.list" "-fPIC"
>    {dl2.c dl2xxx.c} {} "libdl2c.so"}
>+  {"Build libdl2d.so with --export-dynamic-symbol=foo"
>+   "-shared -Wl,--export-dynamic-symbol=foo" "-fPIC"
>+   {dl2.c dl2xxx.c} {} "libdl2d.so"}
>+  {"Build libdl2e.so with --dynamic-list=dlempty.list and --export-dynamic-symbol=foo"
>+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol=foo" "-fPIC"
>+   {dl2.c dl2xxx.c} {} "libdl2e.so"}
>+  {"Build libdl2f.so with --export-dynamic-symbol-list=dl2.list"
>+   "-shared -Wl,--export-dynamic-symbol-list=dl2.list" "-fPIC"
>+   {dl2.c dl2xxx.c} {} "libdl2f.so"}
>+  {"Build libdl2g.so with --dynamic-list=dlempty.list and --export-dynamic-symbol-list=dl2.list"
>+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol-list=dl2.list" "-fPIC"
>+   {dl2.c dl2xxx.c} {} "libdl2g.so"}
>+  {"Build libdl2h.so with -Bsymbolic and --export-dynamic-symbol=foo"
>+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol=foo" "-fPIC"
>+   {dl2.c dl2xxx.c} {} "libdl2h.so"}
>+  {"Build libdl2i.so with -Bsymbolic and --export-dynamic-symbol-list=dl2.list"
>+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol-list=dl2.list" "-fPIC"
>+   {dl2.c dl2xxx.c} {} "libdl2i.so"}
>   {"Build libdl4a.so with --dynamic-list=dl4.list"
>    "-shared -Wl,--dynamic-list=dl4.list" "-fPIC"
>    {dl4.c dl4xxx.c} {} "libdl4a.so"}
>@@ -874,6 +892,24 @@ set run_tests [list \
>     [list "Run with libdl2c.so" \
>      "-Wl,--no-as-needed tmpdir/libdl2c.so" "" \
>      {dl2main.c} "dl2c" "dl2b.out" ] \
>+    [list "Run with libdl2d.so" \
>+     "-Wl,--no-as-needed tmpdir/libdl2d.so" "" \
>+     {dl2main.c} "dl2d" "dl2b.out" ] \
>+    [list "Run with libdl2e.so" \
>+     "-Wl,--no-as-needed tmpdir/libdl2e.so" "" \
>+     {dl2main.c} "dl2e" "dl2a.out" ] \
>+    [list "Run with libdl2f.so" \
>+     "-Wl,--no-as-needed tmpdir/libdl2f.so" "" \
>+     {dl2main.c} "dl2f" "dl2b.out" ] \
>+    [list "Run with libdl2g.so" \
>+     "-Wl,--no-as-needed tmpdir/libdl2g.so" "" \
>+     {dl2main.c} "dl2g" "dl2a.out" ] \
>+    [list "Run with libdl2h.so" \
>+     "-Wl,--no-as-needed tmpdir/libdl2h.so" "" \
>+     {dl2main.c} "dl2h" "dl2a.out" ] \
>+    [list "Run with libdl2i.so" \
>+     "-Wl,--no-as-needed tmpdir/libdl2i.so" "" \
>+     {dl2main.c} "dl2i" "dl2a.out" ] \
>     [list "Run with libdl4a.so" \
>      "-Wl,--no-as-needed tmpdir/libdl4a.so" "" \
>      {dl4main.c} "dl4a" "dl4a.out" ] \
>-- 
>2.26.2
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* V3 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list
  2020-05-23 18:29 ` Fangrui Song
@ 2020-05-23 19:50   ` H.J. Lu
  2020-05-23 21:56     ` Fangrui Song
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2020-05-23 19:50 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils

[-- Attachment #1: Type: text/plain, Size: 16055 bytes --]

On Sat, May 23, 2020 at 11:29 AM Fangrui Song <maskray@google.com> wrote:
>
> On 2020-05-23, H.J. Lu wrote:
> >From: Fangrui Song <maskray@google.com>
> >
> >--export-dynamic-symbol-list is like a dynamic list, but without
> >the symbolic property for unspecified symbols.
> >
> >When creating an executable, --export-dynamic-symbol-list is treated
> >like --dynamic-list.
> >
> >When creating a shared library, it is treated like --dynamic-list if
> >-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
> >that references to matched symbols will not be bound to the definitions
> >within the shared library.
> >
> >2020-05-XX  Fangrui Song  <maskray@google.com>
> >           H.J. Lu  <hongjiu.lu@intel.com>
> >
> >       PR ld/25910
> >       * NEWS: Mention --export-dynamic-symbol[-list].
> >       * ld.texi: Document --export-dynamic-symbol[-list].
> >       * ldgram.y: Pass current_dynamic_list_p to
> >       lang_append_dynamic_list.
> >       * ldlang.c (current_dynamic_list_p): New.
> >       (ang_append_dynamic_list): Updated to take a pointer to
> >       struct bfd_elf_dynamic_list * argument instead of using
> >       link_info.dynamic_list.
> >       (lang_append_dynamic_list_cpp_typeinfo): Pass
> >       &link_info.dynamic_list to ang_append_dynamic_list.
> >       (lang_append_dynamic_list_cpp_new): Likewise.
> >       * ldlang.h (current_dynamic_list_p): New.
> >       (lang_append_dynamic_list): Add a pointer to
> >       struct bfd_elf_dynamic_list * argument.
> >       * ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
> >       * lexsup.c (ld_options): Add entries for
> >       OPTION_EXPORT_DYNAMIC_SYMBOL and
> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
> >       (parse_args): Handle --export-dynamic-symbol and
> >       --export-dynamic-symbol-list.
> >       * testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
> >       * testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
> >       * testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
> >       * testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
> >       * testsuite/ld-dynamic/export-dynamic-symbol.s: New.
> >       * testsuite/ld-dynamic/foo-bar.list: New.
> >       * testsuite/ld-dynamic/foo.list: New.
> >       * testsuite/ld-dynamic/foo.s: New.
> >       * testsuite/ld-dynamic/fstar.list: New.
> >       * testsuite/ld-elf/dlempty.list: New.
> >       * testsuite/ld-elf/shared.exp: Add tests for
> >       --export-dynamic-symbol and --export-dynamic-symbol-list.
> >---
> > ld/NEWS                                       |  3 +
> > ld/ld.texi                                    | 18 +++++
> > ld/ldgram.y                                   |  2 +-
> > ld/ldlang.c                                   | 16 ++--
> > ld/ldlang.h                                   |  5 +-
> > ld/ldlex.h                                    |  2 +
> > ld/lexsup.c                                   | 75 +++++++++++++++++++
> > .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
> > .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
> > .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 ++
> > .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
> > .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
> > .../export-dynamic-symbol-list-glob.d         |  8 ++
> > .../ld-dynamic/export-dynamic-symbol.exp      | 39 ++++++++++
> > .../ld-dynamic/export-dynamic-symbol.s        |  9 +++
> > ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
> > ld/testsuite/ld-dynamic/foo.list              |  1 +
> > ld/testsuite/ld-dynamic/foo.s                 |  4 +
> > ld/testsuite/ld-dynamic/fstar.list            |  1 +
> > ld/testsuite/ld-elf/dlempty.list              |  3 +
> > ld/testsuite/ld-elf/shared.exp                | 36 +++++++++
> > 21 files changed, 258 insertions(+), 9 deletions(-)
> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> > create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
> > create mode 100644 ld/testsuite/ld-dynamic/foo.list
> > create mode 100644 ld/testsuite/ld-dynamic/foo.s
> > create mode 100644 ld/testsuite/ld-dynamic/fstar.list
> > create mode 100644 ld/testsuite/ld-elf/dlempty.list
> >
> >diff --git a/ld/NEWS b/ld/NEWS
> >index 9f5bbe51cf..870c480bde 100644
> >--- a/ld/NEWS
> >+++ b/ld/NEWS
> >@@ -1,5 +1,8 @@
> > -*- text -*-
> >
> >+* Add ELF linker command-line options, --export-dynamic-symbol and
> >+  --export-dynamic-symbol-list, to make symbols dynamic.
> >+
> > * Add command-line options --enable-non-contiguous-regions and
> >   --enable-non-contiguous-regions-warnings.
> >
> >diff --git a/ld/ld.texi b/ld/ld.texi
> >index 4dc78e65fa..92e47c6324 100644
> >--- a/ld/ld.texi
> >+++ b/ld/ld.texi
> >@@ -569,6 +569,24 @@ 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{glob}
> >+@cindex export dynamic symbol
> >+@item --export-dynamic-symbol=@var{glob}
> >+When creating a dynamically linked executable, symbols matching
> >+@var{glob} will be added to the dynamic symbol table. When creating a
> >+shared library, references to symbols matching @var{glob} will not be
> >+bound to the definitions within the shared library. This option is a
> >+no-op when creating a shared library and @samp{-Bsymbolic} or
> >+@samp{--dynamic-list} are not specified. This option is only meaningful
> >+on ELF platforms which support shared libraries.
>
> Is --export-dynamic-symbol still effective for -shared?
> I think either way is ok.

Yes.

> >+@kindex --export-dynamic-symbol-list=@var{file}
> >+@cindex export dynamic symbol list
> >+@item --export-dynamic-symbol-list=@var{file}
> >+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
> >+The format of the file is the same as the version node without
> >+scope and node name.  See @ref{VERSION} for more information.
> >+
> > @ifclear SingleFormat
> > @cindex big-endian objects
> > @cindex endianness
> >diff --git a/ld/ldgram.y b/ld/ldgram.y
> >index df5c035c03..36845c4c30 100644
> >--- a/ld/ldgram.y
> >+++ b/ld/ldgram.y
> >@@ -1313,7 +1313,7 @@ dynamic_list_node:
> > dynamic_list_tag:
> >               vers_defns ';'
> >               {
> >-                lang_append_dynamic_list ($1);
> >+                lang_append_dynamic_list (current_dynamic_list_p, $1);
> >               }
> >       ;
> >
> >diff --git a/ld/ldlang.c b/ld/ldlang.c
> >index 3d653d460d..14a6a577d2 100644
> >--- a/ld/ldlang.c
> >+++ b/ld/ldlang.c
> >@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
> >    lang_statement_union).  */
> > lang_statement_list_type input_file_chain;
> > static const char *current_input_file;
> >+struct bfd_elf_dynamic_list **current_dynamic_list_p;
> > struct bfd_sym_chain entry_symbol = { NULL, NULL };
> > const char *entry_section = ".text";
> > struct lang_input_statement_flags input_flags;
> >@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
> > /* Append the list of dynamic symbols to the existing one.  */
> >
> > void
> >-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
> >+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
> >+                        struct bfd_elf_version_expr *dynamic)
> > {
> >-  if (link_info.dynamic_list)
> >+  if (*list_p)
> >     {
> >       struct bfd_elf_version_expr *tail;
> >       for (tail = dynamic; tail->next != NULL; tail = tail->next)
> >       ;
> >-      tail->next = link_info.dynamic_list->head.list;
> >-      link_info.dynamic_list->head.list = dynamic;
> >+      tail->next = (*list_p)->head.list;
> >+      (*list_p)->head.list = dynamic;
> >     }
> >   else
> >     {
> >@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
> >       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
> >       d->head.list = dynamic;
> >       d->match = lang_vers_match;
> >-      link_info.dynamic_list = d;
> >+      *list_p = d;
> >     }
> > }
> >
> >@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
> >                                    FALSE);
> >
> >-  lang_append_dynamic_list (dynamic);
> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
> > }
> >
> > /* Append the list of C++ operator new and delete dynamic symbols to the
> >@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
> >                                    FALSE);
> >
> >-  lang_append_dynamic_list (dynamic);
> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
> > }
> >
> > /* Scan a space and/or comma separated string of features.  */
> >diff --git a/ld/ldlang.h b/ld/ldlang.h
> >index 3018c3e2ba..529ccd1585 100644
> >--- a/ld/ldlang.h
> >+++ b/ld/ldlang.h
> >@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
> > extern lang_statement_list_type file_chain;
> > extern lang_statement_list_type input_file_chain;
> >
> >+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
> >+
> > extern int lang_statement_iteration;
> > extern struct asneeded_minfo **asneeded_list_tail;
> >
> >@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
> >   (struct bfd_elf_version_deps *, const char *);
> > extern void lang_register_vers_node
> >   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
> >-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
> >+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
> >+                                    struct bfd_elf_version_expr *);
> > extern void lang_append_dynamic_list_cpp_typeinfo (void);
> > extern void lang_append_dynamic_list_cpp_new (void);
> > extern void lang_add_unique
> >diff --git a/ld/ldlex.h b/ld/ldlex.h
> >index 22b928d2d9..2c8d043a09 100644
> >--- a/ld/ldlex.h
> >+++ b/ld/ldlex.h
> >@@ -81,6 +81,8 @@ enum option_values
> >   OPTION_DYNAMIC_LIST_CPP_NEW,
> >   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
> >   OPTION_DYNAMIC_LIST_DATA,
> >+  OPTION_EXPORT_DYNAMIC_SYMBOL,
> >+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
> >   OPTION_WARN_COMMON,
> >   OPTION_WARN_CONSTRUCTORS,
> >   OPTION_WARN_FATAL,
> >diff --git a/ld/lexsup.c b/ld/lexsup.c
> >index fe9526b527..2bac1631d6 100644
> >--- a/ld/lexsup.c
> >+++ b/ld/lexsup.c
> >@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
> >+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
> >+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
> >@@ -581,6 +585,7 @@ parse_args (unsigned argc, char **argv)
> >     dynamic_list_data,
> >     dynamic_list
> >   } opt_dynamic_list = dynamic_list_unset;
> >+  struct bfd_elf_dynamic_list *export_list = NULL;
> >
> >   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
> >   longopts = (struct option *)
> >@@ -1418,6 +1423,7 @@ parse_args (unsigned argc, char **argv)
> >           ldfile_open_command_file (optarg);
> >           saved_script_handle = hold_script_handle;
> >           parser_input = input_dynamic_list;
> >+          current_dynamic_list_p = &link_info.dynamic_list;
> >           yyparse ();
> >         }
> >         if (opt_dynamic_list != dynamic_list_data)
> >@@ -1425,6 +1431,29 @@ parse_args (unsigned argc, char **argv)
> >         if (opt_symbolic == symbolic)
> >           opt_symbolic = symbolic_unset;
> >         break;
> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL:
> >+        {
> >+          struct bfd_elf_version_expr *expr
> >+            = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
> >+                                     FALSE);
> >+          lang_append_dynamic_list (&export_list, expr);
> >+          }
> >+        break;
> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
> >+        /* This option indicates a small script that only specifies
> >+           an export list.  Read it, but don't assume that we've
> >+           seen a linker script.  */
> >+        {
> >+          FILE *hold_script_handle;
> >+
> >+          hold_script_handle = saved_script_handle;
> >+          ldfile_open_command_file (optarg);
> >+          saved_script_handle = hold_script_handle;
> >+          parser_input = input_dynamic_list;
> >+          current_dynamic_list_p = &export_list;
> >+          yyparse ();
> >+        }
> >+        break;
> >       case OPTION_WARN_COMMON:
> >         config.warn_common = TRUE;
> >         break;
> >@@ -1632,6 +1661,52 @@ parse_args (unsigned argc, char **argv)
> >       && command_line.check_section_addresses < 0)
> >     command_line.check_section_addresses = 0;
> >
> >+  if (export_list && !bfd_link_relocatable (&link_info))
> >+    {
> >+      struct bfd_elf_version_expr *head = export_list->head.list;
> >+      struct bfd_elf_version_expr *next;
> >+
> >+      /* For --export-dynamic-symbol[-list]:
> >+       1. When building executable, treat like --dynamic-list.
> >+       2. When building shared object:
> >+          a. If -Bsymbolic or --dynamic-list are used, treat like
> >+             --dynamic-list.
> >+          b. Otherwise, ignored.
> >+       */
> >+      bfd_boolean kept = (bfd_link_executable (&link_info)
> >+                        || opt_symbolic != symbolic_unset
> >+                        || opt_dynamic_list != dynamic_list_unset);
> >+
> >+      if (kept)
> >+      {
> >+        /* Append the export list to link_info.dynamic_list.  */
> >+        if (link_info.dynamic_list)
> >+          {
> >+            for (next = head; next->next != NULL; next = next->next)
> >+              ;
> >+            next->next = link_info.dynamic_list->head.list;
> >+            link_info.dynamic_list->head.list = head;
> >+          }
> >+        else
> >+          link_info.dynamic_list = export_list;
> >+
> >+        if (opt_dynamic_list != dynamic_list_data)
> >+          opt_dynamic_list = dynamic_list;
> >+        if (opt_symbolic == symbolic)
> >+          opt_symbolic = symbolic_unset;
>
> The interaction with -Bsymbolic appears to be more complex now.
> I think users will pretty much avoid the combination of -Bsymbolic and
> (--dynamic-list or --export-dynamic-symbol or --export-dynamic-symbol-list).
>
> So I beg for a re-consideration of
> https://sourceware.org/bugzilla/show_bug.cgi?id=26018
> https://sourceware.org/pipermail/binutils/2020-May/111223.html
>

Here is the updated patch on top of

https://sourceware.org/pipermail/binutils/2020-May/111228.html

-- 
H.J.

[-- Attachment #2: 0001-ld-Add-export-dynamic-symbol-and-export-dynamic-symb.patch --]
[-- Type: text/x-patch, Size: 22660 bytes --]

From a7722abb6a524efdf30e19490e24246bca305900 Mon Sep 17 00:00:00 2001
From: Fangrui Song <maskray@google.com>
Date: Wed, 22 Apr 2020 22:12:42 -0700
Subject: [PATCH] ld: Add --export-dynamic-symbol and
 --export-dynamic-symbol-list

--export-dynamic-symbol-list is like a dynamic list, but without
the symbolic property for unspecified symbols.

When creating an executable, --export-dynamic-symbol-list is treated
like --dynamic-list.

When creating a shared library, it is treated like --dynamic-list if
-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
that references to matched symbols will not be bound to the definitions
within the shared library.

2020-05-XX  Fangrui Song  <maskray@google.com>
	    H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/25910
	* NEWS: Mention --export-dynamic-symbol[-list].
	* ld.texi: Document --export-dynamic-symbol[-list].
	* ldgram.y: Pass current_dynamic_list_p to
	lang_append_dynamic_list.
	* ldlang.c (current_dynamic_list_p): New.
	(ang_append_dynamic_list): Updated to take a pointer to
	struct bfd_elf_dynamic_list * argument instead of using
	link_info.dynamic_list.
	(lang_append_dynamic_list_cpp_typeinfo): Pass
	&link_info.dynamic_list to ang_append_dynamic_list.
	(lang_append_dynamic_list_cpp_new): Likewise.
	* ldlang.h (current_dynamic_list_p): New.
	(lang_append_dynamic_list): Add a pointer to
	struct bfd_elf_dynamic_list * argument.
	* ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
	* lexsup.c (ld_options): Add entries for
	OPTION_EXPORT_DYNAMIC_SYMBOL and
	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
	(parse_args): Handle --export-dynamic-symbol and
	--export-dynamic-symbol-list.
	* testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
	* testsuite/ld-dynamic/export-dynamic-symbol.s: New.
	* testsuite/ld-dynamic/foo-bar.list: New.
	* testsuite/ld-dynamic/foo.list: New.
	* testsuite/ld-dynamic/foo.s: New.
	* testsuite/ld-dynamic/fstar.list: New.
	* testsuite/ld-elf/dlempty.list: New.
	* testsuite/ld-elf/shared.exp: Add tests for
	--export-dynamic-symbol and --export-dynamic-symbol-list.
---
 ld/NEWS                                       |  3 +
 ld/ld.texi                                    | 18 +++++
 ld/ldgram.y                                   |  2 +-
 ld/ldlang.c                                   | 16 +++--
 ld/ldlang.h                                   |  5 +-
 ld/ldlex.h                                    |  2 +
 ld/lexsup.c                                   | 72 +++++++++++++++++++
 .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
 .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
 .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 +++
 .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
 .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
 .../export-dynamic-symbol-list-glob.d         |  8 +++
 .../ld-dynamic/export-dynamic-symbol.exp      | 39 ++++++++++
 .../ld-dynamic/export-dynamic-symbol.s        |  9 +++
 ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
 ld/testsuite/ld-dynamic/foo.list              |  1 +
 ld/testsuite/ld-dynamic/foo.s                 |  4 ++
 ld/testsuite/ld-dynamic/fstar.list            |  1 +
 ld/testsuite/ld-elf/dlempty.list              |  3 +
 ld/testsuite/ld-elf/shared.exp                | 42 +++++++++++
 21 files changed, 261 insertions(+), 9 deletions(-)
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
 create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
 create mode 100644 ld/testsuite/ld-dynamic/foo.list
 create mode 100644 ld/testsuite/ld-dynamic/foo.s
 create mode 100644 ld/testsuite/ld-dynamic/fstar.list
 create mode 100644 ld/testsuite/ld-elf/dlempty.list

diff --git a/ld/NEWS b/ld/NEWS
index 9f5bbe51cf..870c480bde 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add ELF linker command-line options, --export-dynamic-symbol and
+  --export-dynamic-symbol-list, to make symbols dynamic.
+
 * Add command-line options --enable-non-contiguous-regions and
   --enable-non-contiguous-regions-warnings.
 
diff --git a/ld/ld.texi b/ld/ld.texi
index 4dc78e65fa..92e47c6324 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -569,6 +569,24 @@ 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{glob}
+@cindex export dynamic symbol
+@item --export-dynamic-symbol=@var{glob}
+When creating a dynamically linked executable, symbols matching
+@var{glob} will be added to the dynamic symbol table. When creating a
+shared library, references to symbols matching @var{glob} will not be
+bound to the definitions within the shared library. This option is a
+no-op when creating a shared library and @samp{-Bsymbolic} or
+@samp{--dynamic-list} are not specified. This option is only meaningful
+on ELF platforms which support shared libraries.
+
+@kindex --export-dynamic-symbol-list=@var{file}
+@cindex export dynamic symbol list
+@item --export-dynamic-symbol-list=@var{file}
+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
+The format of the file is the same as the version node without
+scope and node name.  See @ref{VERSION} for more information.
+
 @ifclear SingleFormat
 @cindex big-endian objects
 @cindex endianness
diff --git a/ld/ldgram.y b/ld/ldgram.y
index df5c035c03..36845c4c30 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -1313,7 +1313,7 @@ dynamic_list_node:
 dynamic_list_tag:
 		vers_defns ';'
 		{
-		  lang_append_dynamic_list ($1);
+		  lang_append_dynamic_list (current_dynamic_list_p, $1);
 		}
 	;
 
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 3d653d460d..14a6a577d2 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
    lang_statement_union).  */
 lang_statement_list_type input_file_chain;
 static const char *current_input_file;
+struct bfd_elf_dynamic_list **current_dynamic_list_p;
 struct bfd_sym_chain entry_symbol = { NULL, NULL };
 const char *entry_section = ".text";
 struct lang_input_statement_flags input_flags;
@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
 /* Append the list of dynamic symbols to the existing one.  */
 
 void
-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
+			  struct bfd_elf_version_expr *dynamic)
 {
-  if (link_info.dynamic_list)
+  if (*list_p)
     {
       struct bfd_elf_version_expr *tail;
       for (tail = dynamic; tail->next != NULL; tail = tail->next)
 	;
-      tail->next = link_info.dynamic_list->head.list;
-      link_info.dynamic_list->head.list = dynamic;
+      tail->next = (*list_p)->head.list;
+      (*list_p)->head.list = dynamic;
     }
   else
     {
@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
       d->head.list = dynamic;
       d->match = lang_vers_match;
-      link_info.dynamic_list = d;
+      *list_p = d;
     }
 }
 
@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
 				     FALSE);
 
-  lang_append_dynamic_list (dynamic);
+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
 }
 
 /* Append the list of C++ operator new and delete dynamic symbols to the
@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
 				     FALSE);
 
-  lang_append_dynamic_list (dynamic);
+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
 }
 
 /* Scan a space and/or comma separated string of features.  */
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 3018c3e2ba..529ccd1585 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
 extern lang_statement_list_type file_chain;
 extern lang_statement_list_type input_file_chain;
 
+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
+
 extern int lang_statement_iteration;
 extern struct asneeded_minfo **asneeded_list_tail;
 
@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
   (struct bfd_elf_version_deps *, const char *);
 extern void lang_register_vers_node
   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
+				      struct bfd_elf_version_expr *);
 extern void lang_append_dynamic_list_cpp_typeinfo (void);
 extern void lang_append_dynamic_list_cpp_new (void);
 extern void lang_add_unique
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 22b928d2d9..2c8d043a09 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -81,6 +81,8 @@ enum option_values
   OPTION_DYNAMIC_LIST_CPP_NEW,
   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
   OPTION_DYNAMIC_LIST_DATA,
+  OPTION_EXPORT_DYNAMIC_SYMBOL,
+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
   OPTION_WARN_COMMON,
   OPTION_WARN_CONSTRUCTORS,
   OPTION_WARN_FATAL,
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 49e013b5bd..7a00621ae6 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
@@ -581,6 +585,7 @@ parse_args (unsigned argc, char **argv)
     dynamic_list_data,
     dynamic_list
   } opt_dynamic_list = dynamic_list_unset;
+  struct bfd_elf_dynamic_list *export_list = NULL;
 
   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
   longopts = (struct option *)
@@ -1412,11 +1417,35 @@ parse_args (unsigned argc, char **argv)
 	    ldfile_open_command_file (optarg);
 	    saved_script_handle = hold_script_handle;
 	    parser_input = input_dynamic_list;
+	    current_dynamic_list_p = &link_info.dynamic_list;
 	    yyparse ();
 	  }
 	  if (opt_dynamic_list != dynamic_list_data)
 	    opt_dynamic_list = dynamic_list;
 	  break;
+	case OPTION_EXPORT_DYNAMIC_SYMBOL:
+	  {
+	    struct bfd_elf_version_expr *expr
+	      = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
+				       FALSE);
+	    lang_append_dynamic_list (&export_list, expr);
+          }
+	  break;
+	case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
+	  /* This option indicates a small script that only specifies
+	     an export list.  Read it, but don't assume that we've
+	     seen a linker script.  */
+	  {
+	    FILE *hold_script_handle;
+
+	    hold_script_handle = saved_script_handle;
+	    ldfile_open_command_file (optarg);
+	    saved_script_handle = hold_script_handle;
+	    parser_input = input_dynamic_list;
+	    current_dynamic_list_p = &export_list;
+	    yyparse ();
+	  }
+	  break;
 	case OPTION_WARN_COMMON:
 	  config.warn_common = TRUE;
 	  break;
@@ -1624,6 +1653,49 @@ parse_args (unsigned argc, char **argv)
       && command_line.check_section_addresses < 0)
     command_line.check_section_addresses = 0;
 
+  if (export_list)
+    {
+      struct bfd_elf_version_expr *head = export_list->head.list;
+      struct bfd_elf_version_expr *next;
+
+      /* For --export-dynamic-symbol[-list]:
+	 1. When building executable, treat like --dynamic-list.
+	 2. When building shared object:
+	    a. If -Bsymbolic or --dynamic-list are used, treat like
+	       --dynamic-list.
+	    b. Otherwise, ignored.
+       */
+      if (!bfd_link_relocatable (&link_info)
+	  && (bfd_link_executable (&link_info)
+	      || opt_symbolic != symbolic_unset
+	      || opt_dynamic_list != dynamic_list_unset))
+	{
+	  /* Append the export list to link_info.dynamic_list.  */
+	  if (link_info.dynamic_list)
+	    {
+	      for (next = head; next->next != NULL; next = next->next)
+		;
+	      next->next = link_info.dynamic_list->head.list;
+	      link_info.dynamic_list->head.list = head;
+	    }
+	  else
+	    link_info.dynamic_list = export_list;
+
+	  if (opt_dynamic_list != dynamic_list_data)
+	    opt_dynamic_list = dynamic_list;
+	}
+      else
+	{
+	  /* Free the export list.  */
+	  for (; head->next != NULL; head = next)
+	    {
+	      next = head->next;
+	      free (head);
+	    }
+	  free (export_list);
+	}
+    }
+
   switch (opt_dynamic_list)
     {
     case dynamic_list_unset:
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
new file mode 100644
index 0000000000..c1dd4e2f55
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
@@ -0,0 +1,9 @@
+#name: --export-dynamic-symbol foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie --export-dynamic-symbol foo tmpdir/libfoo.a
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
new file mode 100644
index 0000000000..7ec4eed3ed
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
@@ -0,0 +1,9 @@
+#name: -u --export-dynamic-symbol foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol foo --export-dynamic-symbol=bar tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +bar
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
new file mode 100644
index 0000000000..05a6e15b3b
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
@@ -0,0 +1,8 @@
+#name: -u --export-dynamic-symbol f* archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol f* tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
new file mode 100644
index 0000000000..aa1b8839e6
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
@@ -0,0 +1,9 @@
+#name: --export-dynamic-symbol-list foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie --export-dynamic-symbol-list foo.list tmpdir/libfoo.a
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
new file mode 100644
index 0000000000..367a07c1bb
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
@@ -0,0 +1,9 @@
+#name: -u --export-dynamic-symbol-list foo bar archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol-list foo-bar.list tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +bar
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
new file mode 100644
index 0000000000..f0e3427306
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
@@ -0,0 +1,8 @@
+#name: -u --export-dynamic-symbol-list fstar archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol-list fstar.list tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
new file mode 100644
index 0000000000..d0b4bc4eb0
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
@@ -0,0 +1,39 @@
+# 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.
+#
+
+if ![is_elf_format] {
+    return
+}
+
+set build_tests {
+  {"Build libfoo.a"
+   "" "" ""
+   {foo.s} {} "libfoo.a"}
+}
+
+run_ld_link_tests $build_tests
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/export-dynamic-symbol-*.d]]
+foreach test_file $test_list {
+    set test_name [file rootname $test_file]
+    verbose $test_name
+    run_dump_test $test_name
+}
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
new file mode 100644
index 0000000000..4b1b8ebd5c
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
@@ -0,0 +1,9 @@
+	.text
+	.global _start
+_start:
+	.word 0
+
+	.section .text.1, "ax"
+	.global bar
+bar:
+	.word 0
diff --git a/ld/testsuite/ld-dynamic/foo-bar.list b/ld/testsuite/ld-dynamic/foo-bar.list
new file mode 100644
index 0000000000..87732e1de4
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo-bar.list
@@ -0,0 +1 @@
+{ foo; bar; };
diff --git a/ld/testsuite/ld-dynamic/foo.list b/ld/testsuite/ld-dynamic/foo.list
new file mode 100644
index 0000000000..f89f569438
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo.list
@@ -0,0 +1 @@
+{ foo; };
diff --git a/ld/testsuite/ld-dynamic/foo.s b/ld/testsuite/ld-dynamic/foo.s
new file mode 100644
index 0000000000..4a70181776
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo.s
@@ -0,0 +1,4 @@
+	.text
+	.globl foo
+foo:
+	.byte 0
diff --git a/ld/testsuite/ld-dynamic/fstar.list b/ld/testsuite/ld-dynamic/fstar.list
new file mode 100644
index 0000000000..330d1dd2b8
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/fstar.list
@@ -0,0 +1 @@
+{ f*; };
diff --git a/ld/testsuite/ld-elf/dlempty.list b/ld/testsuite/ld-elf/dlempty.list
new file mode 100644
index 0000000000..9b3884b10e
--- /dev/null
+++ b/ld/testsuite/ld-elf/dlempty.list
@@ -0,0 +1,3 @@
+{
+  empty;
+};
diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
index 7d35f3f379..5606c9937f 100644
--- a/ld/testsuite/ld-elf/shared.exp
+++ b/ld/testsuite/ld-elf/shared.exp
@@ -601,6 +601,27 @@ set build_tests {
   {"Build libdl2d.so with --dynamic-list-data -Bsymbolic"
    "-shared -Wl,-Bsymbolic,--dynamic-list-data" "-fPIC"
    {dl2.c dl2xxx.c} {} "libdl2d.so"}
+  {"Build libdl2e.so with --export-dynamic-symbol=foo"
+   "-shared -Wl,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2e.so"}
+  {"Build libdl2f.so with --dynamic-list=dlempty.list and --export-dynamic-symbol=foo"
+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2f.so"}
+  {"Build libdl2g.so with --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2g.so"}
+  {"Build libdl2h.so with --dynamic-list=dlempty.list and --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2h.so"}
+  {"Build libdl2i.so with -Bsymbolic and --export-dynamic-symbol=foo"
+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2i.so"}
+  {"Build libdl2j.so with -Bsymbolic and --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2j.so"}
+  {"Build libdl2k.so with --export-dynamic-symbol-list=dl2.list and -Bsymbolic"
+   "-shared -Wl,--export-dynamic-symbol-list=dl2.list,-Bsymbolic" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2k.so"}
   {"Build libdl4a.so with --dynamic-list=dl4.list"
    "-shared -Wl,--dynamic-list=dl4.list" "-fPIC"
    {dl4.c dl4xxx.c} {} "libdl4a.so"}
@@ -880,6 +901,27 @@ set run_tests [list \
     [list "Run with libdl2d.so" \
      "-Wl,--no-as-needed tmpdir/libdl2d.so" "" \
      {dl2main.c} "dl2d" "dl2a.out" ] \
+    [list "Run with libdl2e.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2e.so" "" \
+     {dl2main.c} "dl2e" "dl2b.out" ] \
+    [list "Run with libdl2f.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2f.so" "" \
+     {dl2main.c} "dl2f" "dl2a.out" ] \
+    [list "Run with libdl2g.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2g.so" "" \
+     {dl2main.c} "dl2g" "dl2b.out" ] \
+    [list "Run with libdl2h.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2h.so" "" \
+     {dl2main.c} "dl2h" "dl2a.out" ] \
+    [list "Run with libdl2i.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2i.so" "" \
+     {dl2main.c} "dl2i" "dl2a.out" ] \
+    [list "Run with libdl2j.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2j.so" "" \
+     {dl2main.c} "dl2j" "dl2a.out" ] \
+    [list "Run with libdl2k.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2k.so" "" \
+     {dl2main.c} "dl2k" "dl2a.out" ] \
     [list "Run with libdl4a.so" \
      "-Wl,--no-as-needed tmpdir/libdl4a.so" "" \
      {dl4main.c} "dl4a" "dl4a.out" ] \
-- 
2.26.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: V3 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list
  2020-05-23 19:50   ` V3 " H.J. Lu
@ 2020-05-23 21:56     ` Fangrui Song
  2020-05-27 14:29       ` V4 " H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: Fangrui Song @ 2020-05-23 21:56 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

On 2020-05-23, H.J. Lu wrote:
>On Sat, May 23, 2020 at 11:29 AM Fangrui Song <maskray@google.com> wrote:
>>
>> On 2020-05-23, H.J. Lu wrote:
>> >From: Fangrui Song <maskray@google.com>
>> >
>> >--export-dynamic-symbol-list is like a dynamic list, but without
>> >the symbolic property for unspecified symbols.
>> >
>> >When creating an executable, --export-dynamic-symbol-list is treated
>> >like --dynamic-list.
>> >
>> >When creating a shared library, it is treated like --dynamic-list if
>> >-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
>> >that references to matched symbols will not be bound to the definitions
>> >within the shared library.
>> >
>> >2020-05-XX  Fangrui Song  <maskray@google.com>
>> >           H.J. Lu  <hongjiu.lu@intel.com>
>> >
>> >       PR ld/25910
>> >       * NEWS: Mention --export-dynamic-symbol[-list].
>> >       * ld.texi: Document --export-dynamic-symbol[-list].
>> >       * ldgram.y: Pass current_dynamic_list_p to
>> >       lang_append_dynamic_list.
>> >       * ldlang.c (current_dynamic_list_p): New.
>> >       (ang_append_dynamic_list): Updated to take a pointer to
>> >       struct bfd_elf_dynamic_list * argument instead of using
>> >       link_info.dynamic_list.
>> >       (lang_append_dynamic_list_cpp_typeinfo): Pass
>> >       &link_info.dynamic_list to ang_append_dynamic_list.
>> >       (lang_append_dynamic_list_cpp_new): Likewise.
>> >       * ldlang.h (current_dynamic_list_p): New.
>> >       (lang_append_dynamic_list): Add a pointer to
>> >       struct bfd_elf_dynamic_list * argument.
>> >       * ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
>> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
>> >       * lexsup.c (ld_options): Add entries for
>> >       OPTION_EXPORT_DYNAMIC_SYMBOL and
>> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
>> >       (parse_args): Handle --export-dynamic-symbol and
>> >       --export-dynamic-symbol-list.
>> >       * testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
>> >       * testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
>> >       * testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
>> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
>> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
>> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
>> >       * testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
>> >       * testsuite/ld-dynamic/export-dynamic-symbol.s: New.
>> >       * testsuite/ld-dynamic/foo-bar.list: New.
>> >       * testsuite/ld-dynamic/foo.list: New.
>> >       * testsuite/ld-dynamic/foo.s: New.
>> >       * testsuite/ld-dynamic/fstar.list: New.
>> >       * testsuite/ld-elf/dlempty.list: New.
>> >       * testsuite/ld-elf/shared.exp: Add tests for
>> >       --export-dynamic-symbol and --export-dynamic-symbol-list.
>> >---
>> > ld/NEWS                                       |  3 +
>> > ld/ld.texi                                    | 18 +++++
>> > ld/ldgram.y                                   |  2 +-
>> > ld/ldlang.c                                   | 16 ++--
>> > ld/ldlang.h                                   |  5 +-
>> > ld/ldlex.h                                    |  2 +
>> > ld/lexsup.c                                   | 75 +++++++++++++++++++
>> > .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
>> > .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
>> > .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 ++
>> > .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
>> > .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
>> > .../export-dynamic-symbol-list-glob.d         |  8 ++
>> > .../ld-dynamic/export-dynamic-symbol.exp      | 39 ++++++++++
>> > .../ld-dynamic/export-dynamic-symbol.s        |  9 +++
>> > ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
>> > ld/testsuite/ld-dynamic/foo.list              |  1 +
>> > ld/testsuite/ld-dynamic/foo.s                 |  4 +
>> > ld/testsuite/ld-dynamic/fstar.list            |  1 +
>> > ld/testsuite/ld-elf/dlempty.list              |  3 +
>> > ld/testsuite/ld-elf/shared.exp                | 36 +++++++++
>> > 21 files changed, 258 insertions(+), 9 deletions(-)
>> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
>> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
>> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
>> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
>> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
>> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
>> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
>> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
>> > create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
>> > create mode 100644 ld/testsuite/ld-dynamic/foo.list
>> > create mode 100644 ld/testsuite/ld-dynamic/foo.s
>> > create mode 100644 ld/testsuite/ld-dynamic/fstar.list
>> > create mode 100644 ld/testsuite/ld-elf/dlempty.list
>> >
>> >diff --git a/ld/NEWS b/ld/NEWS
>> >index 9f5bbe51cf..870c480bde 100644
>> >--- a/ld/NEWS
>> >+++ b/ld/NEWS
>> >@@ -1,5 +1,8 @@
>> > -*- text -*-
>> >
>> >+* Add ELF linker command-line options, --export-dynamic-symbol and
>> >+  --export-dynamic-symbol-list, to make symbols dynamic.
>> >+
>> > * Add command-line options --enable-non-contiguous-regions and
>> >   --enable-non-contiguous-regions-warnings.
>> >
>> >diff --git a/ld/ld.texi b/ld/ld.texi
>> >index 4dc78e65fa..92e47c6324 100644
>> >--- a/ld/ld.texi
>> >+++ b/ld/ld.texi
>> >@@ -569,6 +569,24 @@ 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{glob}
>> >+@cindex export dynamic symbol
>> >+@item --export-dynamic-symbol=@var{glob}
>> >+When creating a dynamically linked executable, symbols matching
>> >+@var{glob} will be added to the dynamic symbol table. When creating a
>> >+shared library, references to symbols matching @var{glob} will not be
>> >+bound to the definitions within the shared library. This option is a
>> >+no-op when creating a shared library and @samp{-Bsymbolic} or
>> >+@samp{--dynamic-list} are not specified. This option is only meaningful
>> >+on ELF platforms which support shared libraries.
>>
>> Is --export-dynamic-symbol still effective for -shared?
>> I think either way is ok.
>
>Yes.
>
>> >+@kindex --export-dynamic-symbol-list=@var{file}
>> >+@cindex export dynamic symbol list
>> >+@item --export-dynamic-symbol-list=@var{file}
>> >+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
>> >+The format of the file is the same as the version node without
>> >+scope and node name.  See @ref{VERSION} for more information.
>> >+
>> > @ifclear SingleFormat
>> > @cindex big-endian objects
>> > @cindex endianness
>> >diff --git a/ld/ldgram.y b/ld/ldgram.y
>> >index df5c035c03..36845c4c30 100644
>> >--- a/ld/ldgram.y
>> >+++ b/ld/ldgram.y
>> >@@ -1313,7 +1313,7 @@ dynamic_list_node:
>> > dynamic_list_tag:
>> >               vers_defns ';'
>> >               {
>> >-                lang_append_dynamic_list ($1);
>> >+                lang_append_dynamic_list (current_dynamic_list_p, $1);
>> >               }
>> >       ;
>> >
>> >diff --git a/ld/ldlang.c b/ld/ldlang.c
>> >index 3d653d460d..14a6a577d2 100644
>> >--- a/ld/ldlang.c
>> >+++ b/ld/ldlang.c
>> >@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
>> >    lang_statement_union).  */
>> > lang_statement_list_type input_file_chain;
>> > static const char *current_input_file;
>> >+struct bfd_elf_dynamic_list **current_dynamic_list_p;
>> > struct bfd_sym_chain entry_symbol = { NULL, NULL };
>> > const char *entry_section = ".text";
>> > struct lang_input_statement_flags input_flags;
>> >@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
>> > /* Append the list of dynamic symbols to the existing one.  */
>> >
>> > void
>> >-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
>> >+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
>> >+                        struct bfd_elf_version_expr *dynamic)
>> > {
>> >-  if (link_info.dynamic_list)
>> >+  if (*list_p)
>> >     {
>> >       struct bfd_elf_version_expr *tail;
>> >       for (tail = dynamic; tail->next != NULL; tail = tail->next)
>> >       ;
>> >-      tail->next = link_info.dynamic_list->head.list;
>> >-      link_info.dynamic_list->head.list = dynamic;
>> >+      tail->next = (*list_p)->head.list;
>> >+      (*list_p)->head.list = dynamic;
>> >     }
>> >   else
>> >     {
>> >@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
>> >       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
>> >       d->head.list = dynamic;
>> >       d->match = lang_vers_match;
>> >-      link_info.dynamic_list = d;
>> >+      *list_p = d;
>> >     }
>> > }
>> >
>> >@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
>> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
>> >                                    FALSE);
>> >
>> >-  lang_append_dynamic_list (dynamic);
>> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
>> > }
>> >
>> > /* Append the list of C++ operator new and delete dynamic symbols to the
>> >@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
>> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
>> >                                    FALSE);
>> >
>> >-  lang_append_dynamic_list (dynamic);
>> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
>> > }
>> >
>> > /* Scan a space and/or comma separated string of features.  */
>> >diff --git a/ld/ldlang.h b/ld/ldlang.h
>> >index 3018c3e2ba..529ccd1585 100644
>> >--- a/ld/ldlang.h
>> >+++ b/ld/ldlang.h
>> >@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
>> > extern lang_statement_list_type file_chain;
>> > extern lang_statement_list_type input_file_chain;
>> >
>> >+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
>> >+
>> > extern int lang_statement_iteration;
>> > extern struct asneeded_minfo **asneeded_list_tail;
>> >
>> >@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
>> >   (struct bfd_elf_version_deps *, const char *);
>> > extern void lang_register_vers_node
>> >   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
>> >-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
>> >+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
>> >+                                    struct bfd_elf_version_expr *);
>> > extern void lang_append_dynamic_list_cpp_typeinfo (void);
>> > extern void lang_append_dynamic_list_cpp_new (void);
>> > extern void lang_add_unique
>> >diff --git a/ld/ldlex.h b/ld/ldlex.h
>> >index 22b928d2d9..2c8d043a09 100644
>> >--- a/ld/ldlex.h
>> >+++ b/ld/ldlex.h
>> >@@ -81,6 +81,8 @@ enum option_values
>> >   OPTION_DYNAMIC_LIST_CPP_NEW,
>> >   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
>> >   OPTION_DYNAMIC_LIST_DATA,
>> >+  OPTION_EXPORT_DYNAMIC_SYMBOL,
>> >+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
>> >   OPTION_WARN_COMMON,
>> >   OPTION_WARN_CONSTRUCTORS,
>> >   OPTION_WARN_FATAL,
>> >diff --git a/ld/lexsup.c b/ld/lexsup.c
>> >index fe9526b527..2bac1631d6 100644
>> >--- a/ld/lexsup.c
>> >+++ b/ld/lexsup.c
>> >@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
>> >+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
>> >+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
>> >@@ -581,6 +585,7 @@ parse_args (unsigned argc, char **argv)
>> >     dynamic_list_data,
>> >     dynamic_list
>> >   } opt_dynamic_list = dynamic_list_unset;
>> >+  struct bfd_elf_dynamic_list *export_list = NULL;
>> >
>> >   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
>> >   longopts = (struct option *)
>> >@@ -1418,6 +1423,7 @@ parse_args (unsigned argc, char **argv)
>> >           ldfile_open_command_file (optarg);
>> >           saved_script_handle = hold_script_handle;
>> >           parser_input = input_dynamic_list;
>> >+          current_dynamic_list_p = &link_info.dynamic_list;
>> >           yyparse ();
>> >         }
>> >         if (opt_dynamic_list != dynamic_list_data)
>> >@@ -1425,6 +1431,29 @@ parse_args (unsigned argc, char **argv)
>> >         if (opt_symbolic == symbolic)
>> >           opt_symbolic = symbolic_unset;
>> >         break;
>> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL:
>> >+        {
>> >+          struct bfd_elf_version_expr *expr
>> >+            = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
>> >+                                     FALSE);
>> >+          lang_append_dynamic_list (&export_list, expr);
>> >+          }
>> >+        break;
>> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
>> >+        /* This option indicates a small script that only specifies
>> >+           an export list.  Read it, but don't assume that we've
>> >+           seen a linker script.  */
>> >+        {
>> >+          FILE *hold_script_handle;
>> >+
>> >+          hold_script_handle = saved_script_handle;
>> >+          ldfile_open_command_file (optarg);
>> >+          saved_script_handle = hold_script_handle;
>> >+          parser_input = input_dynamic_list;
>> >+          current_dynamic_list_p = &export_list;
>> >+          yyparse ();
>> >+        }
>> >+        break;
>> >       case OPTION_WARN_COMMON:
>> >         config.warn_common = TRUE;
>> >         break;
>> >@@ -1632,6 +1661,52 @@ parse_args (unsigned argc, char **argv)
>> >       && command_line.check_section_addresses < 0)
>> >     command_line.check_section_addresses = 0;
>> >
>> >+  if (export_list && !bfd_link_relocatable (&link_info))
>> >+    {
>> >+      struct bfd_elf_version_expr *head = export_list->head.list;
>> >+      struct bfd_elf_version_expr *next;
>> >+
>> >+      /* For --export-dynamic-symbol[-list]:
>> >+       1. When building executable, treat like --dynamic-list.
>> >+       2. When building shared object:
>> >+          a. If -Bsymbolic or --dynamic-list are used, treat like
>> >+             --dynamic-list.
>> >+          b. Otherwise, ignored.
>> >+       */
>> >+      bfd_boolean kept = (bfd_link_executable (&link_info)
>> >+                        || opt_symbolic != symbolic_unset
>> >+                        || opt_dynamic_list != dynamic_list_unset);
>> >+
>> >+      if (kept)
>> >+      {
>> >+        /* Append the export list to link_info.dynamic_list.  */
>> >+        if (link_info.dynamic_list)
>> >+          {
>> >+            for (next = head; next->next != NULL; next = next->next)
>> >+              ;
>> >+            next->next = link_info.dynamic_list->head.list;
>> >+            link_info.dynamic_list->head.list = head;
>> >+          }
>> >+        else
>> >+          link_info.dynamic_list = export_list;
>> >+
>> >+        if (opt_dynamic_list != dynamic_list_data)
>> >+          opt_dynamic_list = dynamic_list;
>> >+        if (opt_symbolic == symbolic)
>> >+          opt_symbolic = symbolic_unset;
>>
>> The interaction with -Bsymbolic appears to be more complex now.
>> I think users will pretty much avoid the combination of -Bsymbolic and
>> (--dynamic-list or --export-dynamic-symbol or --export-dynamic-symbol-list).
>>
>> So I beg for a re-consideration of
>> https://sourceware.org/bugzilla/show_bug.cgi?id=26018
>> https://sourceware.org/pipermail/binutils/2020-May/111223.html
>>
>
>Here is the updated patch on top of
>
>https://sourceware.org/pipermail/binutils/2020-May/111228.html

Thanks for PATCH v3. LGTM.

I have verified the semantics of new tests dl2d ~ dl2k.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* V4 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list
  2020-05-23 21:56     ` Fangrui Song
@ 2020-05-27 14:29       ` H.J. Lu
  2020-05-27 16:19         ` Fangrui Song
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2020-05-27 14:29 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils

[-- Attachment #1: Type: text/plain, Size: 17958 bytes --]

On Sat, May 23, 2020 at 2:56 PM Fangrui Song <maskray@google.com> wrote:
>
> On 2020-05-23, H.J. Lu wrote:
> >On Sat, May 23, 2020 at 11:29 AM Fangrui Song <maskray@google.com> wrote:
> >>
> >> On 2020-05-23, H.J. Lu wrote:
> >> >From: Fangrui Song <maskray@google.com>
> >> >
> >> >--export-dynamic-symbol-list is like a dynamic list, but without
> >> >the symbolic property for unspecified symbols.
> >> >
> >> >When creating an executable, --export-dynamic-symbol-list is treated
> >> >like --dynamic-list.
> >> >
> >> >When creating a shared library, it is treated like --dynamic-list if
> >> >-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
> >> >that references to matched symbols will not be bound to the definitions
> >> >within the shared library.
> >> >
> >> >2020-05-XX  Fangrui Song  <maskray@google.com>
> >> >           H.J. Lu  <hongjiu.lu@intel.com>
> >> >
> >> >       PR ld/25910
> >> >       * NEWS: Mention --export-dynamic-symbol[-list].
> >> >       * ld.texi: Document --export-dynamic-symbol[-list].
> >> >       * ldgram.y: Pass current_dynamic_list_p to
> >> >       lang_append_dynamic_list.
> >> >       * ldlang.c (current_dynamic_list_p): New.
> >> >       (ang_append_dynamic_list): Updated to take a pointer to
> >> >       struct bfd_elf_dynamic_list * argument instead of using
> >> >       link_info.dynamic_list.
> >> >       (lang_append_dynamic_list_cpp_typeinfo): Pass
> >> >       &link_info.dynamic_list to ang_append_dynamic_list.
> >> >       (lang_append_dynamic_list_cpp_new): Likewise.
> >> >       * ldlang.h (current_dynamic_list_p): New.
> >> >       (lang_append_dynamic_list): Add a pointer to
> >> >       struct bfd_elf_dynamic_list * argument.
> >> >       * ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
> >> >       * lexsup.c (ld_options): Add entries for
> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL and
> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
> >> >       (parse_args): Handle --export-dynamic-symbol and
> >> >       --export-dynamic-symbol-list.
> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
> >> >       * testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
> >> >       * testsuite/ld-dynamic/export-dynamic-symbol.s: New.
> >> >       * testsuite/ld-dynamic/foo-bar.list: New.
> >> >       * testsuite/ld-dynamic/foo.list: New.
> >> >       * testsuite/ld-dynamic/foo.s: New.
> >> >       * testsuite/ld-dynamic/fstar.list: New.
> >> >       * testsuite/ld-elf/dlempty.list: New.
> >> >       * testsuite/ld-elf/shared.exp: Add tests for
> >> >       --export-dynamic-symbol and --export-dynamic-symbol-list.
> >> >---
> >> > ld/NEWS                                       |  3 +
> >> > ld/ld.texi                                    | 18 +++++
> >> > ld/ldgram.y                                   |  2 +-
> >> > ld/ldlang.c                                   | 16 ++--
> >> > ld/ldlang.h                                   |  5 +-
> >> > ld/ldlex.h                                    |  2 +
> >> > ld/lexsup.c                                   | 75 +++++++++++++++++++
> >> > .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
> >> > .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
> >> > .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 ++
> >> > .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
> >> > .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
> >> > .../export-dynamic-symbol-list-glob.d         |  8 ++
> >> > .../ld-dynamic/export-dynamic-symbol.exp      | 39 ++++++++++
> >> > .../ld-dynamic/export-dynamic-symbol.s        |  9 +++
> >> > ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
> >> > ld/testsuite/ld-dynamic/foo.list              |  1 +
> >> > ld/testsuite/ld-dynamic/foo.s                 |  4 +
> >> > ld/testsuite/ld-dynamic/fstar.list            |  1 +
> >> > ld/testsuite/ld-elf/dlempty.list              |  3 +
> >> > ld/testsuite/ld-elf/shared.exp                | 36 +++++++++
> >> > 21 files changed, 258 insertions(+), 9 deletions(-)
> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> >> > create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
> >> > create mode 100644 ld/testsuite/ld-dynamic/foo.list
> >> > create mode 100644 ld/testsuite/ld-dynamic/foo.s
> >> > create mode 100644 ld/testsuite/ld-dynamic/fstar.list
> >> > create mode 100644 ld/testsuite/ld-elf/dlempty.list
> >> >
> >> >diff --git a/ld/NEWS b/ld/NEWS
> >> >index 9f5bbe51cf..870c480bde 100644
> >> >--- a/ld/NEWS
> >> >+++ b/ld/NEWS
> >> >@@ -1,5 +1,8 @@
> >> > -*- text -*-
> >> >
> >> >+* Add ELF linker command-line options, --export-dynamic-symbol and
> >> >+  --export-dynamic-symbol-list, to make symbols dynamic.
> >> >+
> >> > * Add command-line options --enable-non-contiguous-regions and
> >> >   --enable-non-contiguous-regions-warnings.
> >> >
> >> >diff --git a/ld/ld.texi b/ld/ld.texi
> >> >index 4dc78e65fa..92e47c6324 100644
> >> >--- a/ld/ld.texi
> >> >+++ b/ld/ld.texi
> >> >@@ -569,6 +569,24 @@ 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{glob}
> >> >+@cindex export dynamic symbol
> >> >+@item --export-dynamic-symbol=@var{glob}
> >> >+When creating a dynamically linked executable, symbols matching
> >> >+@var{glob} will be added to the dynamic symbol table. When creating a
> >> >+shared library, references to symbols matching @var{glob} will not be
> >> >+bound to the definitions within the shared library. This option is a
> >> >+no-op when creating a shared library and @samp{-Bsymbolic} or
> >> >+@samp{--dynamic-list} are not specified. This option is only meaningful
> >> >+on ELF platforms which support shared libraries.
> >>
> >> Is --export-dynamic-symbol still effective for -shared?
> >> I think either way is ok.
> >
> >Yes.
> >
> >> >+@kindex --export-dynamic-symbol-list=@var{file}
> >> >+@cindex export dynamic symbol list
> >> >+@item --export-dynamic-symbol-list=@var{file}
> >> >+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
> >> >+The format of the file is the same as the version node without
> >> >+scope and node name.  See @ref{VERSION} for more information.
> >> >+
> >> > @ifclear SingleFormat
> >> > @cindex big-endian objects
> >> > @cindex endianness
> >> >diff --git a/ld/ldgram.y b/ld/ldgram.y
> >> >index df5c035c03..36845c4c30 100644
> >> >--- a/ld/ldgram.y
> >> >+++ b/ld/ldgram.y
> >> >@@ -1313,7 +1313,7 @@ dynamic_list_node:
> >> > dynamic_list_tag:
> >> >               vers_defns ';'
> >> >               {
> >> >-                lang_append_dynamic_list ($1);
> >> >+                lang_append_dynamic_list (current_dynamic_list_p, $1);
> >> >               }
> >> >       ;
> >> >
> >> >diff --git a/ld/ldlang.c b/ld/ldlang.c
> >> >index 3d653d460d..14a6a577d2 100644
> >> >--- a/ld/ldlang.c
> >> >+++ b/ld/ldlang.c
> >> >@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
> >> >    lang_statement_union).  */
> >> > lang_statement_list_type input_file_chain;
> >> > static const char *current_input_file;
> >> >+struct bfd_elf_dynamic_list **current_dynamic_list_p;
> >> > struct bfd_sym_chain entry_symbol = { NULL, NULL };
> >> > const char *entry_section = ".text";
> >> > struct lang_input_statement_flags input_flags;
> >> >@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
> >> > /* Append the list of dynamic symbols to the existing one.  */
> >> >
> >> > void
> >> >-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
> >> >+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
> >> >+                        struct bfd_elf_version_expr *dynamic)
> >> > {
> >> >-  if (link_info.dynamic_list)
> >> >+  if (*list_p)
> >> >     {
> >> >       struct bfd_elf_version_expr *tail;
> >> >       for (tail = dynamic; tail->next != NULL; tail = tail->next)
> >> >       ;
> >> >-      tail->next = link_info.dynamic_list->head.list;
> >> >-      link_info.dynamic_list->head.list = dynamic;
> >> >+      tail->next = (*list_p)->head.list;
> >> >+      (*list_p)->head.list = dynamic;
> >> >     }
> >> >   else
> >> >     {
> >> >@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
> >> >       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
> >> >       d->head.list = dynamic;
> >> >       d->match = lang_vers_match;
> >> >-      link_info.dynamic_list = d;
> >> >+      *list_p = d;
> >> >     }
> >> > }
> >> >
> >> >@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
> >> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
> >> >                                    FALSE);
> >> >
> >> >-  lang_append_dynamic_list (dynamic);
> >> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
> >> > }
> >> >
> >> > /* Append the list of C++ operator new and delete dynamic symbols to the
> >> >@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
> >> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
> >> >                                    FALSE);
> >> >
> >> >-  lang_append_dynamic_list (dynamic);
> >> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
> >> > }
> >> >
> >> > /* Scan a space and/or comma separated string of features.  */
> >> >diff --git a/ld/ldlang.h b/ld/ldlang.h
> >> >index 3018c3e2ba..529ccd1585 100644
> >> >--- a/ld/ldlang.h
> >> >+++ b/ld/ldlang.h
> >> >@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
> >> > extern lang_statement_list_type file_chain;
> >> > extern lang_statement_list_type input_file_chain;
> >> >
> >> >+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
> >> >+
> >> > extern int lang_statement_iteration;
> >> > extern struct asneeded_minfo **asneeded_list_tail;
> >> >
> >> >@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
> >> >   (struct bfd_elf_version_deps *, const char *);
> >> > extern void lang_register_vers_node
> >> >   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
> >> >-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
> >> >+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
> >> >+                                    struct bfd_elf_version_expr *);
> >> > extern void lang_append_dynamic_list_cpp_typeinfo (void);
> >> > extern void lang_append_dynamic_list_cpp_new (void);
> >> > extern void lang_add_unique
> >> >diff --git a/ld/ldlex.h b/ld/ldlex.h
> >> >index 22b928d2d9..2c8d043a09 100644
> >> >--- a/ld/ldlex.h
> >> >+++ b/ld/ldlex.h
> >> >@@ -81,6 +81,8 @@ enum option_values
> >> >   OPTION_DYNAMIC_LIST_CPP_NEW,
> >> >   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
> >> >   OPTION_DYNAMIC_LIST_DATA,
> >> >+  OPTION_EXPORT_DYNAMIC_SYMBOL,
> >> >+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
> >> >   OPTION_WARN_COMMON,
> >> >   OPTION_WARN_CONSTRUCTORS,
> >> >   OPTION_WARN_FATAL,
> >> >diff --git a/ld/lexsup.c b/ld/lexsup.c
> >> >index fe9526b527..2bac1631d6 100644
> >> >--- a/ld/lexsup.c
> >> >+++ b/ld/lexsup.c
> >> >@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
> >> >+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
> >> >+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
> >> >@@ -581,6 +585,7 @@ parse_args (unsigned argc, char **argv)
> >> >     dynamic_list_data,
> >> >     dynamic_list
> >> >   } opt_dynamic_list = dynamic_list_unset;
> >> >+  struct bfd_elf_dynamic_list *export_list = NULL;
> >> >
> >> >   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
> >> >   longopts = (struct option *)
> >> >@@ -1418,6 +1423,7 @@ parse_args (unsigned argc, char **argv)
> >> >           ldfile_open_command_file (optarg);
> >> >           saved_script_handle = hold_script_handle;
> >> >           parser_input = input_dynamic_list;
> >> >+          current_dynamic_list_p = &link_info.dynamic_list;
> >> >           yyparse ();
> >> >         }
> >> >         if (opt_dynamic_list != dynamic_list_data)
> >> >@@ -1425,6 +1431,29 @@ parse_args (unsigned argc, char **argv)
> >> >         if (opt_symbolic == symbolic)
> >> >           opt_symbolic = symbolic_unset;
> >> >         break;
> >> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL:
> >> >+        {
> >> >+          struct bfd_elf_version_expr *expr
> >> >+            = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
> >> >+                                     FALSE);
> >> >+          lang_append_dynamic_list (&export_list, expr);
> >> >+          }
> >> >+        break;
> >> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
> >> >+        /* This option indicates a small script that only specifies
> >> >+           an export list.  Read it, but don't assume that we've
> >> >+           seen a linker script.  */
> >> >+        {
> >> >+          FILE *hold_script_handle;
> >> >+
> >> >+          hold_script_handle = saved_script_handle;
> >> >+          ldfile_open_command_file (optarg);
> >> >+          saved_script_handle = hold_script_handle;
> >> >+          parser_input = input_dynamic_list;
> >> >+          current_dynamic_list_p = &export_list;
> >> >+          yyparse ();
> >> >+        }
> >> >+        break;
> >> >       case OPTION_WARN_COMMON:
> >> >         config.warn_common = TRUE;
> >> >         break;
> >> >@@ -1632,6 +1661,52 @@ parse_args (unsigned argc, char **argv)
> >> >       && command_line.check_section_addresses < 0)
> >> >     command_line.check_section_addresses = 0;
> >> >
> >> >+  if (export_list && !bfd_link_relocatable (&link_info))
> >> >+    {
> >> >+      struct bfd_elf_version_expr *head = export_list->head.list;
> >> >+      struct bfd_elf_version_expr *next;
> >> >+
> >> >+      /* For --export-dynamic-symbol[-list]:
> >> >+       1. When building executable, treat like --dynamic-list.
> >> >+       2. When building shared object:
> >> >+          a. If -Bsymbolic or --dynamic-list are used, treat like
> >> >+             --dynamic-list.
> >> >+          b. Otherwise, ignored.
> >> >+       */
> >> >+      bfd_boolean kept = (bfd_link_executable (&link_info)
> >> >+                        || opt_symbolic != symbolic_unset
> >> >+                        || opt_dynamic_list != dynamic_list_unset);
> >> >+
> >> >+      if (kept)
> >> >+      {
> >> >+        /* Append the export list to link_info.dynamic_list.  */
> >> >+        if (link_info.dynamic_list)
> >> >+          {
> >> >+            for (next = head; next->next != NULL; next = next->next)
> >> >+              ;
> >> >+            next->next = link_info.dynamic_list->head.list;
> >> >+            link_info.dynamic_list->head.list = head;
> >> >+          }
> >> >+        else
> >> >+          link_info.dynamic_list = export_list;
> >> >+
> >> >+        if (opt_dynamic_list != dynamic_list_data)
> >> >+          opt_dynamic_list = dynamic_list;
> >> >+        if (opt_symbolic == symbolic)
> >> >+          opt_symbolic = symbolic_unset;
> >>
> >> The interaction with -Bsymbolic appears to be more complex now.
> >> I think users will pretty much avoid the combination of -Bsymbolic and
> >> (--dynamic-list or --export-dynamic-symbol or --export-dynamic-symbol-list).
> >>
> >> So I beg for a re-consideration of
> >> https://sourceware.org/bugzilla/show_bug.cgi?id=26018
> >> https://sourceware.org/pipermail/binutils/2020-May/111223.html
> >>
> >
> >Here is the updated patch on top of
> >
> >https://sourceware.org/pipermail/binutils/2020-May/111228.html
>
> Thanks for PATCH v3. LGTM.
>
> I have verified the semantics of new tests dl2d ~ dl2k.

The updated patch to adjust ld-dynamic/export-dynamic-symbol.s
for all ELF targets:

diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
index 4b1b8ebd5c..c55da536c5 100644
--- a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
@@ -1,6 +1,14 @@
   .text
+  .global start  /* Used by SH targets.  */
+start:
   .global _start
 _start:
+  .global __start
+__start:
+  .global main   /* Used by HPPA targets.  */
+main:
+  .globl   _main /* Used by LynxOS targets.  */
+_main:
   .word 0

   .section .text.1, "ax"

-- 
H.J.

[-- Attachment #2: 0001-ld-Add-export-dynamic-symbol-and-export-dynamic-symb.patch --]
[-- Type: text/x-patch, Size: 22888 bytes --]

From 204662941af859a203a84c201a2445f73d71d2a2 Mon Sep 17 00:00:00 2001
From: Fangrui Song <maskray@google.com>
Date: Wed, 22 Apr 2020 22:12:42 -0700
Subject: [PATCH] ld: Add --export-dynamic-symbol and
 --export-dynamic-symbol-list

--export-dynamic-symbol-list is like a dynamic list, but without
the symbolic property for unspecified symbols.

When creating an executable, --export-dynamic-symbol-list is treated
like --dynamic-list.

When creating a shared library, it is treated like --dynamic-list if
-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
that references to matched symbols will not be bound to the definitions
within the shared library.

2020-05-XX  Fangrui Song  <maskray@google.com>
	    H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/25910
	* NEWS: Mention --export-dynamic-symbol[-list].
	* ld.texi: Document --export-dynamic-symbol[-list].
	* ldgram.y: Pass current_dynamic_list_p to
	lang_append_dynamic_list.
	* ldlang.c (current_dynamic_list_p): New.
	(ang_append_dynamic_list): Updated to take a pointer to
	struct bfd_elf_dynamic_list * argument instead of using
	link_info.dynamic_list.
	(lang_append_dynamic_list_cpp_typeinfo): Pass
	&link_info.dynamic_list to ang_append_dynamic_list.
	(lang_append_dynamic_list_cpp_new): Likewise.
	* ldlang.h (current_dynamic_list_p): New.
	(lang_append_dynamic_list): Add a pointer to
	struct bfd_elf_dynamic_list * argument.
	* ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
	* lexsup.c (ld_options): Add entries for
	OPTION_EXPORT_DYNAMIC_SYMBOL and
	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
	(parse_args): Handle --export-dynamic-symbol and
	--export-dynamic-symbol-list.
	* testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
	* testsuite/ld-dynamic/export-dynamic-symbol.s: New.
	* testsuite/ld-dynamic/foo-bar.list: New.
	* testsuite/ld-dynamic/foo.list: New.
	* testsuite/ld-dynamic/foo.s: New.
	* testsuite/ld-dynamic/fstar.list: New.
	* testsuite/ld-elf/dlempty.list: New.
	* testsuite/ld-elf/shared.exp: Add tests for
	--export-dynamic-symbol and --export-dynamic-symbol-list.
---
 ld/NEWS                                       |  3 +
 ld/ld.texi                                    | 18 +++++
 ld/ldgram.y                                   |  2 +-
 ld/ldlang.c                                   | 16 +++--
 ld/ldlang.h                                   |  5 +-
 ld/ldlex.h                                    |  2 +
 ld/lexsup.c                                   | 72 +++++++++++++++++++
 .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
 .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
 .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 +++
 .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
 .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
 .../export-dynamic-symbol-list-glob.d         |  8 +++
 .../ld-dynamic/export-dynamic-symbol.exp      | 39 ++++++++++
 .../ld-dynamic/export-dynamic-symbol.s        | 17 +++++
 ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
 ld/testsuite/ld-dynamic/foo.list              |  1 +
 ld/testsuite/ld-dynamic/foo.s                 |  4 ++
 ld/testsuite/ld-dynamic/fstar.list            |  1 +
 ld/testsuite/ld-elf/dlempty.list              |  3 +
 ld/testsuite/ld-elf/shared.exp                | 42 +++++++++++
 21 files changed, 269 insertions(+), 9 deletions(-)
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
 create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
 create mode 100644 ld/testsuite/ld-dynamic/foo.list
 create mode 100644 ld/testsuite/ld-dynamic/foo.s
 create mode 100644 ld/testsuite/ld-dynamic/fstar.list
 create mode 100644 ld/testsuite/ld-elf/dlempty.list

diff --git a/ld/NEWS b/ld/NEWS
index 0aaa13d487..01f653533b 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add ELF linker command-line options, --export-dynamic-symbol and
+  --export-dynamic-symbol-list, to make symbols dynamic.
+
 * Add a command-line option for ELF linker, --warn-textrel, to warn that
   DT_TEXTREL is set in a position-independent executable or shared object.
 
diff --git a/ld/ld.texi b/ld/ld.texi
index a7ec0d01b3..843975dc97 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -569,6 +569,24 @@ 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{glob}
+@cindex export dynamic symbol
+@item --export-dynamic-symbol=@var{glob}
+When creating a dynamically linked executable, symbols matching
+@var{glob} will be added to the dynamic symbol table. When creating a
+shared library, references to symbols matching @var{glob} will not be
+bound to the definitions within the shared library. This option is a
+no-op when creating a shared library and @samp{-Bsymbolic} or
+@samp{--dynamic-list} are not specified. This option is only meaningful
+on ELF platforms which support shared libraries.
+
+@kindex --export-dynamic-symbol-list=@var{file}
+@cindex export dynamic symbol list
+@item --export-dynamic-symbol-list=@var{file}
+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
+The format of the file is the same as the version node without
+scope and node name.  See @ref{VERSION} for more information.
+
 @ifclear SingleFormat
 @cindex big-endian objects
 @cindex endianness
diff --git a/ld/ldgram.y b/ld/ldgram.y
index df5c035c03..36845c4c30 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -1313,7 +1313,7 @@ dynamic_list_node:
 dynamic_list_tag:
 		vers_defns ';'
 		{
-		  lang_append_dynamic_list ($1);
+		  lang_append_dynamic_list (current_dynamic_list_p, $1);
 		}
 	;
 
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 3d653d460d..14a6a577d2 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
    lang_statement_union).  */
 lang_statement_list_type input_file_chain;
 static const char *current_input_file;
+struct bfd_elf_dynamic_list **current_dynamic_list_p;
 struct bfd_sym_chain entry_symbol = { NULL, NULL };
 const char *entry_section = ".text";
 struct lang_input_statement_flags input_flags;
@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
 /* Append the list of dynamic symbols to the existing one.  */
 
 void
-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
+			  struct bfd_elf_version_expr *dynamic)
 {
-  if (link_info.dynamic_list)
+  if (*list_p)
     {
       struct bfd_elf_version_expr *tail;
       for (tail = dynamic; tail->next != NULL; tail = tail->next)
 	;
-      tail->next = link_info.dynamic_list->head.list;
-      link_info.dynamic_list->head.list = dynamic;
+      tail->next = (*list_p)->head.list;
+      (*list_p)->head.list = dynamic;
     }
   else
     {
@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
       d->head.list = dynamic;
       d->match = lang_vers_match;
-      link_info.dynamic_list = d;
+      *list_p = d;
     }
 }
 
@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
 				     FALSE);
 
-  lang_append_dynamic_list (dynamic);
+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
 }
 
 /* Append the list of C++ operator new and delete dynamic symbols to the
@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
 				     FALSE);
 
-  lang_append_dynamic_list (dynamic);
+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
 }
 
 /* Scan a space and/or comma separated string of features.  */
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 3018c3e2ba..529ccd1585 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
 extern lang_statement_list_type file_chain;
 extern lang_statement_list_type input_file_chain;
 
+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
+
 extern int lang_statement_iteration;
 extern struct asneeded_minfo **asneeded_list_tail;
 
@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
   (struct bfd_elf_version_deps *, const char *);
 extern void lang_register_vers_node
   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
+				      struct bfd_elf_version_expr *);
 extern void lang_append_dynamic_list_cpp_typeinfo (void);
 extern void lang_append_dynamic_list_cpp_new (void);
 extern void lang_add_unique
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 318ac7a789..6388247b45 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -81,6 +81,8 @@ enum option_values
   OPTION_DYNAMIC_LIST_CPP_NEW,
   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
   OPTION_DYNAMIC_LIST_DATA,
+  OPTION_EXPORT_DYNAMIC_SYMBOL,
+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
   OPTION_WARN_COMMON,
   OPTION_WARN_CONSTRUCTORS,
   OPTION_WARN_FATAL,
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 3733a7c893..98f244bee1 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
@@ -583,6 +587,7 @@ parse_args (unsigned argc, char **argv)
     dynamic_list_data,
     dynamic_list
   } opt_dynamic_list = dynamic_list_unset;
+  struct bfd_elf_dynamic_list *export_list = NULL;
 
   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
   longopts = (struct option *)
@@ -1414,11 +1419,35 @@ parse_args (unsigned argc, char **argv)
 	    ldfile_open_command_file (optarg);
 	    saved_script_handle = hold_script_handle;
 	    parser_input = input_dynamic_list;
+	    current_dynamic_list_p = &link_info.dynamic_list;
 	    yyparse ();
 	  }
 	  if (opt_dynamic_list != dynamic_list_data)
 	    opt_dynamic_list = dynamic_list;
 	  break;
+	case OPTION_EXPORT_DYNAMIC_SYMBOL:
+	  {
+	    struct bfd_elf_version_expr *expr
+	      = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
+				       FALSE);
+	    lang_append_dynamic_list (&export_list, expr);
+          }
+	  break;
+	case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
+	  /* This option indicates a small script that only specifies
+	     an export list.  Read it, but don't assume that we've
+	     seen a linker script.  */
+	  {
+	    FILE *hold_script_handle;
+
+	    hold_script_handle = saved_script_handle;
+	    ldfile_open_command_file (optarg);
+	    saved_script_handle = hold_script_handle;
+	    parser_input = input_dynamic_list;
+	    current_dynamic_list_p = &export_list;
+	    yyparse ();
+	  }
+	  break;
 	case OPTION_WARN_COMMON:
 	  config.warn_common = TRUE;
 	  break;
@@ -1626,6 +1655,49 @@ parse_args (unsigned argc, char **argv)
       && command_line.check_section_addresses < 0)
     command_line.check_section_addresses = 0;
 
+  if (export_list)
+    {
+      struct bfd_elf_version_expr *head = export_list->head.list;
+      struct bfd_elf_version_expr *next;
+
+      /* For --export-dynamic-symbol[-list]:
+	 1. When building executable, treat like --dynamic-list.
+	 2. When building shared object:
+	    a. If -Bsymbolic or --dynamic-list are used, treat like
+	       --dynamic-list.
+	    b. Otherwise, ignored.
+       */
+      if (!bfd_link_relocatable (&link_info)
+	  && (bfd_link_executable (&link_info)
+	      || opt_symbolic != symbolic_unset
+	      || opt_dynamic_list != dynamic_list_unset))
+	{
+	  /* Append the export list to link_info.dynamic_list.  */
+	  if (link_info.dynamic_list)
+	    {
+	      for (next = head; next->next != NULL; next = next->next)
+		;
+	      next->next = link_info.dynamic_list->head.list;
+	      link_info.dynamic_list->head.list = head;
+	    }
+	  else
+	    link_info.dynamic_list = export_list;
+
+	  if (opt_dynamic_list != dynamic_list_data)
+	    opt_dynamic_list = dynamic_list;
+	}
+      else
+	{
+	  /* Free the export list.  */
+	  for (; head->next != NULL; head = next)
+	    {
+	      next = head->next;
+	      free (head);
+	    }
+	  free (export_list);
+	}
+    }
+
   switch (opt_dynamic_list)
     {
     case dynamic_list_unset:
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
new file mode 100644
index 0000000000..c1dd4e2f55
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
@@ -0,0 +1,9 @@
+#name: --export-dynamic-symbol foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie --export-dynamic-symbol foo tmpdir/libfoo.a
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
new file mode 100644
index 0000000000..7ec4eed3ed
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
@@ -0,0 +1,9 @@
+#name: -u --export-dynamic-symbol foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol foo --export-dynamic-symbol=bar tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +bar
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
new file mode 100644
index 0000000000..05a6e15b3b
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
@@ -0,0 +1,8 @@
+#name: -u --export-dynamic-symbol f* archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol f* tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
new file mode 100644
index 0000000000..aa1b8839e6
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
@@ -0,0 +1,9 @@
+#name: --export-dynamic-symbol-list foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie --export-dynamic-symbol-list foo.list tmpdir/libfoo.a
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
new file mode 100644
index 0000000000..367a07c1bb
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
@@ -0,0 +1,9 @@
+#name: -u --export-dynamic-symbol-list foo bar archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol-list foo-bar.list tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +bar
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
new file mode 100644
index 0000000000..f0e3427306
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
@@ -0,0 +1,8 @@
+#name: -u --export-dynamic-symbol-list fstar archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol-list fstar.list tmpdir/libfoo.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
new file mode 100644
index 0000000000..d0b4bc4eb0
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
@@ -0,0 +1,39 @@
+# 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.
+#
+
+if ![is_elf_format] {
+    return
+}
+
+set build_tests {
+  {"Build libfoo.a"
+   "" "" ""
+   {foo.s} {} "libfoo.a"}
+}
+
+run_ld_link_tests $build_tests
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/export-dynamic-symbol-*.d]]
+foreach test_file $test_list {
+    set test_name [file rootname $test_file]
+    verbose $test_name
+    run_dump_test $test_name
+}
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
new file mode 100644
index 0000000000..c55da536c5
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
@@ -0,0 +1,17 @@
+	.text
+	.global start	/* Used by SH targets.  */
+start:
+	.global _start
+_start:
+	.global __start
+__start:
+	.global main	/* Used by HPPA targets.  */
+main:
+	.globl	_main	/* Used by LynxOS targets.  */
+_main:
+	.word 0
+
+	.section .text.1, "ax"
+	.global bar
+bar:
+	.word 0
diff --git a/ld/testsuite/ld-dynamic/foo-bar.list b/ld/testsuite/ld-dynamic/foo-bar.list
new file mode 100644
index 0000000000..87732e1de4
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo-bar.list
@@ -0,0 +1 @@
+{ foo; bar; };
diff --git a/ld/testsuite/ld-dynamic/foo.list b/ld/testsuite/ld-dynamic/foo.list
new file mode 100644
index 0000000000..f89f569438
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo.list
@@ -0,0 +1 @@
+{ foo; };
diff --git a/ld/testsuite/ld-dynamic/foo.s b/ld/testsuite/ld-dynamic/foo.s
new file mode 100644
index 0000000000..4a70181776
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo.s
@@ -0,0 +1,4 @@
+	.text
+	.globl foo
+foo:
+	.byte 0
diff --git a/ld/testsuite/ld-dynamic/fstar.list b/ld/testsuite/ld-dynamic/fstar.list
new file mode 100644
index 0000000000..330d1dd2b8
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/fstar.list
@@ -0,0 +1 @@
+{ f*; };
diff --git a/ld/testsuite/ld-elf/dlempty.list b/ld/testsuite/ld-elf/dlempty.list
new file mode 100644
index 0000000000..9b3884b10e
--- /dev/null
+++ b/ld/testsuite/ld-elf/dlempty.list
@@ -0,0 +1,3 @@
+{
+  empty;
+};
diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
index 7d35f3f379..5606c9937f 100644
--- a/ld/testsuite/ld-elf/shared.exp
+++ b/ld/testsuite/ld-elf/shared.exp
@@ -601,6 +601,27 @@ set build_tests {
   {"Build libdl2d.so with --dynamic-list-data -Bsymbolic"
    "-shared -Wl,-Bsymbolic,--dynamic-list-data" "-fPIC"
    {dl2.c dl2xxx.c} {} "libdl2d.so"}
+  {"Build libdl2e.so with --export-dynamic-symbol=foo"
+   "-shared -Wl,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2e.so"}
+  {"Build libdl2f.so with --dynamic-list=dlempty.list and --export-dynamic-symbol=foo"
+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2f.so"}
+  {"Build libdl2g.so with --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2g.so"}
+  {"Build libdl2h.so with --dynamic-list=dlempty.list and --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2h.so"}
+  {"Build libdl2i.so with -Bsymbolic and --export-dynamic-symbol=foo"
+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2i.so"}
+  {"Build libdl2j.so with -Bsymbolic and --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2j.so"}
+  {"Build libdl2k.so with --export-dynamic-symbol-list=dl2.list and -Bsymbolic"
+   "-shared -Wl,--export-dynamic-symbol-list=dl2.list,-Bsymbolic" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2k.so"}
   {"Build libdl4a.so with --dynamic-list=dl4.list"
    "-shared -Wl,--dynamic-list=dl4.list" "-fPIC"
    {dl4.c dl4xxx.c} {} "libdl4a.so"}
@@ -880,6 +901,27 @@ set run_tests [list \
     [list "Run with libdl2d.so" \
      "-Wl,--no-as-needed tmpdir/libdl2d.so" "" \
      {dl2main.c} "dl2d" "dl2a.out" ] \
+    [list "Run with libdl2e.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2e.so" "" \
+     {dl2main.c} "dl2e" "dl2b.out" ] \
+    [list "Run with libdl2f.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2f.so" "" \
+     {dl2main.c} "dl2f" "dl2a.out" ] \
+    [list "Run with libdl2g.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2g.so" "" \
+     {dl2main.c} "dl2g" "dl2b.out" ] \
+    [list "Run with libdl2h.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2h.so" "" \
+     {dl2main.c} "dl2h" "dl2a.out" ] \
+    [list "Run with libdl2i.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2i.so" "" \
+     {dl2main.c} "dl2i" "dl2a.out" ] \
+    [list "Run with libdl2j.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2j.so" "" \
+     {dl2main.c} "dl2j" "dl2a.out" ] \
+    [list "Run with libdl2k.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2k.so" "" \
+     {dl2main.c} "dl2k" "dl2a.out" ] \
     [list "Run with libdl4a.so" \
      "-Wl,--no-as-needed tmpdir/libdl4a.so" "" \
      {dl4main.c} "dl4a" "dl4a.out" ] \
-- 
2.26.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: V4 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list
  2020-05-27 14:29       ` V4 " H.J. Lu
@ 2020-05-27 16:19         ` Fangrui Song
  2020-05-27 16:24           ` H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: Fangrui Song @ 2020-05-27 16:19 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

On 2020-05-27, H.J. Lu wrote:
>On Sat, May 23, 2020 at 2:56 PM Fangrui Song <maskray@google.com> wrote:
>>
>> On 2020-05-23, H.J. Lu wrote:
>> >On Sat, May 23, 2020 at 11:29 AM Fangrui Song <maskray@google.com> wrote:
>> >>
>> >> On 2020-05-23, H.J. Lu wrote:
>> >> >From: Fangrui Song <maskray@google.com>
>> >> >
>> >> >--export-dynamic-symbol-list is like a dynamic list, but without
>> >> >the symbolic property for unspecified symbols.
>> >> >
>> >> >When creating an executable, --export-dynamic-symbol-list is treated
>> >> >like --dynamic-list.
>> >> >
>> >> >When creating a shared library, it is treated like --dynamic-list if
>> >> >-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
>> >> >that references to matched symbols will not be bound to the definitions
>> >> >within the shared library.
>> >> >
>> >> >2020-05-XX  Fangrui Song  <maskray@google.com>
>> >> >           H.J. Lu  <hongjiu.lu@intel.com>
>> >> >
>> >> >       PR ld/25910
>> >> >       * NEWS: Mention --export-dynamic-symbol[-list].
>> >> >       * ld.texi: Document --export-dynamic-symbol[-list].
>> >> >       * ldgram.y: Pass current_dynamic_list_p to
>> >> >       lang_append_dynamic_list.
>> >> >       * ldlang.c (current_dynamic_list_p): New.
>> >> >       (ang_append_dynamic_list): Updated to take a pointer to
>> >> >       struct bfd_elf_dynamic_list * argument instead of using
>> >> >       link_info.dynamic_list.
>> >> >       (lang_append_dynamic_list_cpp_typeinfo): Pass
>> >> >       &link_info.dynamic_list to ang_append_dynamic_list.
>> >> >       (lang_append_dynamic_list_cpp_new): Likewise.
>> >> >       * ldlang.h (current_dynamic_list_p): New.
>> >> >       (lang_append_dynamic_list): Add a pointer to
>> >> >       struct bfd_elf_dynamic_list * argument.
>> >> >       * ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
>> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
>> >> >       * lexsup.c (ld_options): Add entries for
>> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL and
>> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
>> >> >       (parse_args): Handle --export-dynamic-symbol and
>> >> >       --export-dynamic-symbol-list.
>> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
>> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
>> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
>> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
>> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
>> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
>> >> >       * testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
>> >> >       * testsuite/ld-dynamic/export-dynamic-symbol.s: New.
>> >> >       * testsuite/ld-dynamic/foo-bar.list: New.
>> >> >       * testsuite/ld-dynamic/foo.list: New.
>> >> >       * testsuite/ld-dynamic/foo.s: New.
>> >> >       * testsuite/ld-dynamic/fstar.list: New.
>> >> >       * testsuite/ld-elf/dlempty.list: New.
>> >> >       * testsuite/ld-elf/shared.exp: Add tests for
>> >> >       --export-dynamic-symbol and --export-dynamic-symbol-list.
>> >> >---
>> >> > ld/NEWS                                       |  3 +
>> >> > ld/ld.texi                                    | 18 +++++
>> >> > ld/ldgram.y                                   |  2 +-
>> >> > ld/ldlang.c                                   | 16 ++--
>> >> > ld/ldlang.h                                   |  5 +-
>> >> > ld/ldlex.h                                    |  2 +
>> >> > ld/lexsup.c                                   | 75 +++++++++++++++++++
>> >> > .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
>> >> > .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
>> >> > .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 ++
>> >> > .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
>> >> > .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
>> >> > .../export-dynamic-symbol-list-glob.d         |  8 ++
>> >> > .../ld-dynamic/export-dynamic-symbol.exp      | 39 ++++++++++
>> >> > .../ld-dynamic/export-dynamic-symbol.s        |  9 +++
>> >> > ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
>> >> > ld/testsuite/ld-dynamic/foo.list              |  1 +
>> >> > ld/testsuite/ld-dynamic/foo.s                 |  4 +
>> >> > ld/testsuite/ld-dynamic/fstar.list            |  1 +
>> >> > ld/testsuite/ld-elf/dlempty.list              |  3 +
>> >> > ld/testsuite/ld-elf/shared.exp                | 36 +++++++++
>> >> > 21 files changed, 258 insertions(+), 9 deletions(-)
>> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
>> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
>> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
>> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
>> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
>> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
>> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
>> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
>> >> > create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
>> >> > create mode 100644 ld/testsuite/ld-dynamic/foo.list
>> >> > create mode 100644 ld/testsuite/ld-dynamic/foo.s
>> >> > create mode 100644 ld/testsuite/ld-dynamic/fstar.list
>> >> > create mode 100644 ld/testsuite/ld-elf/dlempty.list
>> >> >
>> >> >diff --git a/ld/NEWS b/ld/NEWS
>> >> >index 9f5bbe51cf..870c480bde 100644
>> >> >--- a/ld/NEWS
>> >> >+++ b/ld/NEWS
>> >> >@@ -1,5 +1,8 @@
>> >> > -*- text -*-
>> >> >
>> >> >+* Add ELF linker command-line options, --export-dynamic-symbol and
>> >> >+  --export-dynamic-symbol-list, to make symbols dynamic.
>> >> >+
>> >> > * Add command-line options --enable-non-contiguous-regions and
>> >> >   --enable-non-contiguous-regions-warnings.
>> >> >
>> >> >diff --git a/ld/ld.texi b/ld/ld.texi
>> >> >index 4dc78e65fa..92e47c6324 100644
>> >> >--- a/ld/ld.texi
>> >> >+++ b/ld/ld.texi
>> >> >@@ -569,6 +569,24 @@ 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{glob}
>> >> >+@cindex export dynamic symbol
>> >> >+@item --export-dynamic-symbol=@var{glob}
>> >> >+When creating a dynamically linked executable, symbols matching
>> >> >+@var{glob} will be added to the dynamic symbol table. When creating a
>> >> >+shared library, references to symbols matching @var{glob} will not be
>> >> >+bound to the definitions within the shared library. This option is a
>> >> >+no-op when creating a shared library and @samp{-Bsymbolic} or
>> >> >+@samp{--dynamic-list} are not specified. This option is only meaningful
>> >> >+on ELF platforms which support shared libraries.
>> >>
>> >> Is --export-dynamic-symbol still effective for -shared?
>> >> I think either way is ok.
>> >
>> >Yes.
>> >
>> >> >+@kindex --export-dynamic-symbol-list=@var{file}
>> >> >+@cindex export dynamic symbol list
>> >> >+@item --export-dynamic-symbol-list=@var{file}
>> >> >+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
>> >> >+The format of the file is the same as the version node without
>> >> >+scope and node name.  See @ref{VERSION} for more information.
>> >> >+
>> >> > @ifclear SingleFormat
>> >> > @cindex big-endian objects
>> >> > @cindex endianness
>> >> >diff --git a/ld/ldgram.y b/ld/ldgram.y
>> >> >index df5c035c03..36845c4c30 100644
>> >> >--- a/ld/ldgram.y
>> >> >+++ b/ld/ldgram.y
>> >> >@@ -1313,7 +1313,7 @@ dynamic_list_node:
>> >> > dynamic_list_tag:
>> >> >               vers_defns ';'
>> >> >               {
>> >> >-                lang_append_dynamic_list ($1);
>> >> >+                lang_append_dynamic_list (current_dynamic_list_p, $1);
>> >> >               }
>> >> >       ;
>> >> >
>> >> >diff --git a/ld/ldlang.c b/ld/ldlang.c
>> >> >index 3d653d460d..14a6a577d2 100644
>> >> >--- a/ld/ldlang.c
>> >> >+++ b/ld/ldlang.c
>> >> >@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
>> >> >    lang_statement_union).  */
>> >> > lang_statement_list_type input_file_chain;
>> >> > static const char *current_input_file;
>> >> >+struct bfd_elf_dynamic_list **current_dynamic_list_p;
>> >> > struct bfd_sym_chain entry_symbol = { NULL, NULL };
>> >> > const char *entry_section = ".text";
>> >> > struct lang_input_statement_flags input_flags;
>> >> >@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
>> >> > /* Append the list of dynamic symbols to the existing one.  */
>> >> >
>> >> > void
>> >> >-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
>> >> >+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
>> >> >+                        struct bfd_elf_version_expr *dynamic)
>> >> > {
>> >> >-  if (link_info.dynamic_list)
>> >> >+  if (*list_p)
>> >> >     {
>> >> >       struct bfd_elf_version_expr *tail;
>> >> >       for (tail = dynamic; tail->next != NULL; tail = tail->next)
>> >> >       ;
>> >> >-      tail->next = link_info.dynamic_list->head.list;
>> >> >-      link_info.dynamic_list->head.list = dynamic;
>> >> >+      tail->next = (*list_p)->head.list;
>> >> >+      (*list_p)->head.list = dynamic;
>> >> >     }
>> >> >   else
>> >> >     {
>> >> >@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
>> >> >       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
>> >> >       d->head.list = dynamic;
>> >> >       d->match = lang_vers_match;
>> >> >-      link_info.dynamic_list = d;
>> >> >+      *list_p = d;
>> >> >     }
>> >> > }
>> >> >
>> >> >@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
>> >> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
>> >> >                                    FALSE);
>> >> >
>> >> >-  lang_append_dynamic_list (dynamic);
>> >> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
>> >> > }
>> >> >
>> >> > /* Append the list of C++ operator new and delete dynamic symbols to the
>> >> >@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
>> >> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
>> >> >                                    FALSE);
>> >> >
>> >> >-  lang_append_dynamic_list (dynamic);
>> >> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
>> >> > }
>> >> >
>> >> > /* Scan a space and/or comma separated string of features.  */
>> >> >diff --git a/ld/ldlang.h b/ld/ldlang.h
>> >> >index 3018c3e2ba..529ccd1585 100644
>> >> >--- a/ld/ldlang.h
>> >> >+++ b/ld/ldlang.h
>> >> >@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
>> >> > extern lang_statement_list_type file_chain;
>> >> > extern lang_statement_list_type input_file_chain;
>> >> >
>> >> >+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
>> >> >+
>> >> > extern int lang_statement_iteration;
>> >> > extern struct asneeded_minfo **asneeded_list_tail;
>> >> >
>> >> >@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
>> >> >   (struct bfd_elf_version_deps *, const char *);
>> >> > extern void lang_register_vers_node
>> >> >   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
>> >> >-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
>> >> >+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
>> >> >+                                    struct bfd_elf_version_expr *);
>> >> > extern void lang_append_dynamic_list_cpp_typeinfo (void);
>> >> > extern void lang_append_dynamic_list_cpp_new (void);
>> >> > extern void lang_add_unique
>> >> >diff --git a/ld/ldlex.h b/ld/ldlex.h
>> >> >index 22b928d2d9..2c8d043a09 100644
>> >> >--- a/ld/ldlex.h
>> >> >+++ b/ld/ldlex.h
>> >> >@@ -81,6 +81,8 @@ enum option_values
>> >> >   OPTION_DYNAMIC_LIST_CPP_NEW,
>> >> >   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
>> >> >   OPTION_DYNAMIC_LIST_DATA,
>> >> >+  OPTION_EXPORT_DYNAMIC_SYMBOL,
>> >> >+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
>> >> >   OPTION_WARN_COMMON,
>> >> >   OPTION_WARN_CONSTRUCTORS,
>> >> >   OPTION_WARN_FATAL,
>> >> >diff --git a/ld/lexsup.c b/ld/lexsup.c
>> >> >index fe9526b527..2bac1631d6 100644
>> >> >--- a/ld/lexsup.c
>> >> >+++ b/ld/lexsup.c
>> >> >@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
>> >> >+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
>> >> >+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
>> >> >@@ -581,6 +585,7 @@ parse_args (unsigned argc, char **argv)
>> >> >     dynamic_list_data,
>> >> >     dynamic_list
>> >> >   } opt_dynamic_list = dynamic_list_unset;
>> >> >+  struct bfd_elf_dynamic_list *export_list = NULL;
>> >> >
>> >> >   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
>> >> >   longopts = (struct option *)
>> >> >@@ -1418,6 +1423,7 @@ parse_args (unsigned argc, char **argv)
>> >> >           ldfile_open_command_file (optarg);
>> >> >           saved_script_handle = hold_script_handle;
>> >> >           parser_input = input_dynamic_list;
>> >> >+          current_dynamic_list_p = &link_info.dynamic_list;
>> >> >           yyparse ();
>> >> >         }
>> >> >         if (opt_dynamic_list != dynamic_list_data)
>> >> >@@ -1425,6 +1431,29 @@ parse_args (unsigned argc, char **argv)
>> >> >         if (opt_symbolic == symbolic)
>> >> >           opt_symbolic = symbolic_unset;
>> >> >         break;
>> >> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL:
>> >> >+        {
>> >> >+          struct bfd_elf_version_expr *expr
>> >> >+            = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
>> >> >+                                     FALSE);
>> >> >+          lang_append_dynamic_list (&export_list, expr);
>> >> >+          }
>> >> >+        break;
>> >> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
>> >> >+        /* This option indicates a small script that only specifies
>> >> >+           an export list.  Read it, but don't assume that we've
>> >> >+           seen a linker script.  */
>> >> >+        {
>> >> >+          FILE *hold_script_handle;
>> >> >+
>> >> >+          hold_script_handle = saved_script_handle;
>> >> >+          ldfile_open_command_file (optarg);
>> >> >+          saved_script_handle = hold_script_handle;
>> >> >+          parser_input = input_dynamic_list;
>> >> >+          current_dynamic_list_p = &export_list;
>> >> >+          yyparse ();
>> >> >+        }
>> >> >+        break;
>> >> >       case OPTION_WARN_COMMON:
>> >> >         config.warn_common = TRUE;
>> >> >         break;
>> >> >@@ -1632,6 +1661,52 @@ parse_args (unsigned argc, char **argv)
>> >> >       && command_line.check_section_addresses < 0)
>> >> >     command_line.check_section_addresses = 0;
>> >> >
>> >> >+  if (export_list && !bfd_link_relocatable (&link_info))
>> >> >+    {
>> >> >+      struct bfd_elf_version_expr *head = export_list->head.list;
>> >> >+      struct bfd_elf_version_expr *next;
>> >> >+
>> >> >+      /* For --export-dynamic-symbol[-list]:
>> >> >+       1. When building executable, treat like --dynamic-list.
>> >> >+       2. When building shared object:
>> >> >+          a. If -Bsymbolic or --dynamic-list are used, treat like
>> >> >+             --dynamic-list.
>> >> >+          b. Otherwise, ignored.
>> >> >+       */
>> >> >+      bfd_boolean kept = (bfd_link_executable (&link_info)
>> >> >+                        || opt_symbolic != symbolic_unset
>> >> >+                        || opt_dynamic_list != dynamic_list_unset);
>> >> >+
>> >> >+      if (kept)
>> >> >+      {
>> >> >+        /* Append the export list to link_info.dynamic_list.  */
>> >> >+        if (link_info.dynamic_list)
>> >> >+          {
>> >> >+            for (next = head; next->next != NULL; next = next->next)
>> >> >+              ;
>> >> >+            next->next = link_info.dynamic_list->head.list;
>> >> >+            link_info.dynamic_list->head.list = head;
>> >> >+          }
>> >> >+        else
>> >> >+          link_info.dynamic_list = export_list;
>> >> >+
>> >> >+        if (opt_dynamic_list != dynamic_list_data)
>> >> >+          opt_dynamic_list = dynamic_list;
>> >> >+        if (opt_symbolic == symbolic)
>> >> >+          opt_symbolic = symbolic_unset;
>> >>
>> >> The interaction with -Bsymbolic appears to be more complex now.
>> >> I think users will pretty much avoid the combination of -Bsymbolic and
>> >> (--dynamic-list or --export-dynamic-symbol or --export-dynamic-symbol-list).
>> >>
>> >> So I beg for a re-consideration of
>> >> https://sourceware.org/bugzilla/show_bug.cgi?id=26018
>> >> https://sourceware.org/pipermail/binutils/2020-May/111223.html
>> >>
>> >
>> >Here is the updated patch on top of
>> >
>> >https://sourceware.org/pipermail/binutils/2020-May/111228.html
>>
>> Thanks for PATCH v3. LGTM.
>>
>> I have verified the semantics of new tests dl2d ~ dl2k.
>
>The updated patch to adjust ld-dynamic/export-dynamic-symbol.s
>for all ELF targets:
>
>diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
>b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
>index 4b1b8ebd5c..c55da536c5 100644
>--- a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
>+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
>@@ -1,6 +1,14 @@
>   .text
>+  .global start  /* Used by SH targets.  */
>+start:
>   .global _start
> _start:
>+  .global __start
>+__start:
>+  .global main   /* Used by HPPA targets.  */
>+main:
>+  .globl   _main /* Used by LynxOS targets.  */
>+_main:
>   .word 0
>
>   .section .text.1, "ax"
>
>-- 
>H.J.

Still looks good.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: V4 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list
  2020-05-27 16:19         ` Fangrui Song
@ 2020-05-27 16:24           ` H.J. Lu
  2020-05-27 20:24             ` V5 " H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2020-05-27 16:24 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils

On Wed, May 27, 2020 at 9:19 AM Fangrui Song <maskray@google.com> wrote:
>
> On 2020-05-27, H.J. Lu wrote:
> >On Sat, May 23, 2020 at 2:56 PM Fangrui Song <maskray@google.com> wrote:
> >>
> >> On 2020-05-23, H.J. Lu wrote:
> >> >On Sat, May 23, 2020 at 11:29 AM Fangrui Song <maskray@google.com> wrote:
> >> >>
> >> >> On 2020-05-23, H.J. Lu wrote:
> >> >> >From: Fangrui Song <maskray@google.com>
> >> >> >
> >> >> >--export-dynamic-symbol-list is like a dynamic list, but without
> >> >> >the symbolic property for unspecified symbols.
> >> >> >
> >> >> >When creating an executable, --export-dynamic-symbol-list is treated
> >> >> >like --dynamic-list.
> >> >> >
> >> >> >When creating a shared library, it is treated like --dynamic-list if
> >> >> >-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
> >> >> >that references to matched symbols will not be bound to the definitions
> >> >> >within the shared library.
> >> >> >
> >> >> >2020-05-XX  Fangrui Song  <maskray@google.com>
> >> >> >           H.J. Lu  <hongjiu.lu@intel.com>
> >> >> >
> >> >> >       PR ld/25910
> >> >> >       * NEWS: Mention --export-dynamic-symbol[-list].
> >> >> >       * ld.texi: Document --export-dynamic-symbol[-list].
> >> >> >       * ldgram.y: Pass current_dynamic_list_p to
> >> >> >       lang_append_dynamic_list.
> >> >> >       * ldlang.c (current_dynamic_list_p): New.
> >> >> >       (ang_append_dynamic_list): Updated to take a pointer to
> >> >> >       struct bfd_elf_dynamic_list * argument instead of using
> >> >> >       link_info.dynamic_list.
> >> >> >       (lang_append_dynamic_list_cpp_typeinfo): Pass
> >> >> >       &link_info.dynamic_list to ang_append_dynamic_list.
> >> >> >       (lang_append_dynamic_list_cpp_new): Likewise.
> >> >> >       * ldlang.h (current_dynamic_list_p): New.
> >> >> >       (lang_append_dynamic_list): Add a pointer to
> >> >> >       struct bfd_elf_dynamic_list * argument.
> >> >> >       * ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
> >> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
> >> >> >       * lexsup.c (ld_options): Add entries for
> >> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL and
> >> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
> >> >> >       (parse_args): Handle --export-dynamic-symbol and
> >> >> >       --export-dynamic-symbol-list.
> >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
> >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
> >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
> >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
> >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
> >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
> >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
> >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol.s: New.
> >> >> >       * testsuite/ld-dynamic/foo-bar.list: New.
> >> >> >       * testsuite/ld-dynamic/foo.list: New.
> >> >> >       * testsuite/ld-dynamic/foo.s: New.
> >> >> >       * testsuite/ld-dynamic/fstar.list: New.
> >> >> >       * testsuite/ld-elf/dlempty.list: New.
> >> >> >       * testsuite/ld-elf/shared.exp: Add tests for
> >> >> >       --export-dynamic-symbol and --export-dynamic-symbol-list.
> >> >> >---
> >> >> > ld/NEWS                                       |  3 +
> >> >> > ld/ld.texi                                    | 18 +++++
> >> >> > ld/ldgram.y                                   |  2 +-
> >> >> > ld/ldlang.c                                   | 16 ++--
> >> >> > ld/ldlang.h                                   |  5 +-
> >> >> > ld/ldlex.h                                    |  2 +
> >> >> > ld/lexsup.c                                   | 75 +++++++++++++++++++
> >> >> > .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
> >> >> > .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
> >> >> > .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 ++
> >> >> > .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
> >> >> > .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
> >> >> > .../export-dynamic-symbol-list-glob.d         |  8 ++
> >> >> > .../ld-dynamic/export-dynamic-symbol.exp      | 39 ++++++++++
> >> >> > .../ld-dynamic/export-dynamic-symbol.s        |  9 +++
> >> >> > ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
> >> >> > ld/testsuite/ld-dynamic/foo.list              |  1 +
> >> >> > ld/testsuite/ld-dynamic/foo.s                 |  4 +
> >> >> > ld/testsuite/ld-dynamic/fstar.list            |  1 +
> >> >> > ld/testsuite/ld-elf/dlempty.list              |  3 +
> >> >> > ld/testsuite/ld-elf/shared.exp                | 36 +++++++++
> >> >> > 21 files changed, 258 insertions(+), 9 deletions(-)
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/foo.list
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/foo.s
> >> >> > create mode 100644 ld/testsuite/ld-dynamic/fstar.list
> >> >> > create mode 100644 ld/testsuite/ld-elf/dlempty.list
> >> >> >
> >> >> >diff --git a/ld/NEWS b/ld/NEWS
> >> >> >index 9f5bbe51cf..870c480bde 100644
> >> >> >--- a/ld/NEWS
> >> >> >+++ b/ld/NEWS
> >> >> >@@ -1,5 +1,8 @@
> >> >> > -*- text -*-
> >> >> >
> >> >> >+* Add ELF linker command-line options, --export-dynamic-symbol and
> >> >> >+  --export-dynamic-symbol-list, to make symbols dynamic.
> >> >> >+
> >> >> > * Add command-line options --enable-non-contiguous-regions and
> >> >> >   --enable-non-contiguous-regions-warnings.
> >> >> >
> >> >> >diff --git a/ld/ld.texi b/ld/ld.texi
> >> >> >index 4dc78e65fa..92e47c6324 100644
> >> >> >--- a/ld/ld.texi
> >> >> >+++ b/ld/ld.texi
> >> >> >@@ -569,6 +569,24 @@ 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{glob}
> >> >> >+@cindex export dynamic symbol
> >> >> >+@item --export-dynamic-symbol=@var{glob}
> >> >> >+When creating a dynamically linked executable, symbols matching
> >> >> >+@var{glob} will be added to the dynamic symbol table. When creating a
> >> >> >+shared library, references to symbols matching @var{glob} will not be
> >> >> >+bound to the definitions within the shared library. This option is a
> >> >> >+no-op when creating a shared library and @samp{-Bsymbolic} or
> >> >> >+@samp{--dynamic-list} are not specified. This option is only meaningful
> >> >> >+on ELF platforms which support shared libraries.
> >> >>
> >> >> Is --export-dynamic-symbol still effective for -shared?
> >> >> I think either way is ok.
> >> >
> >> >Yes.
> >> >
> >> >> >+@kindex --export-dynamic-symbol-list=@var{file}
> >> >> >+@cindex export dynamic symbol list
> >> >> >+@item --export-dynamic-symbol-list=@var{file}
> >> >> >+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
> >> >> >+The format of the file is the same as the version node without
> >> >> >+scope and node name.  See @ref{VERSION} for more information.
> >> >> >+
> >> >> > @ifclear SingleFormat
> >> >> > @cindex big-endian objects
> >> >> > @cindex endianness
> >> >> >diff --git a/ld/ldgram.y b/ld/ldgram.y
> >> >> >index df5c035c03..36845c4c30 100644
> >> >> >--- a/ld/ldgram.y
> >> >> >+++ b/ld/ldgram.y
> >> >> >@@ -1313,7 +1313,7 @@ dynamic_list_node:
> >> >> > dynamic_list_tag:
> >> >> >               vers_defns ';'
> >> >> >               {
> >> >> >-                lang_append_dynamic_list ($1);
> >> >> >+                lang_append_dynamic_list (current_dynamic_list_p, $1);
> >> >> >               }
> >> >> >       ;
> >> >> >
> >> >> >diff --git a/ld/ldlang.c b/ld/ldlang.c
> >> >> >index 3d653d460d..14a6a577d2 100644
> >> >> >--- a/ld/ldlang.c
> >> >> >+++ b/ld/ldlang.c
> >> >> >@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
> >> >> >    lang_statement_union).  */
> >> >> > lang_statement_list_type input_file_chain;
> >> >> > static const char *current_input_file;
> >> >> >+struct bfd_elf_dynamic_list **current_dynamic_list_p;
> >> >> > struct bfd_sym_chain entry_symbol = { NULL, NULL };
> >> >> > const char *entry_section = ".text";
> >> >> > struct lang_input_statement_flags input_flags;
> >> >> >@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
> >> >> > /* Append the list of dynamic symbols to the existing one.  */
> >> >> >
> >> >> > void
> >> >> >-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
> >> >> >+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
> >> >> >+                        struct bfd_elf_version_expr *dynamic)
> >> >> > {
> >> >> >-  if (link_info.dynamic_list)
> >> >> >+  if (*list_p)
> >> >> >     {
> >> >> >       struct bfd_elf_version_expr *tail;
> >> >> >       for (tail = dynamic; tail->next != NULL; tail = tail->next)
> >> >> >       ;
> >> >> >-      tail->next = link_info.dynamic_list->head.list;
> >> >> >-      link_info.dynamic_list->head.list = dynamic;
> >> >> >+      tail->next = (*list_p)->head.list;
> >> >> >+      (*list_p)->head.list = dynamic;
> >> >> >     }
> >> >> >   else
> >> >> >     {
> >> >> >@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
> >> >> >       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
> >> >> >       d->head.list = dynamic;
> >> >> >       d->match = lang_vers_match;
> >> >> >-      link_info.dynamic_list = d;
> >> >> >+      *list_p = d;
> >> >> >     }
> >> >> > }
> >> >> >
> >> >> >@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
> >> >> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
> >> >> >                                    FALSE);
> >> >> >
> >> >> >-  lang_append_dynamic_list (dynamic);
> >> >> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
> >> >> > }
> >> >> >
> >> >> > /* Append the list of C++ operator new and delete dynamic symbols to the
> >> >> >@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
> >> >> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
> >> >> >                                    FALSE);
> >> >> >
> >> >> >-  lang_append_dynamic_list (dynamic);
> >> >> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
> >> >> > }
> >> >> >
> >> >> > /* Scan a space and/or comma separated string of features.  */
> >> >> >diff --git a/ld/ldlang.h b/ld/ldlang.h
> >> >> >index 3018c3e2ba..529ccd1585 100644
> >> >> >--- a/ld/ldlang.h
> >> >> >+++ b/ld/ldlang.h
> >> >> >@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
> >> >> > extern lang_statement_list_type file_chain;
> >> >> > extern lang_statement_list_type input_file_chain;
> >> >> >
> >> >> >+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
> >> >> >+
> >> >> > extern int lang_statement_iteration;
> >> >> > extern struct asneeded_minfo **asneeded_list_tail;
> >> >> >
> >> >> >@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
> >> >> >   (struct bfd_elf_version_deps *, const char *);
> >> >> > extern void lang_register_vers_node
> >> >> >   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
> >> >> >-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
> >> >> >+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
> >> >> >+                                    struct bfd_elf_version_expr *);
> >> >> > extern void lang_append_dynamic_list_cpp_typeinfo (void);
> >> >> > extern void lang_append_dynamic_list_cpp_new (void);
> >> >> > extern void lang_add_unique
> >> >> >diff --git a/ld/ldlex.h b/ld/ldlex.h
> >> >> >index 22b928d2d9..2c8d043a09 100644
> >> >> >--- a/ld/ldlex.h
> >> >> >+++ b/ld/ldlex.h
> >> >> >@@ -81,6 +81,8 @@ enum option_values
> >> >> >   OPTION_DYNAMIC_LIST_CPP_NEW,
> >> >> >   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
> >> >> >   OPTION_DYNAMIC_LIST_DATA,
> >> >> >+  OPTION_EXPORT_DYNAMIC_SYMBOL,
> >> >> >+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
> >> >> >   OPTION_WARN_COMMON,
> >> >> >   OPTION_WARN_CONSTRUCTORS,
> >> >> >   OPTION_WARN_FATAL,
> >> >> >diff --git a/ld/lexsup.c b/ld/lexsup.c
> >> >> >index fe9526b527..2bac1631d6 100644
> >> >> >--- a/ld/lexsup.c
> >> >> >+++ b/ld/lexsup.c
> >> >> >@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
> >> >> >+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
> >> >> >+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
> >> >> >@@ -581,6 +585,7 @@ parse_args (unsigned argc, char **argv)
> >> >> >     dynamic_list_data,
> >> >> >     dynamic_list
> >> >> >   } opt_dynamic_list = dynamic_list_unset;
> >> >> >+  struct bfd_elf_dynamic_list *export_list = NULL;
> >> >> >
> >> >> >   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
> >> >> >   longopts = (struct option *)
> >> >> >@@ -1418,6 +1423,7 @@ parse_args (unsigned argc, char **argv)
> >> >> >           ldfile_open_command_file (optarg);
> >> >> >           saved_script_handle = hold_script_handle;
> >> >> >           parser_input = input_dynamic_list;
> >> >> >+          current_dynamic_list_p = &link_info.dynamic_list;
> >> >> >           yyparse ();
> >> >> >         }
> >> >> >         if (opt_dynamic_list != dynamic_list_data)
> >> >> >@@ -1425,6 +1431,29 @@ parse_args (unsigned argc, char **argv)
> >> >> >         if (opt_symbolic == symbolic)
> >> >> >           opt_symbolic = symbolic_unset;
> >> >> >         break;
> >> >> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL:
> >> >> >+        {
> >> >> >+          struct bfd_elf_version_expr *expr
> >> >> >+            = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
> >> >> >+                                     FALSE);
> >> >> >+          lang_append_dynamic_list (&export_list, expr);
> >> >> >+          }
> >> >> >+        break;
> >> >> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
> >> >> >+        /* This option indicates a small script that only specifies
> >> >> >+           an export list.  Read it, but don't assume that we've
> >> >> >+           seen a linker script.  */
> >> >> >+        {
> >> >> >+          FILE *hold_script_handle;
> >> >> >+
> >> >> >+          hold_script_handle = saved_script_handle;
> >> >> >+          ldfile_open_command_file (optarg);
> >> >> >+          saved_script_handle = hold_script_handle;
> >> >> >+          parser_input = input_dynamic_list;
> >> >> >+          current_dynamic_list_p = &export_list;
> >> >> >+          yyparse ();
> >> >> >+        }
> >> >> >+        break;
> >> >> >       case OPTION_WARN_COMMON:
> >> >> >         config.warn_common = TRUE;
> >> >> >         break;
> >> >> >@@ -1632,6 +1661,52 @@ parse_args (unsigned argc, char **argv)
> >> >> >       && command_line.check_section_addresses < 0)
> >> >> >     command_line.check_section_addresses = 0;
> >> >> >
> >> >> >+  if (export_list && !bfd_link_relocatable (&link_info))
> >> >> >+    {
> >> >> >+      struct bfd_elf_version_expr *head = export_list->head.list;
> >> >> >+      struct bfd_elf_version_expr *next;
> >> >> >+
> >> >> >+      /* For --export-dynamic-symbol[-list]:
> >> >> >+       1. When building executable, treat like --dynamic-list.
> >> >> >+       2. When building shared object:
> >> >> >+          a. If -Bsymbolic or --dynamic-list are used, treat like
> >> >> >+             --dynamic-list.
> >> >> >+          b. Otherwise, ignored.
> >> >> >+       */
> >> >> >+      bfd_boolean kept = (bfd_link_executable (&link_info)
> >> >> >+                        || opt_symbolic != symbolic_unset
> >> >> >+                        || opt_dynamic_list != dynamic_list_unset);
> >> >> >+
> >> >> >+      if (kept)
> >> >> >+      {
> >> >> >+        /* Append the export list to link_info.dynamic_list.  */
> >> >> >+        if (link_info.dynamic_list)
> >> >> >+          {
> >> >> >+            for (next = head; next->next != NULL; next = next->next)
> >> >> >+              ;
> >> >> >+            next->next = link_info.dynamic_list->head.list;
> >> >> >+            link_info.dynamic_list->head.list = head;
> >> >> >+          }
> >> >> >+        else
> >> >> >+          link_info.dynamic_list = export_list;
> >> >> >+
> >> >> >+        if (opt_dynamic_list != dynamic_list_data)
> >> >> >+          opt_dynamic_list = dynamic_list;
> >> >> >+        if (opt_symbolic == symbolic)
> >> >> >+          opt_symbolic = symbolic_unset;
> >> >>
> >> >> The interaction with -Bsymbolic appears to be more complex now.
> >> >> I think users will pretty much avoid the combination of -Bsymbolic and
> >> >> (--dynamic-list or --export-dynamic-symbol or --export-dynamic-symbol-list).
> >> >>
> >> >> So I beg for a re-consideration of
> >> >> https://sourceware.org/bugzilla/show_bug.cgi?id=26018
> >> >> https://sourceware.org/pipermail/binutils/2020-May/111223.html
> >> >>
> >> >
> >> >Here is the updated patch on top of
> >> >
> >> >https://sourceware.org/pipermail/binutils/2020-May/111228.html
> >>
> >> Thanks for PATCH v3. LGTM.
> >>
> >> I have verified the semantics of new tests dl2d ~ dl2k.
> >
> >The updated patch to adjust ld-dynamic/export-dynamic-symbol.s
> >for all ELF targets:
> >
> >diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> >b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> >index 4b1b8ebd5c..c55da536c5 100644
> >--- a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> >+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> >@@ -1,6 +1,14 @@
> >   .text
> >+  .global start  /* Used by SH targets.  */
> >+start:
> >   .global _start
> > _start:
> >+  .global __start
> >+__start:
> >+  .global main   /* Used by HPPA targets.  */
> >+main:
> >+  .globl   _main /* Used by LynxOS targets.  */
> >+_main:
> >   .word 0
> >
> >   .section .text.1, "ax"
> >
> >--
> >H.J.
>
> Still looks good.

More changes are needed:
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
index d0b4bc4eb0..c879a5f65f 100644
--- a/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
@@ -23,6 +23,26 @@ if ![is_elf_format] {
     return
 }

+# Skip targets where -shared is not supported
+
+if ![check_shared_lib_support] {
+    return
+}
+
+set old_ASFLAGS $ASFLAGS
+
+# These targets require extra GAS options when building code for shared
+# libraries.
+if [istarget "nds32*-*"] {
+    append ASFLAGS " -mpic"
+}
+if [istarget "tic6x-*-*"] {
+    append ASFLAGS " -mpic -mpid=near"
+}
+if [istarget "sparc*-*-*"] {
+    append ASFLAGS " -K PIC -Av9"
+}
+
 set build_tests {
   {"Build libfoo.a"
    "" "" ""
@@ -37,3 +57,5 @@ foreach test_file $test_list {
     verbose $test_name
     run_dump_test $test_name
 }
+
+set ASFLAGS $old_ASFLAGS

-- 
H.J.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* V5 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list
  2020-05-27 16:24           ` H.J. Lu
@ 2020-05-27 20:24             ` H.J. Lu
  2020-05-28 12:44               ` V6 " H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2020-05-27 20:24 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils

[-- Attachment #1: Type: text/plain, Size: 21266 bytes --]

On Wed, May 27, 2020 at 9:24 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Wed, May 27, 2020 at 9:19 AM Fangrui Song <maskray@google.com> wrote:
> >
> > On 2020-05-27, H.J. Lu wrote:
> > >On Sat, May 23, 2020 at 2:56 PM Fangrui Song <maskray@google.com> wrote:
> > >>
> > >> On 2020-05-23, H.J. Lu wrote:
> > >> >On Sat, May 23, 2020 at 11:29 AM Fangrui Song <maskray@google.com> wrote:
> > >> >>
> > >> >> On 2020-05-23, H.J. Lu wrote:
> > >> >> >From: Fangrui Song <maskray@google.com>
> > >> >> >
> > >> >> >--export-dynamic-symbol-list is like a dynamic list, but without
> > >> >> >the symbolic property for unspecified symbols.
> > >> >> >
> > >> >> >When creating an executable, --export-dynamic-symbol-list is treated
> > >> >> >like --dynamic-list.
> > >> >> >
> > >> >> >When creating a shared library, it is treated like --dynamic-list if
> > >> >> >-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
> > >> >> >that references to matched symbols will not be bound to the definitions
> > >> >> >within the shared library.
> > >> >> >
> > >> >> >2020-05-XX  Fangrui Song  <maskray@google.com>
> > >> >> >           H.J. Lu  <hongjiu.lu@intel.com>
> > >> >> >
> > >> >> >       PR ld/25910
> > >> >> >       * NEWS: Mention --export-dynamic-symbol[-list].
> > >> >> >       * ld.texi: Document --export-dynamic-symbol[-list].
> > >> >> >       * ldgram.y: Pass current_dynamic_list_p to
> > >> >> >       lang_append_dynamic_list.
> > >> >> >       * ldlang.c (current_dynamic_list_p): New.
> > >> >> >       (ang_append_dynamic_list): Updated to take a pointer to
> > >> >> >       struct bfd_elf_dynamic_list * argument instead of using
> > >> >> >       link_info.dynamic_list.
> > >> >> >       (lang_append_dynamic_list_cpp_typeinfo): Pass
> > >> >> >       &link_info.dynamic_list to ang_append_dynamic_list.
> > >> >> >       (lang_append_dynamic_list_cpp_new): Likewise.
> > >> >> >       * ldlang.h (current_dynamic_list_p): New.
> > >> >> >       (lang_append_dynamic_list): Add a pointer to
> > >> >> >       struct bfd_elf_dynamic_list * argument.
> > >> >> >       * ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
> > >> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
> > >> >> >       * lexsup.c (ld_options): Add entries for
> > >> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL and
> > >> >> >       OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
> > >> >> >       (parse_args): Handle --export-dynamic-symbol and
> > >> >> >       --export-dynamic-symbol-list.
> > >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
> > >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
> > >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
> > >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
> > >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
> > >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
> > >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
> > >> >> >       * testsuite/ld-dynamic/export-dynamic-symbol.s: New.
> > >> >> >       * testsuite/ld-dynamic/foo-bar.list: New.
> > >> >> >       * testsuite/ld-dynamic/foo.list: New.
> > >> >> >       * testsuite/ld-dynamic/foo.s: New.
> > >> >> >       * testsuite/ld-dynamic/fstar.list: New.
> > >> >> >       * testsuite/ld-elf/dlempty.list: New.
> > >> >> >       * testsuite/ld-elf/shared.exp: Add tests for
> > >> >> >       --export-dynamic-symbol and --export-dynamic-symbol-list.
> > >> >> >---
> > >> >> > ld/NEWS                                       |  3 +
> > >> >> > ld/ld.texi                                    | 18 +++++
> > >> >> > ld/ldgram.y                                   |  2 +-
> > >> >> > ld/ldlang.c                                   | 16 ++--
> > >> >> > ld/ldlang.h                                   |  5 +-
> > >> >> > ld/ldlex.h                                    |  2 +
> > >> >> > ld/lexsup.c                                   | 75 +++++++++++++++++++
> > >> >> > .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
> > >> >> > .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
> > >> >> > .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 ++
> > >> >> > .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
> > >> >> > .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
> > >> >> > .../export-dynamic-symbol-list-glob.d         |  8 ++
> > >> >> > .../ld-dynamic/export-dynamic-symbol.exp      | 39 ++++++++++
> > >> >> > .../ld-dynamic/export-dynamic-symbol.s        |  9 +++
> > >> >> > ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
> > >> >> > ld/testsuite/ld-dynamic/foo.list              |  1 +
> > >> >> > ld/testsuite/ld-dynamic/foo.s                 |  4 +
> > >> >> > ld/testsuite/ld-dynamic/fstar.list            |  1 +
> > >> >> > ld/testsuite/ld-elf/dlempty.list              |  3 +
> > >> >> > ld/testsuite/ld-elf/shared.exp                | 36 +++++++++
> > >> >> > 21 files changed, 258 insertions(+), 9 deletions(-)
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/foo.list
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/foo.s
> > >> >> > create mode 100644 ld/testsuite/ld-dynamic/fstar.list
> > >> >> > create mode 100644 ld/testsuite/ld-elf/dlempty.list
> > >> >> >
> > >> >> >diff --git a/ld/NEWS b/ld/NEWS
> > >> >> >index 9f5bbe51cf..870c480bde 100644
> > >> >> >--- a/ld/NEWS
> > >> >> >+++ b/ld/NEWS
> > >> >> >@@ -1,5 +1,8 @@
> > >> >> > -*- text -*-
> > >> >> >
> > >> >> >+* Add ELF linker command-line options, --export-dynamic-symbol and
> > >> >> >+  --export-dynamic-symbol-list, to make symbols dynamic.
> > >> >> >+
> > >> >> > * Add command-line options --enable-non-contiguous-regions and
> > >> >> >   --enable-non-contiguous-regions-warnings.
> > >> >> >
> > >> >> >diff --git a/ld/ld.texi b/ld/ld.texi
> > >> >> >index 4dc78e65fa..92e47c6324 100644
> > >> >> >--- a/ld/ld.texi
> > >> >> >+++ b/ld/ld.texi
> > >> >> >@@ -569,6 +569,24 @@ 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{glob}
> > >> >> >+@cindex export dynamic symbol
> > >> >> >+@item --export-dynamic-symbol=@var{glob}
> > >> >> >+When creating a dynamically linked executable, symbols matching
> > >> >> >+@var{glob} will be added to the dynamic symbol table. When creating a
> > >> >> >+shared library, references to symbols matching @var{glob} will not be
> > >> >> >+bound to the definitions within the shared library. This option is a
> > >> >> >+no-op when creating a shared library and @samp{-Bsymbolic} or
> > >> >> >+@samp{--dynamic-list} are not specified. This option is only meaningful
> > >> >> >+on ELF platforms which support shared libraries.
> > >> >>
> > >> >> Is --export-dynamic-symbol still effective for -shared?
> > >> >> I think either way is ok.
> > >> >
> > >> >Yes.
> > >> >
> > >> >> >+@kindex --export-dynamic-symbol-list=@var{file}
> > >> >> >+@cindex export dynamic symbol list
> > >> >> >+@item --export-dynamic-symbol-list=@var{file}
> > >> >> >+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
> > >> >> >+The format of the file is the same as the version node without
> > >> >> >+scope and node name.  See @ref{VERSION} for more information.
> > >> >> >+
> > >> >> > @ifclear SingleFormat
> > >> >> > @cindex big-endian objects
> > >> >> > @cindex endianness
> > >> >> >diff --git a/ld/ldgram.y b/ld/ldgram.y
> > >> >> >index df5c035c03..36845c4c30 100644
> > >> >> >--- a/ld/ldgram.y
> > >> >> >+++ b/ld/ldgram.y
> > >> >> >@@ -1313,7 +1313,7 @@ dynamic_list_node:
> > >> >> > dynamic_list_tag:
> > >> >> >               vers_defns ';'
> > >> >> >               {
> > >> >> >-                lang_append_dynamic_list ($1);
> > >> >> >+                lang_append_dynamic_list (current_dynamic_list_p, $1);
> > >> >> >               }
> > >> >> >       ;
> > >> >> >
> > >> >> >diff --git a/ld/ldlang.c b/ld/ldlang.c
> > >> >> >index 3d653d460d..14a6a577d2 100644
> > >> >> >--- a/ld/ldlang.c
> > >> >> >+++ b/ld/ldlang.c
> > >> >> >@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
> > >> >> >    lang_statement_union).  */
> > >> >> > lang_statement_list_type input_file_chain;
> > >> >> > static const char *current_input_file;
> > >> >> >+struct bfd_elf_dynamic_list **current_dynamic_list_p;
> > >> >> > struct bfd_sym_chain entry_symbol = { NULL, NULL };
> > >> >> > const char *entry_section = ".text";
> > >> >> > struct lang_input_statement_flags input_flags;
> > >> >> >@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
> > >> >> > /* Append the list of dynamic symbols to the existing one.  */
> > >> >> >
> > >> >> > void
> > >> >> >-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
> > >> >> >+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
> > >> >> >+                        struct bfd_elf_version_expr *dynamic)
> > >> >> > {
> > >> >> >-  if (link_info.dynamic_list)
> > >> >> >+  if (*list_p)
> > >> >> >     {
> > >> >> >       struct bfd_elf_version_expr *tail;
> > >> >> >       for (tail = dynamic; tail->next != NULL; tail = tail->next)
> > >> >> >       ;
> > >> >> >-      tail->next = link_info.dynamic_list->head.list;
> > >> >> >-      link_info.dynamic_list->head.list = dynamic;
> > >> >> >+      tail->next = (*list_p)->head.list;
> > >> >> >+      (*list_p)->head.list = dynamic;
> > >> >> >     }
> > >> >> >   else
> > >> >> >     {
> > >> >> >@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
> > >> >> >       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
> > >> >> >       d->head.list = dynamic;
> > >> >> >       d->match = lang_vers_match;
> > >> >> >-      link_info.dynamic_list = d;
> > >> >> >+      *list_p = d;
> > >> >> >     }
> > >> >> > }
> > >> >> >
> > >> >> >@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
> > >> >> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
> > >> >> >                                    FALSE);
> > >> >> >
> > >> >> >-  lang_append_dynamic_list (dynamic);
> > >> >> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
> > >> >> > }
> > >> >> >
> > >> >> > /* Append the list of C++ operator new and delete dynamic symbols to the
> > >> >> >@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
> > >> >> >     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
> > >> >> >                                    FALSE);
> > >> >> >
> > >> >> >-  lang_append_dynamic_list (dynamic);
> > >> >> >+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
> > >> >> > }
> > >> >> >
> > >> >> > /* Scan a space and/or comma separated string of features.  */
> > >> >> >diff --git a/ld/ldlang.h b/ld/ldlang.h
> > >> >> >index 3018c3e2ba..529ccd1585 100644
> > >> >> >--- a/ld/ldlang.h
> > >> >> >+++ b/ld/ldlang.h
> > >> >> >@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
> > >> >> > extern lang_statement_list_type file_chain;
> > >> >> > extern lang_statement_list_type input_file_chain;
> > >> >> >
> > >> >> >+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
> > >> >> >+
> > >> >> > extern int lang_statement_iteration;
> > >> >> > extern struct asneeded_minfo **asneeded_list_tail;
> > >> >> >
> > >> >> >@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
> > >> >> >   (struct bfd_elf_version_deps *, const char *);
> > >> >> > extern void lang_register_vers_node
> > >> >> >   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
> > >> >> >-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
> > >> >> >+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
> > >> >> >+                                    struct bfd_elf_version_expr *);
> > >> >> > extern void lang_append_dynamic_list_cpp_typeinfo (void);
> > >> >> > extern void lang_append_dynamic_list_cpp_new (void);
> > >> >> > extern void lang_add_unique
> > >> >> >diff --git a/ld/ldlex.h b/ld/ldlex.h
> > >> >> >index 22b928d2d9..2c8d043a09 100644
> > >> >> >--- a/ld/ldlex.h
> > >> >> >+++ b/ld/ldlex.h
> > >> >> >@@ -81,6 +81,8 @@ enum option_values
> > >> >> >   OPTION_DYNAMIC_LIST_CPP_NEW,
> > >> >> >   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
> > >> >> >   OPTION_DYNAMIC_LIST_DATA,
> > >> >> >+  OPTION_EXPORT_DYNAMIC_SYMBOL,
> > >> >> >+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
> > >> >> >   OPTION_WARN_COMMON,
> > >> >> >   OPTION_WARN_CONSTRUCTORS,
> > >> >> >   OPTION_WARN_FATAL,
> > >> >> >diff --git a/ld/lexsup.c b/ld/lexsup.c
> > >> >> >index fe9526b527..2bac1631d6 100644
> > >> >> >--- a/ld/lexsup.c
> > >> >> >+++ b/ld/lexsup.c
> > >> >> >@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
> > >> >> >+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
> > >> >> >+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
> > >> >> >@@ -581,6 +585,7 @@ parse_args (unsigned argc, char **argv)
> > >> >> >     dynamic_list_data,
> > >> >> >     dynamic_list
> > >> >> >   } opt_dynamic_list = dynamic_list_unset;
> > >> >> >+  struct bfd_elf_dynamic_list *export_list = NULL;
> > >> >> >
> > >> >> >   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
> > >> >> >   longopts = (struct option *)
> > >> >> >@@ -1418,6 +1423,7 @@ parse_args (unsigned argc, char **argv)
> > >> >> >           ldfile_open_command_file (optarg);
> > >> >> >           saved_script_handle = hold_script_handle;
> > >> >> >           parser_input = input_dynamic_list;
> > >> >> >+          current_dynamic_list_p = &link_info.dynamic_list;
> > >> >> >           yyparse ();
> > >> >> >         }
> > >> >> >         if (opt_dynamic_list != dynamic_list_data)
> > >> >> >@@ -1425,6 +1431,29 @@ parse_args (unsigned argc, char **argv)
> > >> >> >         if (opt_symbolic == symbolic)
> > >> >> >           opt_symbolic = symbolic_unset;
> > >> >> >         break;
> > >> >> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL:
> > >> >> >+        {
> > >> >> >+          struct bfd_elf_version_expr *expr
> > >> >> >+            = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
> > >> >> >+                                     FALSE);
> > >> >> >+          lang_append_dynamic_list (&export_list, expr);
> > >> >> >+          }
> > >> >> >+        break;
> > >> >> >+      case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
> > >> >> >+        /* This option indicates a small script that only specifies
> > >> >> >+           an export list.  Read it, but don't assume that we've
> > >> >> >+           seen a linker script.  */
> > >> >> >+        {
> > >> >> >+          FILE *hold_script_handle;
> > >> >> >+
> > >> >> >+          hold_script_handle = saved_script_handle;
> > >> >> >+          ldfile_open_command_file (optarg);
> > >> >> >+          saved_script_handle = hold_script_handle;
> > >> >> >+          parser_input = input_dynamic_list;
> > >> >> >+          current_dynamic_list_p = &export_list;
> > >> >> >+          yyparse ();
> > >> >> >+        }
> > >> >> >+        break;
> > >> >> >       case OPTION_WARN_COMMON:
> > >> >> >         config.warn_common = TRUE;
> > >> >> >         break;
> > >> >> >@@ -1632,6 +1661,52 @@ parse_args (unsigned argc, char **argv)
> > >> >> >       && command_line.check_section_addresses < 0)
> > >> >> >     command_line.check_section_addresses = 0;
> > >> >> >
> > >> >> >+  if (export_list && !bfd_link_relocatable (&link_info))
> > >> >> >+    {
> > >> >> >+      struct bfd_elf_version_expr *head = export_list->head.list;
> > >> >> >+      struct bfd_elf_version_expr *next;
> > >> >> >+
> > >> >> >+      /* For --export-dynamic-symbol[-list]:
> > >> >> >+       1. When building executable, treat like --dynamic-list.
> > >> >> >+       2. When building shared object:
> > >> >> >+          a. If -Bsymbolic or --dynamic-list are used, treat like
> > >> >> >+             --dynamic-list.
> > >> >> >+          b. Otherwise, ignored.
> > >> >> >+       */
> > >> >> >+      bfd_boolean kept = (bfd_link_executable (&link_info)
> > >> >> >+                        || opt_symbolic != symbolic_unset
> > >> >> >+                        || opt_dynamic_list != dynamic_list_unset);
> > >> >> >+
> > >> >> >+      if (kept)
> > >> >> >+      {
> > >> >> >+        /* Append the export list to link_info.dynamic_list.  */
> > >> >> >+        if (link_info.dynamic_list)
> > >> >> >+          {
> > >> >> >+            for (next = head; next->next != NULL; next = next->next)
> > >> >> >+              ;
> > >> >> >+            next->next = link_info.dynamic_list->head.list;
> > >> >> >+            link_info.dynamic_list->head.list = head;
> > >> >> >+          }
> > >> >> >+        else
> > >> >> >+          link_info.dynamic_list = export_list;
> > >> >> >+
> > >> >> >+        if (opt_dynamic_list != dynamic_list_data)
> > >> >> >+          opt_dynamic_list = dynamic_list;
> > >> >> >+        if (opt_symbolic == symbolic)
> > >> >> >+          opt_symbolic = symbolic_unset;
> > >> >>
> > >> >> The interaction with -Bsymbolic appears to be more complex now.
> > >> >> I think users will pretty much avoid the combination of -Bsymbolic and
> > >> >> (--dynamic-list or --export-dynamic-symbol or --export-dynamic-symbol-list).
> > >> >>
> > >> >> So I beg for a re-consideration of
> > >> >> https://sourceware.org/bugzilla/show_bug.cgi?id=26018
> > >> >> https://sourceware.org/pipermail/binutils/2020-May/111223.html
> > >> >>
> > >> >
> > >> >Here is the updated patch on top of
> > >> >
> > >> >https://sourceware.org/pipermail/binutils/2020-May/111228.html
> > >>
> > >> Thanks for PATCH v3. LGTM.
> > >>
> > >> I have verified the semantics of new tests dl2d ~ dl2k.
> > >
> > >The updated patch to adjust ld-dynamic/export-dynamic-symbol.s
> > >for all ELF targets:
> > >
> > >diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> > >b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> > >index 4b1b8ebd5c..c55da536c5 100644
> > >--- a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> > >+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
> > >@@ -1,6 +1,14 @@
> > >   .text
> > >+  .global start  /* Used by SH targets.  */
> > >+start:
> > >   .global _start
> > > _start:
> > >+  .global __start
> > >+__start:
> > >+  .global main   /* Used by HPPA targets.  */
> > >+main:
> > >+  .globl   _main /* Used by LynxOS targets.  */
> > >+_main:
> > >   .word 0
> > >
> > >   .section .text.1, "ax"
> > >
> > >--
> > >H.J.
> >
> > Still looks good.
>
> More changes are needed:
> diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
> b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
> index d0b4bc4eb0..c879a5f65f 100644
> --- a/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
> +++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
> @@ -23,6 +23,26 @@ if ![is_elf_format] {
>      return
>  }
>
> +# Skip targets where -shared is not supported
> +
> +if ![check_shared_lib_support] {
> +    return
> +}
> +
> +set old_ASFLAGS $ASFLAGS
> +
> +# These targets require extra GAS options when building code for shared
> +# libraries.
> +if [istarget "nds32*-*"] {
> +    append ASFLAGS " -mpic"
> +}
> +if [istarget "tic6x-*-*"] {
> +    append ASFLAGS " -mpic -mpid=near"
> +}
> +if [istarget "sparc*-*-*"] {
> +    append ASFLAGS " -K PIC -Av9"
> +}
> +
>  set build_tests {
>    {"Build libfoo.a"
>     "" "" ""
> @@ -37,3 +57,5 @@ foreach test_file $test_list {
>      verbose $test_name
>      run_dump_test $test_name
>  }
> +
> +set ASFLAGS $old_ASFLAGS
>

More test fixes.  libfoo.a is a bad name since it may have a conflict
with other tests.

-- 
H.J.

[-- Attachment #2: 0001-ld-Add-export-dynamic-symbol-and-export-dynamic-symb.patch --]
[-- Type: text/x-patch, Size: 23650 bytes --]

From 4f646eda64511e01a7c28cd957c84c2b30e3c903 Mon Sep 17 00:00:00 2001
From: Fangrui Song <maskray@google.com>
Date: Wed, 22 Apr 2020 22:12:42 -0700
Subject: [PATCH] ld: Add --export-dynamic-symbol and
 --export-dynamic-symbol-list

--export-dynamic-symbol-list is like a dynamic list, but without
the symbolic property for unspecified symbols.

When creating an executable, --export-dynamic-symbol-list is treated
like --dynamic-list.

When creating a shared library, it is treated like --dynamic-list if
-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
that references to matched symbols will not be bound to the definitions
within the shared library.

2020-05-XX  Fangrui Song  <maskray@google.com>
	    H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/25910
	* NEWS: Mention --export-dynamic-symbol[-list].
	* ld.texi: Document --export-dynamic-symbol[-list].
	* ldgram.y: Pass current_dynamic_list_p to
	lang_append_dynamic_list.
	* ldlang.c (current_dynamic_list_p): New.
	(ang_append_dynamic_list): Updated to take a pointer to
	struct bfd_elf_dynamic_list * argument instead of using
	link_info.dynamic_list.
	(lang_append_dynamic_list_cpp_typeinfo): Pass
	&link_info.dynamic_list to ang_append_dynamic_list.
	(lang_append_dynamic_list_cpp_new): Likewise.
	* ldlang.h (current_dynamic_list_p): New.
	(lang_append_dynamic_list): Add a pointer to
	struct bfd_elf_dynamic_list * argument.
	* ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
	* lexsup.c (ld_options): Add entries for
	OPTION_EXPORT_DYNAMIC_SYMBOL and
	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
	(parse_args): Handle --export-dynamic-symbol and
	--export-dynamic-symbol-list.
	* testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
	* testsuite/ld-dynamic/export-dynamic-symbol.s: New.
	* testsuite/ld-dynamic/foo-bar.list: New.
	* testsuite/ld-dynamic/foo.list: New.
	* testsuite/ld-dynamic/foo.s: New.
	* testsuite/ld-dynamic/fstar.list: New.
	* testsuite/ld-elf/dlempty.list: New.
	* testsuite/ld-elf/shared.exp: Add tests for
	--export-dynamic-symbol and --export-dynamic-symbol-list.
---
 ld/NEWS                                       |  3 +
 ld/ld.texi                                    | 18 +++++
 ld/ldgram.y                                   |  2 +-
 ld/ldlang.c                                   | 16 +++--
 ld/ldlang.h                                   |  5 +-
 ld/ldlex.h                                    |  2 +
 ld/lexsup.c                                   | 72 +++++++++++++++++++
 .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
 .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
 .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 +++
 .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
 .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
 .../export-dynamic-symbol-list-glob.d         |  8 +++
 .../ld-dynamic/export-dynamic-symbol.exp      | 70 ++++++++++++++++++
 .../ld-dynamic/export-dynamic-symbol.s        | 17 +++++
 ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
 ld/testsuite/ld-dynamic/foo.list              |  1 +
 ld/testsuite/ld-dynamic/foo.s                 |  4 ++
 ld/testsuite/ld-dynamic/fstar.list            |  1 +
 ld/testsuite/ld-elf/dlempty.list              |  3 +
 ld/testsuite/ld-elf/shared.exp                | 42 +++++++++++
 21 files changed, 300 insertions(+), 9 deletions(-)
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
 create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
 create mode 100644 ld/testsuite/ld-dynamic/foo.list
 create mode 100644 ld/testsuite/ld-dynamic/foo.s
 create mode 100644 ld/testsuite/ld-dynamic/fstar.list
 create mode 100644 ld/testsuite/ld-elf/dlempty.list

diff --git a/ld/NEWS b/ld/NEWS
index 98f07a73e1..b619837b34 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add ELF linker command-line options, --export-dynamic-symbol and
+  --export-dynamic-symbol-list, to make symbols dynamic.
+
 * The -Map=<filename> command line option has been extended so that if
   <filename> is omitted then a file called <output-filename>.map will be
   created.  Plus if <filename> is a directory then
diff --git a/ld/ld.texi b/ld/ld.texi
index 52342523ed..2b7fb50e2d 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -569,6 +569,24 @@ 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{glob}
+@cindex export dynamic symbol
+@item --export-dynamic-symbol=@var{glob}
+When creating a dynamically linked executable, symbols matching
+@var{glob} will be added to the dynamic symbol table. When creating a
+shared library, references to symbols matching @var{glob} will not be
+bound to the definitions within the shared library. This option is a
+no-op when creating a shared library and @samp{-Bsymbolic} or
+@samp{--dynamic-list} are not specified. This option is only meaningful
+on ELF platforms which support shared libraries.
+
+@kindex --export-dynamic-symbol-list=@var{file}
+@cindex export dynamic symbol list
+@item --export-dynamic-symbol-list=@var{file}
+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
+The format of the file is the same as the version node without
+scope and node name.  See @ref{VERSION} for more information.
+
 @ifclear SingleFormat
 @cindex big-endian objects
 @cindex endianness
diff --git a/ld/ldgram.y b/ld/ldgram.y
index df5c035c03..36845c4c30 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -1313,7 +1313,7 @@ dynamic_list_node:
 dynamic_list_tag:
 		vers_defns ';'
 		{
-		  lang_append_dynamic_list ($1);
+		  lang_append_dynamic_list (current_dynamic_list_p, $1);
 		}
 	;
 
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 3d653d460d..14a6a577d2 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
    lang_statement_union).  */
 lang_statement_list_type input_file_chain;
 static const char *current_input_file;
+struct bfd_elf_dynamic_list **current_dynamic_list_p;
 struct bfd_sym_chain entry_symbol = { NULL, NULL };
 const char *entry_section = ".text";
 struct lang_input_statement_flags input_flags;
@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
 /* Append the list of dynamic symbols to the existing one.  */
 
 void
-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
+			  struct bfd_elf_version_expr *dynamic)
 {
-  if (link_info.dynamic_list)
+  if (*list_p)
     {
       struct bfd_elf_version_expr *tail;
       for (tail = dynamic; tail->next != NULL; tail = tail->next)
 	;
-      tail->next = link_info.dynamic_list->head.list;
-      link_info.dynamic_list->head.list = dynamic;
+      tail->next = (*list_p)->head.list;
+      (*list_p)->head.list = dynamic;
     }
   else
     {
@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
       d->head.list = dynamic;
       d->match = lang_vers_match;
-      link_info.dynamic_list = d;
+      *list_p = d;
     }
 }
 
@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
 				     FALSE);
 
-  lang_append_dynamic_list (dynamic);
+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
 }
 
 /* Append the list of C++ operator new and delete dynamic symbols to the
@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
 				     FALSE);
 
-  lang_append_dynamic_list (dynamic);
+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
 }
 
 /* Scan a space and/or comma separated string of features.  */
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 3018c3e2ba..529ccd1585 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
 extern lang_statement_list_type file_chain;
 extern lang_statement_list_type input_file_chain;
 
+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
+
 extern int lang_statement_iteration;
 extern struct asneeded_minfo **asneeded_list_tail;
 
@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
   (struct bfd_elf_version_deps *, const char *);
 extern void lang_register_vers_node
   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
+				      struct bfd_elf_version_expr *);
 extern void lang_append_dynamic_list_cpp_typeinfo (void);
 extern void lang_append_dynamic_list_cpp_new (void);
 extern void lang_add_unique
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 318ac7a789..6388247b45 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -81,6 +81,8 @@ enum option_values
   OPTION_DYNAMIC_LIST_CPP_NEW,
   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
   OPTION_DYNAMIC_LIST_DATA,
+  OPTION_EXPORT_DYNAMIC_SYMBOL,
+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
   OPTION_WARN_COMMON,
   OPTION_WARN_CONSTRUCTORS,
   OPTION_WARN_FATAL,
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 49c4f23950..7d73ae86cd 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
@@ -583,6 +587,7 @@ parse_args (unsigned argc, char **argv)
     dynamic_list_data,
     dynamic_list
   } opt_dynamic_list = dynamic_list_unset;
+  struct bfd_elf_dynamic_list *export_list = NULL;
 
   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
   longopts = (struct option *)
@@ -1414,11 +1419,35 @@ parse_args (unsigned argc, char **argv)
 	    ldfile_open_command_file (optarg);
 	    saved_script_handle = hold_script_handle;
 	    parser_input = input_dynamic_list;
+	    current_dynamic_list_p = &link_info.dynamic_list;
 	    yyparse ();
 	  }
 	  if (opt_dynamic_list != dynamic_list_data)
 	    opt_dynamic_list = dynamic_list;
 	  break;
+	case OPTION_EXPORT_DYNAMIC_SYMBOL:
+	  {
+	    struct bfd_elf_version_expr *expr
+	      = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
+				       FALSE);
+	    lang_append_dynamic_list (&export_list, expr);
+          }
+	  break;
+	case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
+	  /* This option indicates a small script that only specifies
+	     an export list.  Read it, but don't assume that we've
+	     seen a linker script.  */
+	  {
+	    FILE *hold_script_handle;
+
+	    hold_script_handle = saved_script_handle;
+	    ldfile_open_command_file (optarg);
+	    saved_script_handle = hold_script_handle;
+	    parser_input = input_dynamic_list;
+	    current_dynamic_list_p = &export_list;
+	    yyparse ();
+	  }
+	  break;
 	case OPTION_WARN_COMMON:
 	  config.warn_common = TRUE;
 	  break;
@@ -1657,6 +1686,49 @@ parse_args (unsigned argc, char **argv)
       && command_line.check_section_addresses < 0)
     command_line.check_section_addresses = 0;
 
+  if (export_list)
+    {
+      struct bfd_elf_version_expr *head = export_list->head.list;
+      struct bfd_elf_version_expr *next;
+
+      /* For --export-dynamic-symbol[-list]:
+	 1. When building executable, treat like --dynamic-list.
+	 2. When building shared object:
+	    a. If -Bsymbolic or --dynamic-list are used, treat like
+	       --dynamic-list.
+	    b. Otherwise, ignored.
+       */
+      if (!bfd_link_relocatable (&link_info)
+	  && (bfd_link_executable (&link_info)
+	      || opt_symbolic != symbolic_unset
+	      || opt_dynamic_list != dynamic_list_unset))
+	{
+	  /* Append the export list to link_info.dynamic_list.  */
+	  if (link_info.dynamic_list)
+	    {
+	      for (next = head; next->next != NULL; next = next->next)
+		;
+	      next->next = link_info.dynamic_list->head.list;
+	      link_info.dynamic_list->head.list = head;
+	    }
+	  else
+	    link_info.dynamic_list = export_list;
+
+	  if (opt_dynamic_list != dynamic_list_data)
+	    opt_dynamic_list = dynamic_list;
+	}
+      else
+	{
+	  /* Free the export list.  */
+	  for (; head->next != NULL; head = next)
+	    {
+	      next = head->next;
+	      free (head);
+	    }
+	  free (export_list);
+	}
+    }
+
   switch (opt_dynamic_list)
     {
     case dynamic_list_unset:
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
new file mode 100644
index 0000000000..25ae13023e
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
@@ -0,0 +1,9 @@
+#name: --export-dynamic-symbol foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie --export-dynamic-symbol foo tmpdir/libpr25910.a
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
new file mode 100644
index 0000000000..d38508a5b5
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
@@ -0,0 +1,9 @@
+#name: -u --export-dynamic-symbol foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol foo --export-dynamic-symbol=bar tmpdir/libpr25910.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +bar
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
new file mode 100644
index 0000000000..5f7fca68b2
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
@@ -0,0 +1,8 @@
+#name: -u --export-dynamic-symbol f* archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol "f*" tmpdir/libpr25910.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
new file mode 100644
index 0000000000..fc58af9357
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
@@ -0,0 +1,9 @@
+#name: --export-dynamic-symbol-list foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie --export-dynamic-symbol-list foo.list tmpdir/libpr25910.a
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
new file mode 100644
index 0000000000..337f642ee9
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
@@ -0,0 +1,9 @@
+#name: -u --export-dynamic-symbol-list foo bar archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol-list foo-bar.list tmpdir/libpr25910.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +bar
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
new file mode 100644
index 0000000000..916a22ca23
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
@@ -0,0 +1,8 @@
+#name: -u --export-dynamic-symbol-list fstar archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol-list fstar.list tmpdir/libpr25910.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
new file mode 100644
index 0000000000..ae530361fb
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
@@ -0,0 +1,70 @@
+# 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.
+#
+
+if ![is_elf_format] {
+    return
+}
+
+# Skip targets where -shared is not supported
+
+if ![check_shared_lib_support] {
+    return
+}
+
+set old_ASFLAGS $ASFLAGS
+
+# These targets require extra GAS options when building code for shared
+# libraries.
+if [istarget "nds32*-*"] {
+    append ASFLAGS " -mpic"
+}
+if [istarget "tic6x-*-*"] {
+    append ASFLAGS " -mpic -mpid=near"
+}
+if [istarget "sparc*-*-*"] {
+    append ASFLAGS " -K PIC -Av9"
+}
+
+set old_LDFLAGS $LDFLAGS
+
+# These targets require a non-default emulation for successful shared
+# library/executable builds.
+if [istarget "tic6x-*-*"] {
+    append LDFLAGS " -melf32_tic6x_le"
+}
+
+set build_tests {
+  {"Build libpr25910.a"
+   "" "" ""
+   {foo.s} {} "libpr25910.a"}
+}
+
+run_ld_link_tests $build_tests
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/export-dynamic-symbol-*.d]]
+foreach test_file $test_list {
+    set test_name [file rootname $test_file]
+    verbose $test_name
+    run_dump_test $test_name
+}
+
+set ASFLAGS $old_ASFLAGS
+set LDFLAGS $old_LDFLAGS
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
new file mode 100644
index 0000000000..c55da536c5
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
@@ -0,0 +1,17 @@
+	.text
+	.global start	/* Used by SH targets.  */
+start:
+	.global _start
+_start:
+	.global __start
+__start:
+	.global main	/* Used by HPPA targets.  */
+main:
+	.globl	_main	/* Used by LynxOS targets.  */
+_main:
+	.word 0
+
+	.section .text.1, "ax"
+	.global bar
+bar:
+	.word 0
diff --git a/ld/testsuite/ld-dynamic/foo-bar.list b/ld/testsuite/ld-dynamic/foo-bar.list
new file mode 100644
index 0000000000..87732e1de4
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo-bar.list
@@ -0,0 +1 @@
+{ foo; bar; };
diff --git a/ld/testsuite/ld-dynamic/foo.list b/ld/testsuite/ld-dynamic/foo.list
new file mode 100644
index 0000000000..f89f569438
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo.list
@@ -0,0 +1 @@
+{ foo; };
diff --git a/ld/testsuite/ld-dynamic/foo.s b/ld/testsuite/ld-dynamic/foo.s
new file mode 100644
index 0000000000..4a70181776
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo.s
@@ -0,0 +1,4 @@
+	.text
+	.globl foo
+foo:
+	.byte 0
diff --git a/ld/testsuite/ld-dynamic/fstar.list b/ld/testsuite/ld-dynamic/fstar.list
new file mode 100644
index 0000000000..330d1dd2b8
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/fstar.list
@@ -0,0 +1 @@
+{ f*; };
diff --git a/ld/testsuite/ld-elf/dlempty.list b/ld/testsuite/ld-elf/dlempty.list
new file mode 100644
index 0000000000..9b3884b10e
--- /dev/null
+++ b/ld/testsuite/ld-elf/dlempty.list
@@ -0,0 +1,3 @@
+{
+  empty;
+};
diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
index 7d35f3f379..5606c9937f 100644
--- a/ld/testsuite/ld-elf/shared.exp
+++ b/ld/testsuite/ld-elf/shared.exp
@@ -601,6 +601,27 @@ set build_tests {
   {"Build libdl2d.so with --dynamic-list-data -Bsymbolic"
    "-shared -Wl,-Bsymbolic,--dynamic-list-data" "-fPIC"
    {dl2.c dl2xxx.c} {} "libdl2d.so"}
+  {"Build libdl2e.so with --export-dynamic-symbol=foo"
+   "-shared -Wl,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2e.so"}
+  {"Build libdl2f.so with --dynamic-list=dlempty.list and --export-dynamic-symbol=foo"
+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2f.so"}
+  {"Build libdl2g.so with --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2g.so"}
+  {"Build libdl2h.so with --dynamic-list=dlempty.list and --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2h.so"}
+  {"Build libdl2i.so with -Bsymbolic and --export-dynamic-symbol=foo"
+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2i.so"}
+  {"Build libdl2j.so with -Bsymbolic and --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2j.so"}
+  {"Build libdl2k.so with --export-dynamic-symbol-list=dl2.list and -Bsymbolic"
+   "-shared -Wl,--export-dynamic-symbol-list=dl2.list,-Bsymbolic" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2k.so"}
   {"Build libdl4a.so with --dynamic-list=dl4.list"
    "-shared -Wl,--dynamic-list=dl4.list" "-fPIC"
    {dl4.c dl4xxx.c} {} "libdl4a.so"}
@@ -880,6 +901,27 @@ set run_tests [list \
     [list "Run with libdl2d.so" \
      "-Wl,--no-as-needed tmpdir/libdl2d.so" "" \
      {dl2main.c} "dl2d" "dl2a.out" ] \
+    [list "Run with libdl2e.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2e.so" "" \
+     {dl2main.c} "dl2e" "dl2b.out" ] \
+    [list "Run with libdl2f.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2f.so" "" \
+     {dl2main.c} "dl2f" "dl2a.out" ] \
+    [list "Run with libdl2g.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2g.so" "" \
+     {dl2main.c} "dl2g" "dl2b.out" ] \
+    [list "Run with libdl2h.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2h.so" "" \
+     {dl2main.c} "dl2h" "dl2a.out" ] \
+    [list "Run with libdl2i.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2i.so" "" \
+     {dl2main.c} "dl2i" "dl2a.out" ] \
+    [list "Run with libdl2j.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2j.so" "" \
+     {dl2main.c} "dl2j" "dl2a.out" ] \
+    [list "Run with libdl2k.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2k.so" "" \
+     {dl2main.c} "dl2k" "dl2a.out" ] \
     [list "Run with libdl4a.so" \
      "-Wl,--no-as-needed tmpdir/libdl4a.so" "" \
      {dl4main.c} "dl4a" "dl4a.out" ] \
-- 
2.26.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* V6 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list
  2020-05-27 20:24             ` V5 " H.J. Lu
@ 2020-05-28 12:44               ` H.J. Lu
  2020-06-03 10:51                 ` Nick Clifton
  0 siblings, 1 reply; 12+ messages in thread
From: H.J. Lu @ 2020-05-28 12:44 UTC (permalink / raw)
  To: Fangrui Song, Nick Clifton, Alan Modra; +Cc: Binutils

[-- Attachment #1: Type: text/plain, Size: 522 bytes --]

Here is the rebased patch.  Nick, Alan, is it OK for master?  Thanks.

--export-dynamic-symbol-list is like a dynamic list, but without
the symbolic property for unspecified symbols.

When creating an executable, --export-dynamic-symbol-list is treated
like --dynamic-list.

When creating a shared library, it is treated like --dynamic-list if
-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
that references to matched symbols will not be bound to the definitions
within the shared library.

-- 
H.J.

[-- Attachment #2: 0001-ld-Add-export-dynamic-symbol-and-export-dynamic-symb.patch --]
[-- Type: text/x-patch, Size: 23672 bytes --]

From 9b7df61dcd8f2147d8966a6261e7ff4219443ad3 Mon Sep 17 00:00:00 2001
From: Fangrui Song <maskray@google.com>
Date: Wed, 22 Apr 2020 22:12:42 -0700
Subject: [PATCH] ld: Add --export-dynamic-symbol and
 --export-dynamic-symbol-list

--export-dynamic-symbol-list is like a dynamic list, but without
the symbolic property for unspecified symbols.

When creating an executable, --export-dynamic-symbol-list is treated
like --dynamic-list.

When creating a shared library, it is treated like --dynamic-list if
-Bsymbolic or --dynamic-list are used,  otherwise, it is ignored, so
that references to matched symbols will not be bound to the definitions
within the shared library.

2020-05-XX  Fangrui Song  <maskray@google.com>
	    H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/25910
	* NEWS: Mention --export-dynamic-symbol[-list].
	* ld.texi: Document --export-dynamic-symbol[-list].
	* ldgram.y: Pass current_dynamic_list_p to
	lang_append_dynamic_list.
	* ldlang.c (current_dynamic_list_p): New.
	(ang_append_dynamic_list): Updated to take a pointer to
	struct bfd_elf_dynamic_list * argument instead of using
	link_info.dynamic_list.
	(lang_append_dynamic_list_cpp_typeinfo): Pass
	&link_info.dynamic_list to ang_append_dynamic_list.
	(lang_append_dynamic_list_cpp_new): Likewise.
	* ldlang.h (current_dynamic_list_p): New.
	(lang_append_dynamic_list): Add a pointer to
	struct bfd_elf_dynamic_list * argument.
	* ldlex.h (option_values): Add OPTION_EXPORT_DYNAMIC_SYMBOL and
	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
	* lexsup.c (ld_options): Add entries for
	OPTION_EXPORT_DYNAMIC_SYMBOL and
	OPTION_EXPORT_DYNAMIC_SYMBOL_LIST.
	(parse_args): Handle --export-dynamic-symbol and
	--export-dynamic-symbol-list.
	* testsuite/ld-dynamic/export-dynamic-symbol-1.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-2.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-glob.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-1.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-2.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d: New.
	* testsuite/ld-dynamic/export-dynamic-symbol.exp: New.
	* testsuite/ld-dynamic/export-dynamic-symbol.s: New.
	* testsuite/ld-dynamic/foo-bar.list: New.
	* testsuite/ld-dynamic/foo.list: New.
	* testsuite/ld-dynamic/foo.s: New.
	* testsuite/ld-dynamic/fstar.list: New.
	* testsuite/ld-elf/dlempty.list: New.
	* testsuite/ld-elf/shared.exp: Add tests for
	--export-dynamic-symbol and --export-dynamic-symbol-list.
---
 ld/NEWS                                       |  3 +
 ld/ld.texi                                    | 18 +++++
 ld/ldgram.y                                   |  2 +-
 ld/ldlang.c                                   | 16 +++--
 ld/ldlang.h                                   |  5 +-
 ld/ldlex.h                                    |  2 +
 ld/lexsup.c                                   | 72 +++++++++++++++++++
 .../ld-dynamic/export-dynamic-symbol-1.d      |  9 +++
 .../ld-dynamic/export-dynamic-symbol-2.d      |  9 +++
 .../ld-dynamic/export-dynamic-symbol-glob.d   |  8 +++
 .../ld-dynamic/export-dynamic-symbol-list-1.d |  9 +++
 .../ld-dynamic/export-dynamic-symbol-list-2.d |  9 +++
 .../export-dynamic-symbol-list-glob.d         |  8 +++
 .../ld-dynamic/export-dynamic-symbol.exp      | 70 ++++++++++++++++++
 .../ld-dynamic/export-dynamic-symbol.s        | 17 +++++
 ld/testsuite/ld-dynamic/foo-bar.list          |  1 +
 ld/testsuite/ld-dynamic/foo.list              |  1 +
 ld/testsuite/ld-dynamic/foo.s                 |  4 ++
 ld/testsuite/ld-dynamic/fstar.list            |  1 +
 ld/testsuite/ld-elf/dlempty.list              |  3 +
 ld/testsuite/ld-elf/shared.exp                | 42 +++++++++++
 21 files changed, 300 insertions(+), 9 deletions(-)
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
 create mode 100644 ld/testsuite/ld-dynamic/export-dynamic-symbol.s
 create mode 100644 ld/testsuite/ld-dynamic/foo-bar.list
 create mode 100644 ld/testsuite/ld-dynamic/foo.list
 create mode 100644 ld/testsuite/ld-dynamic/foo.s
 create mode 100644 ld/testsuite/ld-dynamic/fstar.list
 create mode 100644 ld/testsuite/ld-elf/dlempty.list

diff --git a/ld/NEWS b/ld/NEWS
index 0dc5e9b368..485e1cf5b9 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add ELF linker command-line options, --export-dynamic-symbol and
+  --export-dynamic-symbol-list, to make symbols dynamic.
+
 * Add a configure option, --enable-textrel-check=[no|yes|warning|error],
   to decide what ELF linker should do by default with DT_TEXTREL in an
   executable or shared library.  Default to yes for Linux/x86 targets.
diff --git a/ld/ld.texi b/ld/ld.texi
index cb38f47cd3..bf474d4c62 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -569,6 +569,24 @@ 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{glob}
+@cindex export dynamic symbol
+@item --export-dynamic-symbol=@var{glob}
+When creating a dynamically linked executable, symbols matching
+@var{glob} will be added to the dynamic symbol table. When creating a
+shared library, references to symbols matching @var{glob} will not be
+bound to the definitions within the shared library. This option is a
+no-op when creating a shared library and @samp{-Bsymbolic} or
+@samp{--dynamic-list} are not specified. This option is only meaningful
+on ELF platforms which support shared libraries.
+
+@kindex --export-dynamic-symbol-list=@var{file}
+@cindex export dynamic symbol list
+@item --export-dynamic-symbol-list=@var{file}
+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
+The format of the file is the same as the version node without
+scope and node name.  See @ref{VERSION} for more information.
+
 @ifclear SingleFormat
 @cindex big-endian objects
 @cindex endianness
diff --git a/ld/ldgram.y b/ld/ldgram.y
index df5c035c03..36845c4c30 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -1313,7 +1313,7 @@ dynamic_list_node:
 dynamic_list_tag:
 		vers_defns ';'
 		{
-		  lang_append_dynamic_list ($1);
+		  lang_append_dynamic_list (current_dynamic_list_p, $1);
 		}
 	;
 
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 3d653d460d..14a6a577d2 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -118,6 +118,7 @@ lang_statement_list_type file_chain = { NULL, NULL };
    lang_statement_union).  */
 lang_statement_list_type input_file_chain;
 static const char *current_input_file;
+struct bfd_elf_dynamic_list **current_dynamic_list_p;
 struct bfd_sym_chain entry_symbol = { NULL, NULL };
 const char *entry_section = ".text";
 struct lang_input_statement_flags input_flags;
@@ -9324,15 +9325,16 @@ lang_add_unique (const char *name)
 /* Append the list of dynamic symbols to the existing one.  */
 
 void
-lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
+			  struct bfd_elf_version_expr *dynamic)
 {
-  if (link_info.dynamic_list)
+  if (*list_p)
     {
       struct bfd_elf_version_expr *tail;
       for (tail = dynamic; tail->next != NULL; tail = tail->next)
 	;
-      tail->next = link_info.dynamic_list->head.list;
-      link_info.dynamic_list->head.list = dynamic;
+      tail->next = (*list_p)->head.list;
+      (*list_p)->head.list = dynamic;
     }
   else
     {
@@ -9341,7 +9343,7 @@ lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
       d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
       d->head.list = dynamic;
       d->match = lang_vers_match;
-      link_info.dynamic_list = d;
+      *list_p = d;
     }
 }
 
@@ -9363,7 +9365,7 @@ lang_append_dynamic_list_cpp_typeinfo (void)
     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
 				     FALSE);
 
-  lang_append_dynamic_list (dynamic);
+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
 }
 
 /* Append the list of C++ operator new and delete dynamic symbols to the
@@ -9384,7 +9386,7 @@ lang_append_dynamic_list_cpp_new (void)
     dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
 				     FALSE);
 
-  lang_append_dynamic_list (dynamic);
+  lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
 }
 
 /* Scan a space and/or comma separated string of features.  */
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 3018c3e2ba..529ccd1585 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -513,6 +513,8 @@ extern bfd_boolean entry_from_cmdline;
 extern lang_statement_list_type file_chain;
 extern lang_statement_list_type input_file_chain;
 
+extern struct bfd_elf_dynamic_list **current_dynamic_list_p;
+
 extern int lang_statement_iteration;
 extern struct asneeded_minfo **asneeded_list_tail;
 
@@ -673,7 +675,8 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend
   (struct bfd_elf_version_deps *, const char *);
 extern void lang_register_vers_node
   (const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
-extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
+extern void lang_append_dynamic_list (struct bfd_elf_dynamic_list **,
+				      struct bfd_elf_version_expr *);
 extern void lang_append_dynamic_list_cpp_typeinfo (void);
 extern void lang_append_dynamic_list_cpp_new (void);
 extern void lang_add_unique
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 318ac7a789..6388247b45 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -81,6 +81,8 @@ enum option_values
   OPTION_DYNAMIC_LIST_CPP_NEW,
   OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
   OPTION_DYNAMIC_LIST_DATA,
+  OPTION_EXPORT_DYNAMIC_SYMBOL,
+  OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
   OPTION_WARN_COMMON,
   OPTION_WARN_CONSTRUCTORS,
   OPTION_WARN_FATAL,
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 412e2e6026..4808f7443d 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -504,6 +504,10 @@ 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_("Export the specified symbol"), EXACTLY_TWO_DASHES },
+  { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
+    '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_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},
@@ -588,6 +592,7 @@ parse_args (unsigned argc, char **argv)
     dynamic_list_data,
     dynamic_list
   } opt_dynamic_list = dynamic_list_unset;
+  struct bfd_elf_dynamic_list *export_list = NULL;
 
   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
   longopts = (struct option *)
@@ -1419,11 +1424,35 @@ parse_args (unsigned argc, char **argv)
 	    ldfile_open_command_file (optarg);
 	    saved_script_handle = hold_script_handle;
 	    parser_input = input_dynamic_list;
+	    current_dynamic_list_p = &link_info.dynamic_list;
 	    yyparse ();
 	  }
 	  if (opt_dynamic_list != dynamic_list_data)
 	    opt_dynamic_list = dynamic_list;
 	  break;
+	case OPTION_EXPORT_DYNAMIC_SYMBOL:
+	  {
+	    struct bfd_elf_version_expr *expr
+	      = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
+				       FALSE);
+	    lang_append_dynamic_list (&export_list, expr);
+          }
+	  break;
+	case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
+	  /* This option indicates a small script that only specifies
+	     an export list.  Read it, but don't assume that we've
+	     seen a linker script.  */
+	  {
+	    FILE *hold_script_handle;
+
+	    hold_script_handle = saved_script_handle;
+	    ldfile_open_command_file (optarg);
+	    saved_script_handle = hold_script_handle;
+	    parser_input = input_dynamic_list;
+	    current_dynamic_list_p = &export_list;
+	    yyparse ();
+	  }
+	  break;
 	case OPTION_WARN_COMMON:
 	  config.warn_common = TRUE;
 	  break;
@@ -1666,6 +1695,49 @@ parse_args (unsigned argc, char **argv)
       && command_line.check_section_addresses < 0)
     command_line.check_section_addresses = 0;
 
+  if (export_list)
+    {
+      struct bfd_elf_version_expr *head = export_list->head.list;
+      struct bfd_elf_version_expr *next;
+
+      /* For --export-dynamic-symbol[-list]:
+	 1. When building executable, treat like --dynamic-list.
+	 2. When building shared object:
+	    a. If -Bsymbolic or --dynamic-list are used, treat like
+	       --dynamic-list.
+	    b. Otherwise, ignored.
+       */
+      if (!bfd_link_relocatable (&link_info)
+	  && (bfd_link_executable (&link_info)
+	      || opt_symbolic != symbolic_unset
+	      || opt_dynamic_list != dynamic_list_unset))
+	{
+	  /* Append the export list to link_info.dynamic_list.  */
+	  if (link_info.dynamic_list)
+	    {
+	      for (next = head; next->next != NULL; next = next->next)
+		;
+	      next->next = link_info.dynamic_list->head.list;
+	      link_info.dynamic_list->head.list = head;
+	    }
+	  else
+	    link_info.dynamic_list = export_list;
+
+	  if (opt_dynamic_list != dynamic_list_data)
+	    opt_dynamic_list = dynamic_list;
+	}
+      else
+	{
+	  /* Free the export list.  */
+	  for (; head->next != NULL; head = next)
+	    {
+	      next = head->next;
+	      free (head);
+	    }
+	  free (export_list);
+	}
+    }
+
   switch (opt_dynamic_list)
     {
     case dynamic_list_unset:
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
new file mode 100644
index 0000000000..25ae13023e
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-1.d
@@ -0,0 +1,9 @@
+#name: --export-dynamic-symbol foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie --export-dynamic-symbol foo tmpdir/libpr25910.a
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
new file mode 100644
index 0000000000..d38508a5b5
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d
@@ -0,0 +1,9 @@
+#name: -u --export-dynamic-symbol foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol foo --export-dynamic-symbol=bar tmpdir/libpr25910.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +bar
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
new file mode 100644
index 0000000000..f8187be75c
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-glob.d
@@ -0,0 +1,8 @@
+#name: -u --export-dynamic-symbol "f*" archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol "f*" tmpdir/libpr25910.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
new file mode 100644
index 0000000000..fc58af9357
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-1.d
@@ -0,0 +1,9 @@
+#name: --export-dynamic-symbol-list foo archive
+#source: export-dynamic-symbol.s
+#ld: -pie --export-dynamic-symbol-list foo.list tmpdir/libpr25910.a
+#nm: -n
+
+#failif
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
new file mode 100644
index 0000000000..337f642ee9
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-2.d
@@ -0,0 +1,9 @@
+#name: -u --export-dynamic-symbol-list foo bar archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol-list foo-bar.list tmpdir/libpr25910.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +bar
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
new file mode 100644
index 0000000000..916a22ca23
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol-list-glob.d
@@ -0,0 +1,8 @@
+#name: -u --export-dynamic-symbol-list fstar archive
+#source: export-dynamic-symbol.s
+#ld: -pie -u foo --export-dynamic-symbol-list fstar.list tmpdir/libpr25910.a
+#nm: -D
+
+#...
+[0-9a-f]+ T +foo
+#...
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
new file mode 100644
index 0000000000..ae530361fb
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.exp
@@ -0,0 +1,70 @@
+# 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.
+#
+
+if ![is_elf_format] {
+    return
+}
+
+# Skip targets where -shared is not supported
+
+if ![check_shared_lib_support] {
+    return
+}
+
+set old_ASFLAGS $ASFLAGS
+
+# These targets require extra GAS options when building code for shared
+# libraries.
+if [istarget "nds32*-*"] {
+    append ASFLAGS " -mpic"
+}
+if [istarget "tic6x-*-*"] {
+    append ASFLAGS " -mpic -mpid=near"
+}
+if [istarget "sparc*-*-*"] {
+    append ASFLAGS " -K PIC -Av9"
+}
+
+set old_LDFLAGS $LDFLAGS
+
+# These targets require a non-default emulation for successful shared
+# library/executable builds.
+if [istarget "tic6x-*-*"] {
+    append LDFLAGS " -melf32_tic6x_le"
+}
+
+set build_tests {
+  {"Build libpr25910.a"
+   "" "" ""
+   {foo.s} {} "libpr25910.a"}
+}
+
+run_ld_link_tests $build_tests
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/export-dynamic-symbol-*.d]]
+foreach test_file $test_list {
+    set test_name [file rootname $test_file]
+    verbose $test_name
+    run_dump_test $test_name
+}
+
+set ASFLAGS $old_ASFLAGS
+set LDFLAGS $old_LDFLAGS
diff --git a/ld/testsuite/ld-dynamic/export-dynamic-symbol.s b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
new file mode 100644
index 0000000000..c55da536c5
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/export-dynamic-symbol.s
@@ -0,0 +1,17 @@
+	.text
+	.global start	/* Used by SH targets.  */
+start:
+	.global _start
+_start:
+	.global __start
+__start:
+	.global main	/* Used by HPPA targets.  */
+main:
+	.globl	_main	/* Used by LynxOS targets.  */
+_main:
+	.word 0
+
+	.section .text.1, "ax"
+	.global bar
+bar:
+	.word 0
diff --git a/ld/testsuite/ld-dynamic/foo-bar.list b/ld/testsuite/ld-dynamic/foo-bar.list
new file mode 100644
index 0000000000..87732e1de4
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo-bar.list
@@ -0,0 +1 @@
+{ foo; bar; };
diff --git a/ld/testsuite/ld-dynamic/foo.list b/ld/testsuite/ld-dynamic/foo.list
new file mode 100644
index 0000000000..f89f569438
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo.list
@@ -0,0 +1 @@
+{ foo; };
diff --git a/ld/testsuite/ld-dynamic/foo.s b/ld/testsuite/ld-dynamic/foo.s
new file mode 100644
index 0000000000..4a70181776
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/foo.s
@@ -0,0 +1,4 @@
+	.text
+	.globl foo
+foo:
+	.byte 0
diff --git a/ld/testsuite/ld-dynamic/fstar.list b/ld/testsuite/ld-dynamic/fstar.list
new file mode 100644
index 0000000000..330d1dd2b8
--- /dev/null
+++ b/ld/testsuite/ld-dynamic/fstar.list
@@ -0,0 +1 @@
+{ f*; };
diff --git a/ld/testsuite/ld-elf/dlempty.list b/ld/testsuite/ld-elf/dlempty.list
new file mode 100644
index 0000000000..9b3884b10e
--- /dev/null
+++ b/ld/testsuite/ld-elf/dlempty.list
@@ -0,0 +1,3 @@
+{
+  empty;
+};
diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
index 7d35f3f379..5606c9937f 100644
--- a/ld/testsuite/ld-elf/shared.exp
+++ b/ld/testsuite/ld-elf/shared.exp
@@ -601,6 +601,27 @@ set build_tests {
   {"Build libdl2d.so with --dynamic-list-data -Bsymbolic"
    "-shared -Wl,-Bsymbolic,--dynamic-list-data" "-fPIC"
    {dl2.c dl2xxx.c} {} "libdl2d.so"}
+  {"Build libdl2e.so with --export-dynamic-symbol=foo"
+   "-shared -Wl,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2e.so"}
+  {"Build libdl2f.so with --dynamic-list=dlempty.list and --export-dynamic-symbol=foo"
+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2f.so"}
+  {"Build libdl2g.so with --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2g.so"}
+  {"Build libdl2h.so with --dynamic-list=dlempty.list and --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,--dynamic-list=dlempty.list,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2h.so"}
+  {"Build libdl2i.so with -Bsymbolic and --export-dynamic-symbol=foo"
+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol=foo" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2i.so"}
+  {"Build libdl2j.so with -Bsymbolic and --export-dynamic-symbol-list=dl2.list"
+   "-shared -Wl,-Bsymbolic,--export-dynamic-symbol-list=dl2.list" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2j.so"}
+  {"Build libdl2k.so with --export-dynamic-symbol-list=dl2.list and -Bsymbolic"
+   "-shared -Wl,--export-dynamic-symbol-list=dl2.list,-Bsymbolic" "-fPIC"
+   {dl2.c dl2xxx.c} {} "libdl2k.so"}
   {"Build libdl4a.so with --dynamic-list=dl4.list"
    "-shared -Wl,--dynamic-list=dl4.list" "-fPIC"
    {dl4.c dl4xxx.c} {} "libdl4a.so"}
@@ -880,6 +901,27 @@ set run_tests [list \
     [list "Run with libdl2d.so" \
      "-Wl,--no-as-needed tmpdir/libdl2d.so" "" \
      {dl2main.c} "dl2d" "dl2a.out" ] \
+    [list "Run with libdl2e.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2e.so" "" \
+     {dl2main.c} "dl2e" "dl2b.out" ] \
+    [list "Run with libdl2f.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2f.so" "" \
+     {dl2main.c} "dl2f" "dl2a.out" ] \
+    [list "Run with libdl2g.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2g.so" "" \
+     {dl2main.c} "dl2g" "dl2b.out" ] \
+    [list "Run with libdl2h.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2h.so" "" \
+     {dl2main.c} "dl2h" "dl2a.out" ] \
+    [list "Run with libdl2i.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2i.so" "" \
+     {dl2main.c} "dl2i" "dl2a.out" ] \
+    [list "Run with libdl2j.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2j.so" "" \
+     {dl2main.c} "dl2j" "dl2a.out" ] \
+    [list "Run with libdl2k.so" \
+     "-Wl,--no-as-needed tmpdir/libdl2k.so" "" \
+     {dl2main.c} "dl2k" "dl2a.out" ] \
     [list "Run with libdl4a.so" \
      "-Wl,--no-as-needed tmpdir/libdl4a.so" "" \
      {dl4main.c} "dl4a" "dl4a.out" ] \
-- 
2.26.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: V6 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list
  2020-05-28 12:44               ` V6 " H.J. Lu
@ 2020-06-03 10:51                 ` Nick Clifton
  2020-06-03 12:12                   ` Alan Modra
  0 siblings, 1 reply; 12+ messages in thread
From: Nick Clifton @ 2020-06-03 10:51 UTC (permalink / raw)
  To: H.J. Lu, Fangrui Song, Alan Modra; +Cc: Binutils

Hi H.J. 

> Here is the rebased patch.  Nick, Alan, is it OK for master?  Thanks.

Short version: Approved - please apply.

Long version: The patch looks mostly fine to me.  But there is a problem: 
some regressions in the linker testsuite for various targets:

  Checking Binutils in: mips-sgi-irix6 ... 
    LD REGRESSION: -u --export-dynamic-symbol foo archive 
    LD REGRESSION: -u --export-dynamic-symbol "f*" archive 
    LD REGRESSION: -u --export-dynamic-symbol-list foo bar archive
    LD REGRESSION: -u --export-dynamic-symbol-list fstar archive 

The failures here all look like:

  extra regexps in ld/testsuite/ld-dynamic/export-dynamic-symbol-2.d starting with "^[0-9a-f]+ T +bar$"

I suspect that this is a target that can be skipped/xfailed.

Next:

  Checking Binutils in: mn10300-elf ... 
    LD REGRESSION: --export-dynamic-symbol foo archive  
    LD REGRESSION: -u --export-dynamic-symbol foo archive 
    LD REGRESSION: -u --export-dynamic-symbol "f*" archive 

These failures are from:

  ./ld-new: tmpdir/dump: error: PHDR segment not covered by LOAD segment

However this failure is showing up for a lot more tests than just your new ones,
so please ignore.  It is obviously a mn10300 specific problem.

Finally:

  Checking Binutils in: sanitize-undefined ... LD: 400  done
    LD REGRESSION: Build libdl2e.so with --export-dynamic-symbol=foo 
    LD REGRESSION: Build libdl2f.so with --dynamic-list=dlempty.list and
    LD REGRESSION: Build libdl2g.so with --export-dynamic-symbol-list=dl2.list 
    LD REGRESSION: Build libdl2h.so with --dynamic-list=dlempty.list and
    LD REGRESSION: Build libdl2i.so with -Bsymbolic and
    LD REGRESSION: Build libdl2j.so with -Bsymbolic and
    LD REGRESSION: Build libdl2k.so with --export-dynamic-symbol-list=dl2.list and

Which are all due to:

  bfd/elf64-x86-64.c:3233:8: runtime error: member access within null pointer of type 'struct elf_x86_link_hash_entry'

I remember trying to look into this before and getting nowhere.  It is however 
another generic problem for linker tests run with the undefined sanitizer enabled
so it is not something that should hold up your patch.

Cheers
  Nick


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: V6 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list
  2020-06-03 10:51                 ` Nick Clifton
@ 2020-06-03 12:12                   ` Alan Modra
  2020-06-03 13:35                     ` [PATCH] x86: Silence -fsanitize=undefined H.J. Lu
  0 siblings, 1 reply; 12+ messages in thread
From: Alan Modra @ 2020-06-03 12:12 UTC (permalink / raw)
  To: Nick Clifton; +Cc: H.J. Lu, Fangrui Song, Binutils

On Wed, Jun 03, 2020 at 11:51:30AM +0100, Nick Clifton wrote:
> Which are all due to:
> 
>   bfd/elf64-x86-64.c:3233:8: runtime error: member access within null pointer of type 'struct elf_x86_link_hash_entry'

This will be "&(EH)->elf" in elfxx-x86.h:GENERATE_DYNAMIC_RELOCATION_P.
Fixable by using "(struct elf_link_hash_entry *) (EH)" instead.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH] x86: Silence -fsanitize=undefined
  2020-06-03 12:12                   ` Alan Modra
@ 2020-06-03 13:35                     ` H.J. Lu
  0 siblings, 0 replies; 12+ messages in thread
From: H.J. Lu @ 2020-06-03 13:35 UTC (permalink / raw)
  To: Alan Modra; +Cc: Nick Clifton, Fangrui Song, Binutils

[-- Attachment #1: Type: text/plain, Size: 482 bytes --]

On Wed, Jun 3, 2020 at 5:12 AM Alan Modra <amodra@gmail.com> wrote:
>
> On Wed, Jun 03, 2020 at 11:51:30AM +0100, Nick Clifton wrote:
> > Which are all due to:
> >
> >   bfd/elf64-x86-64.c:3233:8: runtime error: member access within null pointer of type 'struct elf_x86_link_hash_entry'
>
> This will be "&(EH)->elf" in elfxx-x86.h:GENERATE_DYNAMIC_RELOCATION_P.
> Fixable by using "(struct elf_link_hash_entry *) (EH)" instead.
>

Thanks.  This is what I am checking in.

-- 
H.J.

[-- Attachment #2: 0001-x86-Silence-fsanitize-undefined.patch --]
[-- Type: text/x-patch, Size: 1541 bytes --]

From 433953ffa1a59531a5537327a4e3ce24565e609c Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 3 Jun 2020 06:32:24 -0700
Subject: [PATCH] x86: Silence -fsanitize=undefined

Replace "&(EH)->elf" with "(struct elf_link_hash_entry *) (EH)" to
silence -fsanitize=undefined.

	* elfxx-x86.h (GENERATE_DYNAMIC_RELOCATION_P): Replace
	"&(EH)->elf" with "(struct elf_link_hash_entry *) (EH)".
---
 bfd/ChangeLog   | 5 +++++
 bfd/elfxx-x86.h | 6 +++---
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e60cfac5be..2fa19f8130 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,8 @@
+2020-06-03  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* elfxx-x86.h (GENERATE_DYNAMIC_RELOCATION_P): Silence
+	-fsanitize=undefined.
+
 2020-06-03  Alan Modra  <amodra@gmail.com>
 
 	PR 26069
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index b64c41390a..c717cd16e5 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -133,9 +133,9 @@
 	|| ((ELF_ST_VISIBILITY ((EH)->elf.other) == STV_DEFAULT \
 	     && (!(RESOLVED_TO_ZERO) || PC32_RELOC)) \
 	    || (EH)->elf.root.type != bfd_link_hash_undefweak)) \
-    && ((!X86_PCREL_TYPE_P (R_TYPE) \
-	 && !X86_SIZE_TYPE_P (R_TYPE)) \
-	 || ! SYMBOL_CALLS_LOCAL ((INFO), &(EH)->elf))) \
+    && ((!X86_PCREL_TYPE_P (R_TYPE) && !X86_SIZE_TYPE_P (R_TYPE)) \
+	|| ! SYMBOL_CALLS_LOCAL ((INFO), \
+				 (struct elf_link_hash_entry *) (EH)))) \
    || (ELIMINATE_COPY_RELOCS \
        && !bfd_link_pic (INFO) \
        && (EH) != NULL \
-- 
2.26.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2020-06-03 13:35 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-23 14:47 V2 [PATCH] ld: Add --export-dynamic-symbol and --export-dynamic-symbol-list H.J. Lu
2020-05-23 18:29 ` Fangrui Song
2020-05-23 19:50   ` V3 " H.J. Lu
2020-05-23 21:56     ` Fangrui Song
2020-05-27 14:29       ` V4 " H.J. Lu
2020-05-27 16:19         ` Fangrui Song
2020-05-27 16:24           ` H.J. Lu
2020-05-27 20:24             ` V5 " H.J. Lu
2020-05-28 12:44               ` V6 " H.J. Lu
2020-06-03 10:51                 ` Nick Clifton
2020-06-03 12:12                   ` Alan Modra
2020-06-03 13:35                     ` [PATCH] x86: Silence -fsanitize=undefined H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).