X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Flexsup.c;h=d84b334b346e7d2e49d4482422e1173ecc9ab219;hb=612f258a491539f36c618030cc558e83e7d58b4e;hp=f91549697e24dc43174059314990fea0a138910b;hpb=1914e26482b6d60a0a9fd7fb981ca1ce5e75919b;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/lexsup.c b/ld/lexsup.c index f91549697e..d84b334b34 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -1,5 +1,5 @@ /* Parse options for the GNU linker. - Copyright (C) 1991-2019 Free Software Foundation, Inc. + Copyright (C) 1991-2020 Free Software Foundation, Inc. This file is part of the GNU Binutils. @@ -27,6 +27,7 @@ #include "safe-ctype.h" #include "getopt.h" #include "bfdlink.h" +#include "ctf-api.h" #include "ld.h" #include "ldmain.h" #include "ldmisc.h" @@ -121,6 +122,10 @@ static const struct ld_option ld_options[] = 'E', NULL, N_("Export all dynamic symbols"), TWO_DASHES }, { {"no-export-dynamic", no_argument, NULL, OPTION_NO_EXPORT_DYNAMIC}, '\0', NULL, N_("Undo the effect of --export-dynamic"), TWO_DASHES }, + { {"enable-non-contiguous-regions", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS}, + '\0', NULL, N_("Enable support of non-contiguous memory regions"), TWO_DASHES }, + { {"enable-non-contiguous-regions-warnings", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS}, + '\0', NULL, N_("Enable warnings when --enable-non-contiguous-regions may cause unexpected behaviour"), TWO_DASHES }, { {"EB", no_argument, NULL, OPTION_EB}, '\0', NULL, N_("Link big-endian objects"), ONE_DASH }, { {"EL", no_argument, NULL, OPTION_EL}, @@ -180,6 +185,11 @@ static const struct ld_option ld_options[] = { {"flto-partition=", required_argument, NULL, OPTION_IGNORE}, '\0', NULL, N_("Ignored for GCC LTO option compatibility"), ONE_DASH }, +#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 /* ENABLE_PLUGINS */ { {"fuse-ld=", required_argument, NULL, OPTION_IGNORE}, '\0', NULL, N_("Ignored for GCC linker option compatibility"), @@ -354,7 +364,7 @@ static const struct ld_option ld_options[] = { {"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/.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 }, @@ -499,6 +509,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}, @@ -511,9 +525,16 @@ static const struct ld_option ld_options[] = { {"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 outpout has DT_TEXTREL (default)"), +#else + N_("Warn if outpout 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 }, @@ -564,7 +585,6 @@ parse_args (unsigned argc, char **argv) struct option *longopts; struct option *really_longopts; int last_optind; - enum report_method how_to_report_unresolved_symbols = RM_GENERATE_ERROR; enum symbolic_enum { symbolic_unset = 0, @@ -577,6 +597,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 *) @@ -844,6 +865,12 @@ parse_args (unsigned argc, char **argv) case OPTION_NO_EXPORT_DYNAMIC: link_info.export_dynamic = FALSE; break; + case OPTION_NON_CONTIGUOUS_REGIONS: + link_info.non_contiguous_regions = TRUE; + break; + case OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS: + link_info.non_contiguous_regions_warnings = TRUE; + break; case 'e': lang_add_entry (optarg, TRUE); break; @@ -927,6 +954,7 @@ parse_args (unsigned argc, char **argv) Use --call-shared or -Bdynamic for this. */ break; case 'n': + config.text_read_only = TRUE; config.magic_demand_paged = FALSE; input_flags.dynamic = FALSE; break; @@ -946,15 +974,13 @@ parse_args (unsigned argc, char **argv) link_info.keep_memory = FALSE; break; case OPTION_NO_UNDEFINED: - link_info.unresolved_syms_in_objects - = how_to_report_unresolved_symbols; + link_info.unresolved_syms_in_objects = RM_DIAGNOSE; break; case OPTION_ALLOW_SHLIB_UNDEFINED: link_info.unresolved_syms_in_shared_libs = RM_IGNORE; break; case OPTION_NO_ALLOW_SHLIB_UNDEFINED: - link_info.unresolved_syms_in_shared_libs - = how_to_report_unresolved_symbols; + link_info.unresolved_syms_in_shared_libs = RM_DIAGNOSE; break; case OPTION_UNRESOLVED_SYMBOLS: if (strcmp (optarg, "ignore-all") == 0) @@ -964,40 +990,27 @@ parse_args (unsigned argc, char **argv) } else if (strcmp (optarg, "report-all") == 0) { - link_info.unresolved_syms_in_objects - = how_to_report_unresolved_symbols; - link_info.unresolved_syms_in_shared_libs - = how_to_report_unresolved_symbols; + link_info.unresolved_syms_in_objects = RM_DIAGNOSE; + link_info.unresolved_syms_in_shared_libs = RM_DIAGNOSE; } else if (strcmp (optarg, "ignore-in-object-files") == 0) { link_info.unresolved_syms_in_objects = RM_IGNORE; - link_info.unresolved_syms_in_shared_libs - = how_to_report_unresolved_symbols; + link_info.unresolved_syms_in_shared_libs = RM_DIAGNOSE; } else if (strcmp (optarg, "ignore-in-shared-libs") == 0) { - link_info.unresolved_syms_in_objects - = how_to_report_unresolved_symbols; + link_info.unresolved_syms_in_objects = RM_DIAGNOSE; link_info.unresolved_syms_in_shared_libs = RM_IGNORE; } else einfo (_("%F%P: bad --unresolved-symbols option: %s\n"), optarg); break; case OPTION_WARN_UNRESOLVED_SYMBOLS: - how_to_report_unresolved_symbols = RM_GENERATE_WARNING; - if (link_info.unresolved_syms_in_objects == RM_GENERATE_ERROR) - link_info.unresolved_syms_in_objects = RM_GENERATE_WARNING; - if (link_info.unresolved_syms_in_shared_libs == RM_GENERATE_ERROR) - link_info.unresolved_syms_in_shared_libs = RM_GENERATE_WARNING; + link_info.warn_unresolved_syms = TRUE; break; - case OPTION_ERROR_UNRESOLVED_SYMBOLS: - how_to_report_unresolved_symbols = RM_GENERATE_ERROR; - if (link_info.unresolved_syms_in_objects == RM_GENERATE_WARNING) - link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR; - if (link_info.unresolved_syms_in_shared_libs == RM_GENERATE_WARNING) - link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR; + link_info.warn_unresolved_syms = FALSE; break; case OPTION_ALLOW_MULTIPLE_DEFINITION: link_info.allow_multiple_definition = TRUE; @@ -1394,22 +1407,16 @@ parse_args (unsigned argc, char **argv) break; case OPTION_DYNAMIC_LIST_DATA: opt_dynamic_list = dynamic_list_data; - if (opt_symbolic == symbolic) - opt_symbolic = symbolic_unset; break; case OPTION_DYNAMIC_LIST_CPP_TYPEINFO: lang_append_dynamic_list_cpp_typeinfo (); if (opt_dynamic_list != dynamic_list_data) opt_dynamic_list = dynamic_list; - if (opt_symbolic == symbolic) - opt_symbolic = symbolic_unset; break; case OPTION_DYNAMIC_LIST_CPP_NEW: lang_append_dynamic_list_cpp_new (); if (opt_dynamic_list != dynamic_list_data) opt_dynamic_list = dynamic_list; - if (opt_symbolic == symbolic) - opt_symbolic = symbolic_unset; break; case OPTION_DYNAMIC_LIST: /* This option indicates a small script that only specifies @@ -1422,12 +1429,34 @@ 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; - 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; @@ -1450,8 +1479,8 @@ parse_args (unsigned argc, char **argv) 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; @@ -1489,8 +1518,7 @@ parse_args (unsigned argc, char **argv) case 'Y': if (CONST_STRNEQ (optarg, "P,")) optarg += 2; - if (default_dirlist != NULL) - free (default_dirlist); + free (default_dirlist); default_dirlist = xstrdup (optarg); break; case 'y': @@ -1606,6 +1634,41 @@ parse_args (unsigned argc, char **argv) } } + /* 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; + } + } + } + if (command_line.soname && command_line.soname[0] == '\0') { einfo (_("%P: SONAME must not be empty string; ignored\n")); @@ -1627,16 +1690,72 @@ parse_args (unsigned argc, char **argv) if (link_info.unresolved_syms_in_objects == RM_NOT_YET_SET) /* FIXME: Should we allow emulations a chance to set this ? */ - link_info.unresolved_syms_in_objects = how_to_report_unresolved_symbols; + link_info.unresolved_syms_in_objects = RM_DIAGNOSE; if (link_info.unresolved_syms_in_shared_libs == RM_NOT_YET_SET) /* FIXME: Should we allow emulations a chance to set this ? */ - link_info.unresolved_syms_in_shared_libs = how_to_report_unresolved_symbols; + link_info.unresolved_syms_in_shared_libs = RM_DIAGNOSE; if (bfd_link_relocatable (&link_info) && 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: + break; + case dynamic_list_data: + link_info.dynamic_data = TRUE; + /* Fall through. */ + case dynamic_list: + link_info.dynamic = TRUE; + opt_symbolic = symbolic_unset; + break; + } + /* -Bsymbolic and -Bsymbols-functions are for shared library output. */ if (bfd_link_dll (&link_info)) switch (opt_symbolic) @@ -1656,25 +1775,13 @@ parse_args (unsigned argc, char **argv) free (link_info.dynamic_list); link_info.dynamic_list = NULL; } - opt_dynamic_list = dynamic_list_unset; break; case symbolic_functions: - opt_dynamic_list = dynamic_list_data; + link_info.dynamic = TRUE; + link_info.dynamic_data = TRUE; break; } - switch (opt_dynamic_list) - { - case dynamic_list_unset: - break; - case dynamic_list_data: - link_info.dynamic_data = TRUE; - /* Fall through. */ - case dynamic_list: - link_info.dynamic = TRUE; - break; - } - if (!bfd_link_dll (&link_info)) { if (command_line.filter_shlib) @@ -1779,7 +1886,24 @@ elf_shlib_list_options (FILE *file) fprintf (file, _("\ --exclude-libs=LIBS Make all symbols in LIBS hidden\n")); fprintf (file, _("\ - --hash-style=STYLE Set hash style to sysv, gnu or both\n")); + --hash-style=STYLE Set hash style to sysv/gnu/both. Default: ")); + if (DEFAULT_EMIT_SYSV_HASH) + { + /* Note - these strings are not translated as + they are keywords not descriptive text. */ + if (DEFAULT_EMIT_GNU_HASH) + fprintf (file, "both\n"); + else + fprintf (file, "sysv\n"); + } + else + { + if (DEFAULT_EMIT_GNU_HASH) + fprintf (file, "gnu\n"); + else + /* FIXME: Can this happen ? */ + fprintf (file, "none\n"); + } fprintf (file, _("\ -P AUDITLIB, --depaudit=AUDITLIB\n" "\ Specify a library to use for auditing dependencies\n")); @@ -1841,12 +1965,26 @@ elf_shlib_list_options (FILE *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