X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=ld%2Fldmain.c;h=ea72b14a301dc41a5aee7e91772881705039f073;hb=d7c448293af68af5fc270d90d3746e39a496e750;hp=2f15ba72a9c6aeddf40761c3ff6d5a4b13428bf5;hpb=fb47deda560b754008c35b5ec13fe02ef0593019;p=binutils-gdb.git diff --git a/ld/ldmain.c b/ld/ldmain.c index 2f15ba72a9c..ea72b14a301 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -1,5 +1,5 @@ /* Main program of GNU linker. - Copyright (C) 1991-2016 Free Software Foundation, Inc. + Copyright (C) 1991-2022 Free Software Foundation, Inc. Written by Steve Chamberlain steve@cygnus.com This file is part of the GNU Binutils. @@ -25,7 +25,9 @@ #include "libiberty.h" #include "progress.h" #include "bfdlink.h" +#include "ctf-api.h" #include "filenames.h" +#include "elf/common.h" #include "ld.h" #include "ldmain.h" @@ -38,10 +40,10 @@ #include "ldfile.h" #include "ldemul.h" #include "ldctor.h" -#ifdef ENABLE_PLUGINS +#if BFD_SUPPORTS_PLUGINS #include "plugin.h" #include "plugin-api.h" -#endif /* ENABLE_PLUGINS */ +#endif /* BFD_SUPPORTS_PLUGINS */ /* Somewhere above, sys/stat.h got included. */ #if !defined(S_ISDIR) && defined(S_IFDIR) @@ -50,12 +52,6 @@ #include -#ifdef HAVE_SBRK -#if !HAVE_DECL_SBRK -extern void *sbrk (); -#endif -#endif - #ifndef TARGET_SYSTEM_ROOT #define TARGET_SYSTEM_ROOT "" #endif @@ -64,7 +60,7 @@ extern void *sbrk (); FILE *saved_script_handle = NULL; FILE *previous_script_handle = NULL; -bfd_boolean force_make_executable = FALSE; +bool force_make_executable = false; char *default_target; const char *output_filename = "a.out"; @@ -83,17 +79,17 @@ int ld_canon_sysroot_len; int g_switch_value = 8; /* Nonzero means print names of input files as processed. */ -bfd_boolean trace_files; +unsigned int trace_files; /* Nonzero means report actions taken by the linker, and describe the linker script in use. */ -bfd_boolean verbose; +bool verbose; /* Nonzero means version number was printed, so exit successfully instead of complaining if no input files are given. */ -bfd_boolean version_printed; +bool version_printed; /* TRUE if we should demangle symbol names. */ -bfd_boolean demangling; +bool demangling; args_type command_line; @@ -105,7 +101,7 @@ static const char *get_sysroot (int, char **); static char *get_emulation (int, char **); -static bfd_boolean add_archive_element +static bool add_archive_element (struct bfd_link_info *, bfd *, const char *, bfd **); static void multiple_definition (struct bfd_link_info *, struct bfd_link_hash_entry *, @@ -117,7 +113,7 @@ static void add_to_set (struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_reloc_code_real_type, bfd *, asection *, bfd_vma); static void constructor_callback - (struct bfd_link_info *, bfd_boolean, const char *, bfd *, + (struct bfd_link_info *, bool, const char *, bfd *, asection *, bfd_vma); static void warning_callback (struct bfd_link_info *, const char *, const char *, bfd *, @@ -126,7 +122,7 @@ static void warning_find_reloc (bfd *, asection *, void *); static void undefined_symbol (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma, - bfd_boolean); + bool); static void reloc_overflow (struct bfd_link_info *, struct bfd_link_hash_entry *, const char *, const char *, bfd_vma, bfd *, asection *, bfd_vma); @@ -134,7 +130,7 @@ static void reloc_dangerous (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma); static void unattached_reloc (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma); -static bfd_boolean notice +static bool notice (struct bfd_link_info *, struct bfd_link_hash_entry *, struct bfd_link_hash_entry *, bfd *, asection *, bfd_vma, flagword); @@ -154,7 +150,11 @@ static struct bfd_link_callbacks link_callbacks = einfo, info_msg, minfo, - ldlang_override_segment_assignment + ldlang_override_segment_assignment, + ldlang_ctf_acquire_strings, + NULL, + ldlang_ctf_new_dynsym, + ldlang_write_ctf_late }; static bfd_assert_handler_type default_bfd_assert_handler; @@ -162,11 +162,58 @@ static bfd_error_handler_type default_bfd_error_handler; struct bfd_link_info link_info; +struct dependency_file +{ + struct dependency_file *next; + char *name; +}; + +static struct dependency_file *dependency_files, *dependency_files_tail; + +void +track_dependency_files (const char *filename) +{ + struct dependency_file *dep + = (struct dependency_file *) xmalloc (sizeof (*dep)); + dep->name = xstrdup (filename); + dep->next = NULL; + if (dependency_files == NULL) + dependency_files = dep; + else + dependency_files_tail->next = dep; + dependency_files_tail = dep; +} + +static void +write_dependency_file (void) +{ + FILE *out; + struct dependency_file *dep; + + out = fopen (config.dependency_file, FOPEN_WT); + if (out == NULL) + { + einfo (_("%F%P: cannot open dependency file %s: %E\n"), + config.dependency_file); + } + + fprintf (out, "%s:", output_filename); + + for (dep = dependency_files; dep != NULL; dep = dep->next) + fprintf (out, " \\\n %s", dep->name); + + fprintf (out, "\n"); + for (dep = dependency_files; dep != NULL; dep = dep->next) + fprintf (out, "\n%s:\n", dep->name); + + fclose (out); +} + static void ld_cleanup (void) { bfd_cache_close_all (); -#ifdef ENABLE_PLUGINS +#if BFD_SUPPORTS_PLUGINS plugin_call_cleanup (); #endif if (output_filename && delete_output_file_on_failure) @@ -179,7 +226,7 @@ static void ld_bfd_assert_handler (const char *fmt, const char *bfdver, const char *file, int line) { - config.make_executable = FALSE; + config.make_executable = false; (*default_bfd_assert_handler) (fmt, bfdver, file, line); } @@ -189,7 +236,7 @@ static void ld_bfd_error_handler (const char *fmt, va_list ap) { if (config.fatal_warnings) - config.make_executable = FALSE; + config.make_executable = false; (*default_bfd_error_handler) (fmt, ap); } @@ -198,16 +245,11 @@ main (int argc, char **argv) { char *emulation; long start_time = get_run_time (); -#ifdef HAVE_SBRK - char *start_sbrk = (char *) sbrk (0); -#endif -#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) +#ifdef HAVE_LC_MESSAGES setlocale (LC_MESSAGES, ""); #endif -#if defined (HAVE_SETLOCALE) setlocale (LC_CTYPE, ""); -#endif bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); @@ -218,7 +260,8 @@ main (int argc, char **argv) expandargv (&argc, &argv); - bfd_init (); + if (bfd_init () != BFD_INIT_MAGIC) + einfo (_("%F%P: fatal error: libbfd ABI mismatch\n")); bfd_set_error_program_name (program_name); @@ -237,7 +280,14 @@ main (int argc, char **argv) if (*ld_sysroot) ld_canon_sysroot = lrealpath (ld_sysroot); if (ld_canon_sysroot) - ld_canon_sysroot_len = strlen (ld_canon_sysroot); + { + ld_canon_sysroot_len = strlen (ld_canon_sysroot); + + /* is_sysrooted_pathname() relies on no trailing dirsep. */ + if (ld_canon_sysroot_len > 0 + && IS_DIR_SEPARATOR (ld_canon_sysroot [ld_canon_sysroot_len - 1])) + ld_canon_sysroot [--ld_canon_sysroot_len] = '\0'; + } else ld_canon_sysroot_len = -1; @@ -258,17 +308,18 @@ main (int argc, char **argv) } #endif - config.build_constructors = TRUE; + config.build_constructors = true; config.rpath_separator = ':'; config.split_by_reloc = (unsigned) -1; config.split_by_file = (bfd_size_type) -1; - config.make_executable = TRUE; - config.magic_demand_paged = TRUE; - config.text_read_only = TRUE; + config.make_executable = true; + config.magic_demand_paged = true; + config.text_read_only = true; + config.print_map_discarded = true; link_info.disable_target_specific_optimizations = -1; - command_line.warn_mismatch = TRUE; - command_line.warn_search_mismatch = TRUE; + command_line.warn_mismatch = true; + command_line.warn_search_mismatch = true; command_line.check_section_addresses = -1; /* We initialize DEMANGLING based on the environment variable @@ -278,11 +329,15 @@ main (int argc, char **argv) interface by default. */ demangling = getenv ("COLLECT_NO_DEMANGLE") == NULL; - link_info.allow_undefined_version = TRUE; - link_info.keep_memory = TRUE; - link_info.combreloc = TRUE; - link_info.strip_discarded = TRUE; - link_info.emit_hash = TRUE; + link_info.allow_undefined_version = true; + link_info.keep_memory = true; + link_info.max_cache_size = (bfd_size_type) -1; + link_info.combreloc = true; + link_info.strip_discarded = true; + link_info.prohibit_multiple_definition_absolute = false; + link_info.textrel_check = DEFAULT_LD_TEXTREL_CHECK; + link_info.emit_hash = DEFAULT_EMIT_SYSV_HASH; + link_info.emit_gnu_hash = DEFAULT_EMIT_GNU_HASH; link_info.callbacks = &link_callbacks; link_info.input_bfds_tail = &link_info.input_bfds; /* SVR4 linkers seem to set DT_INIT and DT_FINI based on magic _init @@ -292,32 +347,36 @@ main (int argc, char **argv) link_info.relax_pass = 1; link_info.extern_protected_data = -1; link_info.dynamic_undefined_weak = -1; + link_info.indirect_extern_access = -1; link_info.pei386_auto_import = -1; link_info.spare_dynamic_tags = 5; link_info.path_separator = ':'; #ifdef DEFAULT_FLAG_COMPRESS_DEBUG link_info.compress_debug = COMPRESS_DEBUG_GABI_ZLIB; #endif +#ifdef DEFAULT_NEW_DTAGS + link_info.new_dtags = DEFAULT_NEW_DTAGS; +#endif + link_info.start_stop_gc = false; + link_info.start_stop_visibility = STV_PROTECTED; ldfile_add_arch (""); emulation = get_emulation (argc, argv); ldemul_choose_mode (emulation); default_target = ldemul_choose_target (argc, argv); - config.maxpagesize = bfd_emul_get_maxpagesize (default_target); - config.commonpagesize = bfd_emul_get_commonpagesize (default_target); lang_init (); ldexp_init (); ldemul_before_parse (); - lang_has_input_file = FALSE; + lang_has_input_file = false; parse_args (argc, argv); if (config.hash_table_size != 0) bfd_hash_set_default_size (config.hash_table_size); -#ifdef ENABLE_PLUGINS +#if BFD_SUPPORTS_PLUGINS /* Now all the plugin arguments have been gathered, we can load them. */ plugin_load_plugins (); -#endif /* ENABLE_PLUGINS */ +#endif /* BFD_SUPPORTS_PLUGINS */ ldemul_set_symbols (); @@ -326,7 +385,7 @@ main (int argc, char **argv) if (saved_script_handle == NULL && command_line.default_script != NULL) { - ldfile_open_command_file (command_line.default_script); + ldfile_open_script_file (command_line.default_script); parser_input = input_script; yyparse (); } @@ -368,7 +427,7 @@ main (int argc, char **argv) while ((n = fread (buf, 1, ld_bufsz - 1, saved_script_handle)) > 0) { buf[n] = 0; - info_msg (buf); + info_msg ("%s", buf); } rewind (saved_script_handle); free (buf); @@ -383,6 +442,12 @@ main (int argc, char **argv) info_msg ("\n==================================================\n"); } + if (command_line.force_group_allocation + || !bfd_link_relocatable (&link_info)) + link_info.resolve_section_groups = true; + else + link_info.resolve_section_groups = false; + if (command_line.print_output_format) info_msg ("%s\n", lang_get_output_target ()); @@ -395,14 +460,17 @@ main (int argc, char **argv) if (argc == 2 && version_printed) xexit (0); + if (link_info.inhibit_common_definition && !bfd_link_dll (&link_info)) + einfo (_("%F%P: --no-define-common may not be used without -shared\n")); + if (!lang_has_input_file) { if (version_printed || command_line.print_output_format) xexit (0); - einfo (_("%P%F: no input files\n")); + einfo (_("%F%P: no input files\n")); } - if (trace_files) + if (verbose) info_msg (_("%P: mode %s\n"), emulation); ldemul_after_parse (); @@ -419,10 +487,11 @@ main (int argc, char **argv) if (config.map_file == (FILE *) NULL) { bfd_set_error (bfd_error_system_call); - einfo (_("%P%F: cannot open map file %s: %E\n"), + einfo (_("%F%P: cannot open map file %s: %E\n"), config.map_filename); } } + link_info.has_map_file = true; } lang_process (); @@ -462,12 +531,15 @@ main (int argc, char **argv) ldexp_finish (); lang_finish (); + if (config.dependency_file != NULL) + write_dependency_file (); + /* Even if we're producing relocatable output, some non-fatal errors should be reported in the exit status. (What non-fatal errors, if any, do we want to ignore for relocatable output?) */ if (!config.make_executable && !force_make_executable) { - if (trace_files) + if (verbose) einfo (_("%P: link errors found, deleting executable `%s'\n"), output_filename); @@ -477,7 +549,7 @@ main (int argc, char **argv) else { if (!bfd_close (link_info.output_bfd)) - einfo (_("%F%B: final close failed: %E\n"), link_info.output_bfd); + einfo (_("%F%P: %pB: final close failed: %E\n"), link_info.output_bfd); /* If the --force-exe-suffix is enabled, and we're making an executable file and it doesn't end in .exe, copy it to one @@ -504,22 +576,22 @@ main (int argc, char **argv) dst = fopen (dst_name, FOPEN_WB); if (!src) - einfo (_("%P%F: unable to open for source of copy `%s'\n"), + einfo (_("%F%P: unable to open for source of copy `%s'\n"), output_filename); if (!dst) - einfo (_("%P%F: unable to open for destination of copy `%s'\n"), + einfo (_("%F%P: unable to open for destination of copy `%s'\n"), dst_name); while ((l = fread (buf, 1, bsize, src)) > 0) { int done = fwrite (buf, 1, l, dst); if (done != l) - einfo (_("%P: Error writing file `%s'\n"), dst_name); + einfo (_("%P: error writing file `%s'\n"), dst_name); } fclose (src); if (fclose (dst) == EOF) - einfo (_("%P: Error closing file `%s'\n"), dst_name); + einfo (_("%P: error closing file `%s'\n"), dst_name); free (dst_name); free (buf); } @@ -530,18 +602,11 @@ main (int argc, char **argv) if (config.stats) { -#ifdef HAVE_SBRK - char *lim = (char *) sbrk (0); -#endif long run_time = get_run_time () - start_time; fflush (stdout); fprintf (stderr, _("%s: total time in link: %ld.%06ld\n"), program_name, run_time / 1000000, run_time % 1000000); -#ifdef HAVE_SBRK - fprintf (stderr, _("%s: data size %ld\n"), program_name, - (long) (lim - start_sbrk)); -#endif fflush (stderr); } @@ -580,21 +645,25 @@ static const char * get_sysroot (int argc, char **argv) { int i; - const char *path; + const char *path = NULL; for (i = 1; i < argc; i++) - if (CONST_STRNEQ (argv[i], "--sysroot=")) - return argv[i] + strlen ("--sysroot="); + if (startswith (argv[i], "--sysroot=")) + path = argv[i] + strlen ("--sysroot="); - path = get_relative_sysroot (BINDIR); - if (path) - return path; + if (!path) + path = get_relative_sysroot (BINDIR); - path = get_relative_sysroot (TOOLBINDIR); - if (path) - return path; + if (!path) + path = get_relative_sysroot (TOOLBINDIR); + + if (!path) + path = TARGET_SYSTEM_ROOT; - return TARGET_SYSTEM_ROOT; + if (IS_DIR_SEPARATOR (*path) && path[1] == 0) + path = ""; + + return path; } /* We need to find any explicitly given emulation in order to initialize the @@ -612,7 +681,7 @@ get_emulation (int argc, char **argv) for (i = 1; i < argc; i++) { - if (CONST_STRNEQ (argv[i], "-m")) + if (startswith (argv[i], "-m")) { if (argv[i][2] == '\0') { @@ -623,7 +692,7 @@ get_emulation (int argc, char **argv) i++; } else - einfo (_("%P%F: missing argument to -m\n")); + einfo (_("%F%P: missing argument to -m\n")); } else if (strcmp (argv[i], "-mips1") == 0 || strcmp (argv[i], "-mips2") == 0 @@ -632,9 +701,13 @@ get_emulation (int argc, char **argv) || strcmp (argv[i], "-mips5") == 0 || strcmp (argv[i], "-mips32") == 0 || strcmp (argv[i], "-mips32r2") == 0 + || strcmp (argv[i], "-mips32r3") == 0 + || strcmp (argv[i], "-mips32r5") == 0 || strcmp (argv[i], "-mips32r6") == 0 || strcmp (argv[i], "-mips64") == 0 || strcmp (argv[i], "-mips64r2") == 0 + || strcmp (argv[i], "-mips64r3") == 0 + || strcmp (argv[i], "-mips64r5") == 0 || strcmp (argv[i], "-mips64r6") == 0) { /* FIXME: The arguments -mips1, -mips2, -mips3, etc. are @@ -673,11 +746,11 @@ add_ysym (const char *name) bfd_hash_newfunc, sizeof (struct bfd_hash_entry), 61)) - einfo (_("%P%F: bfd_hash_table_init failed: %E\n")); + einfo (_("%F%P: bfd_hash_table_init failed: %E\n")); } - if (bfd_hash_lookup (link_info.notice_hash, name, TRUE, TRUE) == NULL) - einfo (_("%P%F: bfd_hash_lookup failed: %E\n")); + if (bfd_hash_lookup (link_info.notice_hash, name, true, true) == NULL) + einfo (_("%F%P: bfd_hash_lookup failed: %E\n")); } void @@ -690,11 +763,11 @@ add_ignoresym (struct bfd_link_info *info, const char *name) bfd_hash_newfunc, sizeof (struct bfd_hash_entry), 61)) - einfo (_("%P%F: bfd_hash_table_init failed: %E\n")); + einfo (_("%F%P: bfd_hash_table_init failed: %E\n")); } - if (bfd_hash_lookup (info->ignore_hash, name, TRUE, TRUE) == NULL) - einfo (_("%P%F: bfd_hash_lookup failed: %E\n")); + if (bfd_hash_lookup (info->ignore_hash, name, true, true) == NULL) + einfo (_("%F%P: bfd_hash_lookup failed: %E\n")); } /* Record a symbol to be wrapped, from the --wrap option. */ @@ -710,11 +783,11 @@ add_wrap (const char *name) bfd_hash_newfunc, sizeof (struct bfd_hash_entry), 61)) - einfo (_("%P%F: bfd_hash_table_init failed: %E\n")); + einfo (_("%F%P: bfd_hash_table_init failed: %E\n")); } - if (bfd_hash_lookup (link_info.wrap_hash, name, TRUE, TRUE) == NULL) - einfo (_("%P%F: bfd_hash_lookup failed: %E\n")); + if (bfd_hash_lookup (link_info.wrap_hash, name, true, true) == NULL) + einfo (_("%F%P: bfd_hash_lookup failed: %E\n")); } /* Handle the -retain-symbols-file option. */ @@ -742,7 +815,7 @@ add_keepsyms_file (const char *filename) xmalloc (sizeof (struct bfd_hash_table)); if (!bfd_hash_table_init (link_info.keep_hash, bfd_hash_newfunc, sizeof (struct bfd_hash_entry))) - einfo (_("%P%F: bfd_hash_table_init failed: %E\n")); + einfo (_("%F%P: bfd_hash_table_init failed: %E\n")); bufsize = 100; buf = (char *) xmalloc (bufsize); @@ -771,8 +844,8 @@ add_keepsyms_file (const char *filename) buf[len] = '\0'; - if (bfd_hash_lookup (link_info.keep_hash, buf, TRUE, TRUE) == NULL) - einfo (_("%P%F: bfd_hash_lookup for insertion failed: %E\n")); + if (bfd_hash_lookup (link_info.keep_hash, buf, true, true) == NULL) + einfo (_("%F%P: bfd_hash_lookup for insertion failed: %E\n")); } } @@ -789,27 +862,28 @@ add_keepsyms_file (const char *filename) /* This is called when BFD has decided to include an archive member in a link. */ -static bfd_boolean +static bool add_archive_element (struct bfd_link_info *info, bfd *abfd, const char *name, bfd **subsbfd ATTRIBUTE_UNUSED) { lang_input_statement_type *input; + lang_input_statement_type *parent; lang_input_statement_type orig_input; input = (lang_input_statement_type *) xcalloc (1, sizeof (lang_input_statement_type)); input->header.type = lang_input_statement_enum; - input->filename = abfd->filename; - input->local_sym_name = abfd->filename; + input->filename = bfd_get_filename (abfd); + input->local_sym_name = bfd_get_filename (abfd); input->the_bfd = abfd; /* Save the original data for trace files/tries below, as plugins (if enabled) may possibly alter it to point to a replacement BFD, but we still want to output the original BFD filename. */ orig_input = *input; -#ifdef ENABLE_PLUGINS +#if BFD_SUPPORTS_PLUGINS if (link_info.lto_plugin_active) { /* We must offer this archive member to the plugins to claim. */ @@ -820,28 +894,49 @@ add_archive_element (struct bfd_link_info *info, { /* Don't claim new IR symbols after all IR symbols have been claimed. */ - if (trace_files || verbose) - info_msg ("%I: no new IR symbols to claimi\n", + if (verbose) + info_msg ("%pI: no new IR symbols to claim\n", &orig_input); input->flags.claimed = 0; - return FALSE; + return false; } - input->flags.claim_archive = TRUE; + input->flags.claim_archive = true; *subsbfd = input->the_bfd; } } -#endif /* ENABLE_PLUGINS */ +#endif /* BFD_SUPPORTS_PLUGINS */ + + if (link_info.input_bfds_tail == &input->the_bfd->link.next + || input->the_bfd->link.next != NULL) + { + /* We have already loaded this element, and are attempting to + load it again. This can happen when the archive map doesn't + match actual symbols defined by the element. */ + free (input); + bfd_set_error (bfd_error_malformed_archive); + return false; + } + + /* Set the file_chain pointer of archives to the last element loaded + from the archive. See ldlang.c:find_rescan_insertion. */ + parent = bfd_usrdata (abfd->my_archive); + if (parent != NULL && !parent->flags.reload) + parent->next = input; ldlang_add_file (input); if (config.map_file != NULL) { - static bfd_boolean header_printed; + static bool header_printed; struct bfd_link_hash_entry *h; bfd *from; int len; - h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE); + h = bfd_link_hash_lookup (info->hash, name, false, false, true); + if (h == NULL + && info->pei386_auto_import + && startswith (name, "__imp_")) + h = bfd_link_hash_lookup (info->hash, name + 6, false, false, true); if (h == NULL) from = NULL; @@ -871,12 +966,8 @@ add_archive_element (struct bfd_link_info *info, if (!header_printed) { - char buf[100]; - - sprintf (buf, _("Archive member included " - "to satisfy reference by file (symbol)\n\n")); - minfo ("%s", buf); - header_printed = TRUE; + minfo (_("Archive member included to satisfy reference by file (symbol)\n\n")); + header_printed = true; } if (abfd->my_archive == NULL @@ -906,16 +997,18 @@ add_archive_element (struct bfd_link_info *info, } if (from != NULL) - minfo ("%B ", from); + minfo ("%pB ", from); if (h != NULL) - minfo ("(%T)\n", h->root.string); + minfo ("(%pT)\n", h->root.string); else minfo ("(%s)\n", name); } - if (trace_files || verbose) - info_msg ("%I\n", &orig_input); - return TRUE; + if (verbose + || trace_files > 1 + || (trace_files && bfd_is_thin_archive (orig_input.the_bfd->my_archive))) + info_msg ("%pI\n", &orig_input); + return true; } /* This is called when BFD has discovered a symbol which is defined @@ -965,12 +1058,13 @@ multiple_definition (struct bfd_link_info *info, discarded, and this is not really a multiple definition at all. FIXME: It would be cleaner to somehow ignore symbols defined in sections which are being discarded. */ - if ((osec->output_section != NULL - && !bfd_is_abs_section (osec) - && bfd_is_abs_section (osec->output_section)) - || (nsec->output_section != NULL - && !bfd_is_abs_section (nsec) - && bfd_is_abs_section (nsec->output_section))) + if (!info->prohibit_multiple_definition_absolute + && ((osec->output_section != NULL + && ! bfd_is_abs_section (osec) + && bfd_is_abs_section (osec->output_section)) + || (nsec->output_section != NULL + && !bfd_is_abs_section (nsec) + && bfd_is_abs_section (nsec->output_section)))) return; name = h->root.string; @@ -981,14 +1075,19 @@ multiple_definition (struct bfd_link_info *info, nval = oval; obfd = NULL; } - einfo (_("%X%C: multiple definition of `%T'\n"), - nbfd, nsec, nval, name); + if (info->warn_multiple_definition) + einfo (_("%P: %C: warning: multiple definition of `%pT'"), + nbfd, nsec, nval, name); + else + einfo (_("%X%P: %C: multiple definition of `%pT'"), + nbfd, nsec, nval, name); if (obfd != NULL) - einfo (_("%D: first defined here\n"), obfd, osec, oval); + einfo (_("; %D: first defined here"), obfd, osec, oval); + einfo ("\n"); if (RELAXATION_ENABLED_BY_USER) { - einfo (_("%P: Disabling relaxation: it will not work with multiple definitions\n")); + einfo (_("%P: disabling relaxation; it will not work with multiple definitions\n")); DISABLE_RELAXATION; } } @@ -1040,43 +1139,60 @@ multiple_common (struct bfd_link_info *info ATTRIBUTE_UNUSED, || ntype == bfd_link_hash_indirect) { ASSERT (otype == bfd_link_hash_common); - einfo (_("%B: warning: definition of `%T' overriding common\n"), - nbfd, name); if (obfd != NULL) - einfo (_("%B: warning: common is here\n"), obfd); + einfo (_("%P: %pB: warning: definition of `%pT' overriding common" + " from %pB\n"), + nbfd, name, obfd); + else + einfo (_("%P: %pB: warning: definition of `%pT' overriding common\n"), + nbfd, name); } else if (otype == bfd_link_hash_defined || otype == bfd_link_hash_defweak || otype == bfd_link_hash_indirect) { ASSERT (ntype == bfd_link_hash_common); - einfo (_("%B: warning: common of `%T' overridden by definition\n"), - nbfd, name); if (obfd != NULL) - einfo (_("%B: warning: defined here\n"), obfd); + einfo (_("%P: %pB: warning: common of `%pT' overridden by definition" + " from %pB\n"), + nbfd, name, obfd); + else + einfo (_("%P: %pB: warning: common of `%pT' overridden by definition\n"), + nbfd, name); } else { ASSERT (otype == bfd_link_hash_common && ntype == bfd_link_hash_common); if (osize > nsize) { - einfo (_("%B: warning: common of `%T' overridden by larger common\n"), - nbfd, name); if (obfd != NULL) - einfo (_("%B: warning: larger common is here\n"), obfd); + einfo (_("%P: %pB: warning: common of `%pT' overridden" + " by larger common from %pB\n"), + nbfd, name, obfd); + else + einfo (_("%P: %pB: warning: common of `%pT' overridden" + " by larger common\n"), + nbfd, name); } else if (nsize > osize) { - einfo (_("%B: warning: common of `%T' overriding smaller common\n"), - nbfd, name); if (obfd != NULL) - einfo (_("%B: warning: smaller common is here\n"), obfd); + einfo (_("%P: %pB: warning: common of `%pT' overriding" + " smaller common from %pB\n"), + nbfd, name, obfd); + else + einfo (_("%P: %pB: warning: common of `%pT' overriding" + " smaller common\n"), + nbfd, name); } else { - einfo (_("%B: warning: multiple common of `%T'\n"), nbfd, name); if (obfd != NULL) - einfo (_("%B: warning: previous common is here\n"), obfd); + einfo (_("%P: %pB and %pB: warning: multiple common of `%pT'\n"), + nbfd, obfd, name); + else + einfo (_("%P: %pB: warning: multiple common of `%pT'\n"), + nbfd, name); } } } @@ -1119,7 +1235,7 @@ add_to_set (struct bfd_link_info *info ATTRIBUTE_UNUSED, static void constructor_callback (struct bfd_link_info *info, - bfd_boolean constructor, + bool constructor, const char *name, bfd *abfd, asection *section, @@ -1140,7 +1256,7 @@ constructor_callback (struct bfd_link_info *info, if (bfd_reloc_type_lookup (info->output_bfd, BFD_RELOC_CTOR) == NULL && (bfd_link_relocatable (info) || bfd_reloc_type_lookup (abfd, BFD_RELOC_CTOR) == NULL)) - einfo (_("%P%F: BFD backend error: BFD_RELOC_CTOR unsupported\n")); + einfo (_("%F%P: BFD backend error: BFD_RELOC_CTOR unsupported\n")); s = set_name; if (bfd_get_symbol_leading_char (abfd) != '\0') @@ -1150,9 +1266,9 @@ constructor_callback (struct bfd_link_info *info, else strcpy (s, "__DTOR_LIST__"); - h = bfd_link_hash_lookup (info->hash, set_name, TRUE, TRUE, TRUE); + h = bfd_link_hash_lookup (info->hash, set_name, true, true, true); if (h == (struct bfd_link_hash_entry *) NULL) - einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); + einfo (_("%F%P: bfd_link_hash_lookup failed: %E\n")); if (h->type == bfd_link_hash_new) { h->type = bfd_link_hash_undefined; @@ -1170,7 +1286,7 @@ constructor_callback (struct bfd_link_info *info, struct warning_callback_info { - bfd_boolean found; + bool found; const char *warning; const char *symbol; asymbol **asymbols; @@ -1179,15 +1295,15 @@ struct warning_callback_info /* Look through the relocs to see if we can find a plausible address for SYMBOL in ABFD. Return TRUE if found. Otherwise return FALSE. */ -static bfd_boolean +static bool symbol_warning (const char *warning, const char *symbol, bfd *abfd) { struct warning_callback_info cinfo; if (!bfd_generic_link_read_symbols (abfd)) - einfo (_("%B%F: could not read symbols: %E\n"), abfd); + einfo (_("%F%P: %pB: could not read symbols: %E\n"), abfd); - cinfo.found = FALSE; + cinfo.found = false; cinfo.warning = warning; cinfo.symbol = symbol; cinfo.asymbols = bfd_get_outsymbols (abfd); @@ -1212,11 +1328,11 @@ warning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED, return; if (section != NULL) - einfo ("%C: %s%s\n", abfd, section, address, _("warning: "), warning); + einfo ("%P: %C: %s%s\n", abfd, section, address, _("warning: "), warning); else if (abfd == NULL) einfo ("%P: %s%s\n", _("warning: "), warning); else if (symbol == NULL) - einfo ("%B: %s%s\n", abfd, _("warning: "), warning); + einfo ("%P: %pB: %s%s\n", abfd, _("warning: "), warning); else if (!symbol_warning (warning, symbol, abfd)) { bfd *b; @@ -1224,7 +1340,7 @@ warning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED, for (b = info->input_bfds; b; b = b->link.next) if (b != abfd && symbol_warning (warning, symbol, b)) return; - einfo ("%B: %s%s\n", abfd, _("warning: "), warning); + einfo ("%P: %pB: %s%s\n", abfd, _("warning: "), warning); } } @@ -1247,14 +1363,14 @@ warning_find_reloc (bfd *abfd, asection *sec, void *iarg) relsize = bfd_get_reloc_upper_bound (abfd, sec); if (relsize < 0) - einfo (_("%B%F: could not read relocs: %E\n"), abfd); + einfo (_("%F%P: %pB: could not read relocs: %E\n"), abfd); if (relsize == 0) return; relpp = (arelent **) xmalloc (relsize); relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols); if (relcount < 0) - einfo (_("%B%F: could not read relocs: %E\n"), abfd); + einfo (_("%F%P: %pB: could not read relocs: %E\n"), abfd); p = relpp; pend = p + relcount; @@ -1267,9 +1383,9 @@ warning_find_reloc (bfd *abfd, asection *sec, void *iarg) && strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), info->symbol) == 0) { /* We found a reloc for the symbol we are looking for. */ - einfo ("%C: %s%s\n", abfd, sec, q->address, _("warning: "), + einfo ("%P: %C: %s%s\n", abfd, sec, q->address, _("warning: "), info->warning); - info->found = TRUE; + info->found = true; break; } } @@ -1277,6 +1393,10 @@ warning_find_reloc (bfd *abfd, asection *sec, void *iarg) free (relpp); } +#if SUPPORT_ERROR_HANDLING_SCRIPT +char * error_handling_script = NULL; +#endif + /* This is called when an undefined symbol is found. */ static void @@ -1285,7 +1405,7 @@ undefined_symbol (struct bfd_link_info *info, bfd *abfd, asection *section, bfd_vma address, - bfd_boolean error) + bool error) { static char *error_name; static unsigned int error_count; @@ -1293,7 +1413,7 @@ undefined_symbol (struct bfd_link_info *info, #define MAX_ERRORS_IN_A_ROW 5 if (info->ignore_hash != NULL - && bfd_hash_lookup (info->ignore_hash, name, FALSE, FALSE) != NULL) + && bfd_hash_lookup (info->ignore_hash, name, false, false) != NULL) return; if (config.warn_once) @@ -1310,29 +1430,62 @@ undefined_symbol (struct bfd_link_info *info, else { error_count = 0; - if (error_name != NULL) - free (error_name); + free (error_name); error_name = xstrdup (name); } +#if SUPPORT_ERROR_HANDLING_SCRIPT + if (error_handling_script != NULL + && error_count < MAX_ERRORS_IN_A_ROW) + { + char * argv[4]; + const char * res; + int status, err; + + argv[0] = error_handling_script; + argv[1] = "undefined-symbol"; + argv[2] = (char *) name; + argv[3] = NULL; + + if (verbose) + einfo (_("%P: About to run error handling script '%s' with arguments: '%s' '%s'\n"), + argv[0], argv[1], argv[2]); + + res = pex_one (PEX_SEARCH, error_handling_script, argv, + N_("error handling script"), + NULL /* Send stdout to random, temp file. */, + NULL /* Write to stderr. */, + &status, &err); + if (res != NULL) + { + einfo (_("%P: Failed to run error handling script '%s', reason: "), + error_handling_script); + /* FIXME: We assume here that errrno == err. */ + perror (res); + } + /* We ignore the return status of the script and + carry on to issue the normal error message. */ + } +#endif /* SUPPORT_ERROR_HANDLING_SCRIPT */ + if (section != NULL) { if (error_count < MAX_ERRORS_IN_A_ROW) { if (error) - einfo (_("%X%C: undefined reference to `%T'\n"), + einfo (_("%X%P: %C: undefined reference to `%pT'\n"), abfd, section, address, name); else - einfo (_("%C: warning: undefined reference to `%T'\n"), + einfo (_("%P: %C: warning: undefined reference to `%pT'\n"), abfd, section, address, name); } else if (error_count == MAX_ERRORS_IN_A_ROW) { if (error) - einfo (_("%X%D: more undefined references to `%T' follow\n"), + einfo (_("%X%P: %D: more undefined references to `%pT' follow\n"), abfd, section, address, name); else - einfo (_("%D: warning: more undefined references to `%T' follow\n"), + einfo (_("%P: %D: warning: more undefined references to `%pT' follow\n"), abfd, section, address, name); } else if (error) @@ -1343,19 +1496,19 @@ undefined_symbol (struct bfd_link_info *info, if (error_count < MAX_ERRORS_IN_A_ROW) { if (error) - einfo (_("%X%B: undefined reference to `%T'\n"), + einfo (_("%X%P: %pB: undefined reference to `%pT'\n"), abfd, name); else - einfo (_("%B: warning: undefined reference to `%T'\n"), + einfo (_("%P: %pB: warning: undefined reference to `%pT'\n"), abfd, name); } else if (error_count == MAX_ERRORS_IN_A_ROW) { if (error) - einfo (_("%X%B: more undefined references to `%T' follow\n"), + einfo (_("%X%P: %pB: more undefined references to `%pT' follow\n"), abfd, name); else - einfo (_("%B: warning: more undefined references to `%T' follow\n"), + einfo (_("%P: %pB: warning: more undefined references to `%pT' follow\n"), abfd, name); } else if (error) @@ -1406,13 +1559,13 @@ reloc_overflow (struct bfd_link_info *info, case bfd_link_hash_undefined: case bfd_link_hash_undefweak: einfo (_(" relocation truncated to fit: " - "%s against undefined symbol `%T'"), + "%s against undefined symbol `%pT'"), reloc_name, entry->root.string); break; case bfd_link_hash_defined: case bfd_link_hash_defweak: einfo (_(" relocation truncated to fit: " - "%s against symbol `%T' defined in %A section in %B"), + "%s against symbol `%pT' defined in %pA section in %pB"), reloc_name, entry->root.string, entry->u.def.section, entry->u.def.section == bfd_abs_section_ptr @@ -1424,7 +1577,7 @@ reloc_overflow (struct bfd_link_info *info, } } else - einfo (_(" relocation truncated to fit: %s against `%T'"), + einfo (_(" relocation truncated to fit: %s against `%pT'"), reloc_name, name); if (addend != 0) einfo ("+%v", addend); @@ -1454,7 +1607,7 @@ unattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED, asection *section, bfd_vma address) { - einfo (_("%X%H: reloc refers to symbol `%T' which is not being output\n"), + einfo (_("%X%H: reloc refers to symbol `%pT' which is not being output\n"), abfd, section, address, name); } @@ -1465,7 +1618,7 @@ unattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED, linker script; and if plugins are active, since they need to monitor all references from non-IR files. */ -static bfd_boolean +static bool notice (struct bfd_link_info *info, struct bfd_link_hash_entry *h, struct bfd_link_hash_entry *inh ATTRIBUTE_UNUSED, @@ -1480,21 +1633,21 @@ notice (struct bfd_link_info *info, { if (command_line.cref || nocrossref_list != NULL) return handle_asneeded_cref (abfd, (enum notice_asneeded_action) value); - return TRUE; + return true; } name = h->root.string; if (info->notice_hash != NULL - && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL) + && bfd_hash_lookup (info->notice_hash, name, false, false) != NULL) { if (bfd_is_und_section (section)) - einfo ("%B: reference to %s\n", abfd, name); + einfo (_("%P: %pB: reference to %s\n"), abfd, name); else - einfo ("%B: definition of %s\n", abfd, name); + einfo (_("%P: %pB: definition of %s\n"), abfd, name); } if (command_line.cref || nocrossref_list != NULL) add_cref (name, abfd, section, value); - return TRUE; + return true; }