summaryrefslogtreecommitdiff
path: root/ld/lexsup.c
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2020-06-03 06:37:39 -0700
committerH.J. Lu <hjl.tools@gmail.com>2020-06-03 06:37:39 -0700
commit37a141bfed4dd3c33d77c15dfde00e4b4f5b24c7 (patch)
tree05fc3a047c219a7e59357a758472a566e926a570 /ld/lexsup.c
parent433953ffa1a59531a5537327a4e3ce24565e609c (diff)
downloadbinutils-gdb-37a141bfed4dd3c33d77c15dfde00e4b4f5b24c7.tar.gz
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. 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.
Diffstat (limited to 'ld/lexsup.c')
-rw-r--r--ld/lexsup.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 412e2e60267..4808f7443d1 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: