#include "ldver.h"
#include "ldemul.h"
#include "demangle.h"
-#ifdef ENABLE_PLUGINS
+#if BFD_SUPPORTS_PLUGINS
#include "plugin.h"
-#endif /* ENABLE_PLUGINS */
+#endif /* BFD_SUPPORTS_PLUGINS */
#ifndef PATH_SEPARATOR
#if defined (__MSDOS__) || (defined (_WIN32) && ! defined (__CYGWIN32__))
'd', NULL, N_("Force common symbols to be defined"), ONE_DASH },
{ {"dp", no_argument, NULL, 'd'},
'\0', NULL, NULL, ONE_DASH },
+ { {"dependency-file", required_argument, NULL, OPTION_DEPENDENCY_FILE},
+ '\0', N_("FILE"), N_("Write dependency file"), TWO_DASHES },
{ {"force-group-allocation", no_argument, NULL,
OPTION_FORCE_GROUP_ALLOCATION},
'\0', NULL, N_("Force group members out of groups"), TWO_DASHES },
'O', NULL, N_("Optimize output file"), ONE_DASH },
{ {"out-implib", required_argument, NULL, OPTION_OUT_IMPLIB},
'\0', N_("FILE"), N_("Generate import library"), TWO_DASHES },
-#ifdef ENABLE_PLUGINS
+#if BFD_SUPPORTS_PLUGINS
{ {"plugin", required_argument, NULL, OPTION_PLUGIN},
'\0', N_("PLUGIN"), N_("Load named plugin"), ONE_DASH },
{ {"plugin-opt", required_argument, NULL, OPTION_PLUGIN_OPT},
{ {"flto-partition=", required_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for GCC LTO option compatibility"),
ONE_DASH },
-#endif /* ENABLE_PLUGINS */
+#else
+ { {"plugin", required_argument, NULL, OPTION_IGNORE},
+ '\0', N_("PLUGIN"), N_("Load named plugin (ignored)"), ONE_DASH },
+ { {"plugin-opt", required_argument, NULL, OPTION_IGNORE},
+ '\0', N_("ARG"), N_("Send arg to last-loaded plugin (ignored)"), ONE_DASH },
+#endif /* BFD_SUPPORTS_PLUGINS */
{ {"fuse-ld=", required_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for GCC linker option compatibility"),
ONE_DASH },
{ {"init", required_argument, NULL, OPTION_INIT},
'\0', N_("SYMBOL"), N_("Call SYMBOL at load-time"), ONE_DASH },
{ {"Map", required_argument, NULL, OPTION_MAP},
- '\0', N_("FILE"), N_("Write a map file"), ONE_DASH },
+ '\0', N_("FILE/DIR"), N_("Write a linker map to FILE or DIR/<outputname>.map"), ONE_DASH },
{ {"no-define-common", no_argument, NULL, OPTION_NO_DEFINE_COMMON},
'\0', NULL, N_("Do not define Common storage"), TWO_DASHES },
{ {"no-demangle", no_argument, NULL, OPTION_NO_DEMANGLE },
{ {"allow-multiple-definition", no_argument, NULL,
OPTION_ALLOW_MULTIPLE_DEFINITION},
'\0', NULL, N_("Allow multiple definitions"), TWO_DASHES },
+#if SUPPORT_ERROR_HANDLING_SCRIPT
+ { {"error-handling-script", required_argument, NULL,
+ OPTION_ERROR_HANDLING_SCRIPT},
+ '\0', N_("SCRIPT"), N_("Provide a script to help with undefined symbol errors"), TWO_DASHES},
+#endif
{ {"no-undefined-version", no_argument, NULL, OPTION_NO_UNDEFINED_VERSION},
'\0', NULL, N_("Disallow undefined version"), TWO_DASHES },
{ {"default-symver", no_argument, NULL, OPTION_DEFAULT_SYMVER},
'\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},
{ {"warn-section-align", no_argument, NULL, OPTION_WARN_SECTION_ALIGN},
'\0', NULL, N_("Warn if start of section changes due to alignment"),
TWO_DASHES },
- { {"warn-shared-textrel", no_argument, NULL, OPTION_WARN_SHARED_TEXTREL},
- '\0', NULL, N_("Warn if shared object has DT_TEXTREL"),
+ { {"warn-textrel", no_argument, NULL, OPTION_WARN_TEXTREL},
+ '\0', NULL,
+#if DEFAULT_LD_TEXTREL_CHECK_WARNING
+ N_("Warn if output has DT_TEXTREL (default)"),
+#else
+ N_("Warn if output has DT_TEXTREL"),
+#endif
TWO_DASHES },
+ { {"warn-shared-textrel", no_argument, NULL, OPTION_WARN_TEXTREL},
+ '\0', NULL, NULL, NO_HELP },
{ {"warn-alternate-em", no_argument, NULL, OPTION_WARN_ALTERNATE_EM},
'\0', NULL, N_("Warn if an object has alternate ELF machine code"),
TWO_DASHES },
{ {"no-print-map-discarded", no_argument, NULL, OPTION_NO_PRINT_MAP_DISCARDED},
'\0', NULL, N_("Do not show discarded sections in map file output"),
TWO_DASHES },
+ { {"ctf-variables", no_argument, NULL, OPTION_CTF_VARIABLES},
+ '\0', NULL, N_("Emit names and types of static variables in CTF"),
+ TWO_DASHES },
+ { {"no-ctf-variables", no_argument, NULL, OPTION_NO_CTF_VARIABLES},
+ '\0', NULL, N_("Do not emit names and types of static variables in CTF"),
+ TWO_DASHES },
+ { {"ctf-share-types=<method>", required_argument, NULL,
+ OPTION_CTF_SHARE_TYPES},
+ '\0', NULL, N_("How to share CTF types between translation units.\n"
+ " <method> is: share-unconflicted (default),\n"
+ " share-duplicated"),
+ TWO_DASHES },
};
#define OPTION_COUNT ARRAY_SIZE (ld_options)
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 *)
xmalloc (sizeof (*longopts) * (OPTION_COUNT + 1));
really_longopts = (struct option *)
- malloc (sizeof (*really_longopts) * (OPTION_COUNT + 1));
+ xmalloc (sizeof (*really_longopts) * (OPTION_COUNT + 1));
/* Starting the short option string with '-' is for programs that
expect options and other ARGV-elements in any order and that care about
optind = last_optind;
optc = getopt_long (argc, argv, "-", really_longopts, &longind);
}
+ /* Attempt to detect grouped short options, eg: "-non-start".
+ Accepting such options is error prone as it is not clear if the user
+ intended "-n -o n-start" or "--non-start". */
+ else if (longind == 0 /* This is a short option. */
+ && optc > 32 /* It is a valid option. */
+ /* The character is not the second character of argv[last_optind]. */
+ && optc != argv[last_optind][1])
+ {
+ if (optarg)
+ einfo (_("%F%P: Error: unable to disambiguate: %s (did you mean -%s ?)\n"),
+ argv[last_optind], argv[last_optind]);
+ else
+ einfo (_("%P: Warning: grouped short command line options are deprecated: %s\n"), argv[last_optind]);
+ }
if (ldemul_handle_option (optc))
continue;
case OPTION_ALLOW_MULTIPLE_DEFINITION:
link_info.allow_multiple_definition = TRUE;
break;
+
+#if SUPPORT_ERROR_HANDLING_SCRIPT
+ case OPTION_ERROR_HANDLING_SCRIPT:
+ /* FIXME: Should we warn if the script is being overridden by another ?
+ Or maybe they should be chained together ? */
+ error_handling_script = optarg;
+ break;
+#endif
+
case OPTION_NO_UNDEFINED_VERSION:
link_info.allow_undefined_version = FALSE;
break;
case OPTION_PRINT_OUTPUT_FORMAT:
command_line.print_output_format = TRUE;
break;
-#ifdef ENABLE_PLUGINS
+#if BFD_SUPPORTS_PLUGINS
case OPTION_PLUGIN:
plugin_opt_plugin (optarg);
break;
if (plugin_opt_plugin_arg (optarg))
einfo (_("%F%P: bad -plugin-opt option\n"));
break;
-#endif /* ENABLE_PLUGINS */
+#endif /* BFD_SUPPORTS_PLUGINS */
case 'q':
link_info.emitrelocations = TRUE;
break;
int level ATTRIBUTE_UNUSED = strtoul (optarg, &end, 0);
if (*end)
einfo (_("%F%P: invalid number `%s'\n"), optarg);
-#ifdef ENABLE_PLUGINS
+#if BFD_SUPPORTS_PLUGINS
report_plugin_symbols = level > 1;
-#endif /* ENABLE_PLUGINS */
+#endif /* BFD_SUPPORTS_PLUGINS */
}
break;
case 'v':
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;
case OPTION_WARN_SECTION_ALIGN:
config.warn_section_align = TRUE;
break;
- case OPTION_WARN_SHARED_TEXTREL:
- link_info.warn_shared_textrel = TRUE;
+ case OPTION_WARN_TEXTREL:
+ link_info.textrel_check = textrel_check_warning;
break;
case OPTION_WARN_ALTERNATE_EM:
link_info.warn_alternate_em = TRUE;
case OPTION_PRINT_MAP_DISCARDED:
config.print_map_discarded = TRUE;
break;
+
+ case OPTION_DEPENDENCY_FILE:
+ config.dependency_file = optarg;
+ break;
+
+ case OPTION_CTF_VARIABLES:
+ config.ctf_variables = TRUE;
+ break;
+
+ case OPTION_NO_CTF_VARIABLES:
+ config.ctf_variables = FALSE;
+ break;
+
+ case OPTION_CTF_SHARE_TYPES:
+ if (strcmp (optarg, "share-unconflicted") == 0)
+ config.ctf_share_duplicated = FALSE;
+ else if (strcmp (optarg, "share-duplicated") == 0)
+ config.ctf_share_duplicated = TRUE;
+ else
+ einfo (_("%F%P: bad --ctf-share-types option: %s\n"), optarg);
+ break;
+ }
+ }
+
+ /* Run a couple of checks on the map filename. */
+ if (config.map_filename)
+ {
+ if (config.map_filename[0] == 0)
+ {
+ einfo (_("%P: no file/directory name provided for map output; ignored\n"));
+ config.map_filename = NULL;
+ }
+ else
+ {
+ struct stat s;
+
+ /* If the map filename is actually a directory then create
+ a file inside it, based upon the output filename. */
+ if (stat (config.map_filename, &s) >= 0
+ && S_ISDIR (s.st_mode))
+ {
+ char * new_name;
+
+ /* FIXME: This is a (trivial) memory leak. */
+ if (asprintf (&new_name, "%s/%s.map",
+ config.map_filename, output_filename) < 0)
+ {
+ /* If this alloc fails then something is probably very
+ wrong. Better to halt now rather than continue on
+ into more problems. */
+ einfo (_("%P%F: cannot create name for linker map file: %E\n"));
+ new_name = NULL;
+ }
+
+ config.map_filename = new_name;
+ }
}
}
&& 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:
-z nocombreloc Don't merge dynamic relocs into one section\n"));
fprintf (file, _("\
-z global Make symbols in DSO available for subsequently\n\
- loaded objects\n"));
+ loaded objects\n"));
fprintf (file, _("\
-z initfirst Mark DSO to be initialized first at runtime\n"));
fprintf (file, _("\
-z nocommon Generate common symbols with STT_OBJECT type\n"));
fprintf (file, _("\
-z stack-size=SIZE Set size of stack segment\n"));
- fprintf (file, _("\
- -z text Treat DT_TEXTREL in shared object as error\n"));
- fprintf (file, _("\
- -z notext Don't treat DT_TEXTREL in shared object as error\n"));
- fprintf (file, _("\
- -z textoff Don't treat DT_TEXTREL in shared object as error\n"));
+ if (link_info.textrel_check == textrel_check_error)
+ fprintf (file, _("\
+ -z text Treat DT_TEXTREL in output as error (default)\n"));
+ else
+ fprintf (file, _("\
+ -z text Treat DT_TEXTREL in output as error\n"));
+ if (link_info.textrel_check == textrel_check_none)
+ {
+ fprintf (file, _("\
+ -z notext Don't treat DT_TEXTREL in output as error (default)\n"));
+ fprintf (file, _("\
+ -z textoff Don't treat DT_TEXTREL in output as error (default)\n"));
+ }
+ else
+ {
+ fprintf (file, _("\
+ -z notext Don't treat DT_TEXTREL in output as error\n"));
+ fprintf (file, _("\
+ -z textoff Don't treat DT_TEXTREL in output as error\n"));
+ }
}
static void
Compress DWARF debug sections using zlib\n"));
#ifdef DEFAULT_FLAG_COMPRESS_DEBUG
fprintf (file, _("\
- Default: zlib-gabi\n"));
+ Default: zlib-gabi\n"));
#else
fprintf (file, _("\
- Default: none\n"));
+ Default: none\n"));
#endif
fprintf (file, _("\
-z common-page-size=SIZE Set common page size to SIZE\n"));
fprintf (file, _("\
-z noexecstack Mark executable as not requiring executable stack\n"));
fprintf (file, _("\
+ -z unique-symbol Avoid duplicated local symbol names\n"));
+ fprintf (file, _("\
+ -z nounique-symbol Keep duplicated local symbol names (default)\n"));
+ fprintf (file, _("\
-z globalaudit Mark executable requiring global auditing\n"));
}