xref: /openbsd/gnu/usr.bin/binutils-2.17/ld/ldmain.c (revision 04e9c2fa)
13d8817e4Smiod /* Main program of GNU linker.
23d8817e4Smiod    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
33d8817e4Smiod    2002, 2003, 2004, 2005, 2006
43d8817e4Smiod    Free Software Foundation, Inc.
53d8817e4Smiod    Written by Steve Chamberlain steve@cygnus.com
63d8817e4Smiod 
73d8817e4Smiod    This file is part of GLD, the Gnu Linker.
83d8817e4Smiod 
93d8817e4Smiod    GLD is free software; you can redistribute it and/or modify
103d8817e4Smiod    it under the terms of the GNU General Public License as published by
113d8817e4Smiod    the Free Software Foundation; either version 2, or (at your option)
123d8817e4Smiod    any later version.
133d8817e4Smiod 
143d8817e4Smiod    GLD is distributed in the hope that it will be useful,
153d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
163d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
173d8817e4Smiod    GNU General Public License for more details.
183d8817e4Smiod 
193d8817e4Smiod    You should have received a copy of the GNU General Public License
203d8817e4Smiod    along with GLD; see the file COPYING.  If not, write to the Free
213d8817e4Smiod    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
223d8817e4Smiod    02110-1301, USA.  */
233d8817e4Smiod 
243d8817e4Smiod #include "bfd.h"
253d8817e4Smiod #include "sysdep.h"
263d8817e4Smiod #include <stdio.h>
273d8817e4Smiod #include "safe-ctype.h"
283d8817e4Smiod #include "libiberty.h"
293d8817e4Smiod #include "progress.h"
303d8817e4Smiod #include "bfdlink.h"
313d8817e4Smiod #include "filenames.h"
323d8817e4Smiod 
333d8817e4Smiod #include "ld.h"
343d8817e4Smiod #include "ldmain.h"
353d8817e4Smiod #include "ldmisc.h"
363d8817e4Smiod #include "ldwrite.h"
373d8817e4Smiod #include "ldexp.h"
383d8817e4Smiod #include "ldlang.h"
393d8817e4Smiod #include <ldgram.h>
403d8817e4Smiod #include "ldlex.h"
413d8817e4Smiod #include "ldfile.h"
423d8817e4Smiod #include "ldemul.h"
433d8817e4Smiod #include "ldctor.h"
443d8817e4Smiod 
453d8817e4Smiod /* Somewhere above, sys/stat.h got included.  */
463d8817e4Smiod #if !defined(S_ISDIR) && defined(S_IFDIR)
473d8817e4Smiod #define	S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
483d8817e4Smiod #endif
493d8817e4Smiod 
503d8817e4Smiod #include <string.h>
513d8817e4Smiod 
523d8817e4Smiod #ifdef HAVE_SBRK
533d8817e4Smiod #if !HAVE_DECL_SBRK
543d8817e4Smiod extern void *sbrk ();
553d8817e4Smiod #endif
563d8817e4Smiod #endif
573d8817e4Smiod 
583d8817e4Smiod #ifndef TARGET_SYSTEM_ROOT
593d8817e4Smiod #define TARGET_SYSTEM_ROOT ""
603d8817e4Smiod #endif
613d8817e4Smiod 
623d8817e4Smiod /* EXPORTS */
633d8817e4Smiod 
643d8817e4Smiod char *default_target;
653d8817e4Smiod const char *output_filename = "a.out";
663d8817e4Smiod 
673d8817e4Smiod /* Name this program was invoked by.  */
683d8817e4Smiod char *program_name;
693d8817e4Smiod 
703d8817e4Smiod /* The prefix for system library directories.  */
713d8817e4Smiod const char *ld_sysroot;
723d8817e4Smiod 
733d8817e4Smiod /* The canonical representation of ld_sysroot.  */
743d8817e4Smiod char * ld_canon_sysroot;
753d8817e4Smiod int ld_canon_sysroot_len;
763d8817e4Smiod 
773d8817e4Smiod /* The file that we're creating.  */
783d8817e4Smiod bfd *output_bfd = 0;
793d8817e4Smiod 
803d8817e4Smiod /* Set by -G argument, for MIPS ECOFF target.  */
813d8817e4Smiod int g_switch_value = 8;
823d8817e4Smiod 
833d8817e4Smiod /* Nonzero means print names of input files as processed.  */
843d8817e4Smiod bfd_boolean trace_files;
853d8817e4Smiod 
863d8817e4Smiod /* Nonzero means same, but note open failures, too.  */
873d8817e4Smiod bfd_boolean trace_file_tries;
883d8817e4Smiod 
893d8817e4Smiod /* Nonzero means version number was printed, so exit successfully
903d8817e4Smiod    instead of complaining if no input files are given.  */
913d8817e4Smiod bfd_boolean version_printed;
923d8817e4Smiod 
933d8817e4Smiod /* Nonzero means link in every member of an archive.  */
943d8817e4Smiod bfd_boolean whole_archive;
953d8817e4Smiod 
963d8817e4Smiod /* Nonzero means create DT_NEEDED entries only if a dynamic library
973d8817e4Smiod    actually satisfies some reference in a regular object.  */
983d8817e4Smiod bfd_boolean as_needed;
993d8817e4Smiod 
1003d8817e4Smiod /* Nonzero means never create DT_NEEDED entries for dynamic libraries
1013d8817e4Smiod    in DT_NEEDED tags.  */
1023d8817e4Smiod bfd_boolean add_needed = TRUE;
1033d8817e4Smiod 
1043d8817e4Smiod /* TRUE if we should demangle symbol names.  */
1053d8817e4Smiod bfd_boolean demangling;
1063d8817e4Smiod 
1073d8817e4Smiod args_type command_line;
1083d8817e4Smiod 
1093d8817e4Smiod ld_config_type config;
1103d8817e4Smiod 
1113d8817e4Smiod sort_type sort_section;
1123d8817e4Smiod 
1133d8817e4Smiod static const char *get_sysroot
1143d8817e4Smiod   (int, char **);
1153d8817e4Smiod static char *get_emulation
1163d8817e4Smiod   (int, char **);
1173d8817e4Smiod static void set_scripts_dir
1183d8817e4Smiod   (void);
1193d8817e4Smiod static bfd_boolean add_archive_element
1203d8817e4Smiod   (struct bfd_link_info *, bfd *, const char *);
1213d8817e4Smiod static bfd_boolean multiple_definition
1223d8817e4Smiod   (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma,
1233d8817e4Smiod    bfd *, asection *, bfd_vma);
1243d8817e4Smiod static bfd_boolean multiple_common
1253d8817e4Smiod   (struct bfd_link_info *, const char *, bfd *, enum bfd_link_hash_type,
1263d8817e4Smiod    bfd_vma, bfd *, enum bfd_link_hash_type, bfd_vma);
1273d8817e4Smiod static bfd_boolean add_to_set
1283d8817e4Smiod   (struct bfd_link_info *, struct bfd_link_hash_entry *,
1293d8817e4Smiod    bfd_reloc_code_real_type, bfd *, asection *, bfd_vma);
1303d8817e4Smiod static bfd_boolean constructor_callback
1313d8817e4Smiod   (struct bfd_link_info *, bfd_boolean, const char *, bfd *,
1323d8817e4Smiod    asection *, bfd_vma);
1333d8817e4Smiod static bfd_boolean warning_callback
1343d8817e4Smiod   (struct bfd_link_info *, const char *, const char *, bfd *,
1353d8817e4Smiod    asection *, bfd_vma);
1363d8817e4Smiod static void warning_find_reloc
1373d8817e4Smiod   (bfd *, asection *, void *);
1383d8817e4Smiod static bfd_boolean undefined_symbol
1393d8817e4Smiod   (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma,
1403d8817e4Smiod    bfd_boolean);
1413d8817e4Smiod static bfd_boolean reloc_overflow
1423d8817e4Smiod   (struct bfd_link_info *, struct bfd_link_hash_entry *, const char *,
1433d8817e4Smiod    const char *, bfd_vma, bfd *, asection *, bfd_vma);
1443d8817e4Smiod static bfd_boolean reloc_dangerous
1453d8817e4Smiod   (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
1463d8817e4Smiod static bfd_boolean unattached_reloc
1473d8817e4Smiod   (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
1483d8817e4Smiod static bfd_boolean notice
1493d8817e4Smiod   (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
1503d8817e4Smiod 
1513d8817e4Smiod static struct bfd_link_callbacks link_callbacks =
1523d8817e4Smiod {
1533d8817e4Smiod   add_archive_element,
1543d8817e4Smiod   multiple_definition,
1553d8817e4Smiod   multiple_common,
1563d8817e4Smiod   add_to_set,
1573d8817e4Smiod   constructor_callback,
1583d8817e4Smiod   warning_callback,
1593d8817e4Smiod   undefined_symbol,
1603d8817e4Smiod   reloc_overflow,
1613d8817e4Smiod   reloc_dangerous,
1623d8817e4Smiod   unattached_reloc,
1633d8817e4Smiod   notice,
1643d8817e4Smiod   einfo
1653d8817e4Smiod };
1663d8817e4Smiod 
1673d8817e4Smiod struct bfd_link_info link_info;
1683d8817e4Smiod 
1693d8817e4Smiod static void
remove_output(void)1703d8817e4Smiod remove_output (void)
1713d8817e4Smiod {
1723d8817e4Smiod   if (output_filename)
1733d8817e4Smiod     {
1743d8817e4Smiod       if (output_bfd)
1753d8817e4Smiod 	bfd_cache_close (output_bfd);
1763d8817e4Smiod       if (delete_output_file_on_failure)
1773d8817e4Smiod 	unlink_if_ordinary (output_filename);
1783d8817e4Smiod     }
1793d8817e4Smiod }
1803d8817e4Smiod 
1813d8817e4Smiod int
main(int argc,char ** argv)1823d8817e4Smiod main (int argc, char **argv)
1833d8817e4Smiod {
1843d8817e4Smiod   char *emulation;
1853d8817e4Smiod   long start_time = get_run_time ();
1863d8817e4Smiod 
1873d8817e4Smiod #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
1883d8817e4Smiod   setlocale (LC_MESSAGES, "");
1893d8817e4Smiod #endif
1903d8817e4Smiod #if defined (HAVE_SETLOCALE)
1913d8817e4Smiod   setlocale (LC_CTYPE, "");
1923d8817e4Smiod #endif
1933d8817e4Smiod   bindtextdomain (PACKAGE, LOCALEDIR);
1943d8817e4Smiod   textdomain (PACKAGE);
1953d8817e4Smiod 
1963d8817e4Smiod   program_name = argv[0];
1973d8817e4Smiod   xmalloc_set_program_name (program_name);
1983d8817e4Smiod 
19982505dd8Sderaadt   if (pledge ("stdio rpath wpath cpath fattr", NULL) == -1) {
20082505dd8Sderaadt     einfo (_("%X%P: Failed to pledge"));
20182505dd8Sderaadt     xexit (1);
20282505dd8Sderaadt   }
20382505dd8Sderaadt 
2043d8817e4Smiod   START_PROGRESS (program_name, 0);
2053d8817e4Smiod 
2063d8817e4Smiod   expandargv (&argc, &argv);
2073d8817e4Smiod 
2083d8817e4Smiod   bfd_init ();
2093d8817e4Smiod 
2103d8817e4Smiod   bfd_set_error_program_name (program_name);
2113d8817e4Smiod 
2123d8817e4Smiod   xatexit (remove_output);
2133d8817e4Smiod 
2143d8817e4Smiod   /* Set up the sysroot directory.  */
2153d8817e4Smiod   ld_sysroot = get_sysroot (argc, argv);
2163d8817e4Smiod   if (*ld_sysroot)
2173d8817e4Smiod     {
2183d8817e4Smiod       if (*TARGET_SYSTEM_ROOT == 0)
2193d8817e4Smiod 	{
2203d8817e4Smiod 	  einfo ("%P%F: this linker was not configured to use sysroots\n");
2213d8817e4Smiod 	  ld_sysroot = "";
2223d8817e4Smiod 	}
2233d8817e4Smiod       else
2243d8817e4Smiod 	ld_canon_sysroot = lrealpath (ld_sysroot);
2253d8817e4Smiod     }
2263d8817e4Smiod   if (ld_canon_sysroot)
2273d8817e4Smiod     ld_canon_sysroot_len = strlen (ld_canon_sysroot);
2283d8817e4Smiod   else
2293d8817e4Smiod     ld_canon_sysroot_len = -1;
2303d8817e4Smiod 
2313d8817e4Smiod   /* Set the default BFD target based on the configured target.  Doing
2323d8817e4Smiod      this permits the linker to be configured for a particular target,
2333d8817e4Smiod      and linked against a shared BFD library which was configured for
2343d8817e4Smiod      a different target.  The macro TARGET is defined by Makefile.  */
2353d8817e4Smiod   if (! bfd_set_default_target (TARGET))
2363d8817e4Smiod     {
2373d8817e4Smiod       einfo (_("%X%P: can't set BFD default target to `%s': %E\n"), TARGET);
2383d8817e4Smiod       xexit (1);
2393d8817e4Smiod     }
2403d8817e4Smiod 
2413d8817e4Smiod #if YYDEBUG
2423d8817e4Smiod   {
2433d8817e4Smiod     extern int yydebug;
2443d8817e4Smiod     yydebug = 1;
2453d8817e4Smiod   }
2463d8817e4Smiod #endif
2473d8817e4Smiod 
2483d8817e4Smiod   /* Initialize the data about options.  */
2493d8817e4Smiod   trace_files = trace_file_tries = version_printed = FALSE;
2503d8817e4Smiod   whole_archive = FALSE;
2513d8817e4Smiod   config.build_constructors = TRUE;
2523d8817e4Smiod   config.dynamic_link = FALSE;
2533d8817e4Smiod   config.has_shared = FALSE;
2543d8817e4Smiod   config.split_by_reloc = (unsigned) -1;
2553d8817e4Smiod   config.split_by_file = (bfd_size_type) -1;
2563d8817e4Smiod   config.hash_table_size = 0;
2573d8817e4Smiod   command_line.force_common_definition = FALSE;
2583d8817e4Smiod   command_line.inhibit_common_definition = FALSE;
2593d8817e4Smiod   command_line.interpreter = NULL;
2603d8817e4Smiod   command_line.rpath = NULL;
2613d8817e4Smiod   command_line.warn_mismatch = TRUE;
2623d8817e4Smiod   command_line.check_section_addresses = TRUE;
2633d8817e4Smiod   command_line.accept_unknown_input_arch = FALSE;
2643d8817e4Smiod 
2653d8817e4Smiod   sort_section = none;
2663d8817e4Smiod 
2673d8817e4Smiod   /* We initialize DEMANGLING based on the environment variable
2683d8817e4Smiod      COLLECT_NO_DEMANGLE.  The gcc collect2 program will demangle the
2693d8817e4Smiod      output of the linker, unless COLLECT_NO_DEMANGLE is set in the
2703d8817e4Smiod      environment.  Acting the same way here lets us provide the same
2713d8817e4Smiod      interface by default.  */
2723d8817e4Smiod   demangling = getenv ("COLLECT_NO_DEMANGLE") == NULL;
2733d8817e4Smiod 
2743d8817e4Smiod   link_info.relocatable = FALSE;
2753d8817e4Smiod   link_info.emitrelocations = FALSE;
2763d8817e4Smiod   link_info.task_link = FALSE;
2773d8817e4Smiod   link_info.shared = FALSE;
2789622a78fSpascal #ifdef PIE_DEFAULT
2799622a78fSpascal   link_info.pie = TRUE;
2809622a78fSpascal #else
2813d8817e4Smiod   link_info.pie = FALSE;
2829622a78fSpascal #endif
2833d8817e4Smiod   link_info.executable = FALSE;
2843d8817e4Smiod   link_info.symbolic = FALSE;
2853d8817e4Smiod   link_info.export_dynamic = FALSE;
2863d8817e4Smiod   link_info.static_link = FALSE;
2873d8817e4Smiod   link_info.traditional_format = FALSE;
2883d8817e4Smiod   link_info.optimize = FALSE;
2893d8817e4Smiod   link_info.unresolved_syms_in_objects = RM_NOT_YET_SET;
2903d8817e4Smiod   link_info.unresolved_syms_in_shared_libs = RM_NOT_YET_SET;
2913d8817e4Smiod   link_info.allow_multiple_definition = FALSE;
2923d8817e4Smiod   link_info.allow_undefined_version = TRUE;
29389e0a384Sguenther   link_info.allow_textrel = FALSE;
2943d8817e4Smiod   link_info.create_default_symver = FALSE;
2953d8817e4Smiod   link_info.default_imported_symver = FALSE;
2963d8817e4Smiod   link_info.keep_memory = TRUE;
2973d8817e4Smiod   link_info.notice_all = FALSE;
2983d8817e4Smiod   link_info.nocopyreloc = FALSE;
29983fc6d9dSguenther   link_info.new_dtags = TRUE;	/* to match lld */
3003d8817e4Smiod   link_info.combreloc = TRUE;
3013d8817e4Smiod   link_info.eh_frame_hdr = FALSE;
3027310f5ffSguenther   link_info.relro = TRUE;
3033d8817e4Smiod   link_info.strip_discarded = TRUE;
3043d8817e4Smiod   link_info.strip = strip_none;
3053d8817e4Smiod   link_info.discard = discard_sec_merge;
3063d8817e4Smiod   link_info.common_skip_ar_aymbols = bfd_link_common_skip_none;
3073d8817e4Smiod   link_info.callbacks = &link_callbacks;
3083d8817e4Smiod   link_info.hash = NULL;
3093d8817e4Smiod   link_info.keep_hash = NULL;
3103d8817e4Smiod   link_info.notice_hash = NULL;
3113d8817e4Smiod   link_info.wrap_hash = NULL;
3123d8817e4Smiod   link_info.input_bfds = NULL;
3133d8817e4Smiod   link_info.create_object_symbols_section = NULL;
3143d8817e4Smiod   link_info.gc_sym_list = NULL;
3153d8817e4Smiod   link_info.base_file = NULL;
316fa04e3d1Sguenther   link_info.emit_hash = TRUE;
317fa04e3d1Sguenther #ifndef __mips64__
318fa04e3d1Sguenther   link_info.emit_gnu_hash = TRUE;
319fa04e3d1Sguenther #else
320fa04e3d1Sguenther   link_info.emit_gnu_hash = FALSE;
321fa04e3d1Sguenther #endif
322*04e9c2faSderaadt #if defined(__amd64__) || defined(__hppa__) || defined(__mips64__)
32384b753dfSderaadt   link_info.execute_only = TRUE;
32484b753dfSderaadt #else
32584b753dfSderaadt   link_info.execute_only = FALSE;
32684b753dfSderaadt #endif
3273d8817e4Smiod   /* SVR4 linkers seem to set DT_INIT and DT_FINI based on magic _init
3283d8817e4Smiod      and _fini symbols.  We are compatible.  */
3293d8817e4Smiod   link_info.init_function = "_init";
3303d8817e4Smiod   link_info.fini_function = "_fini";
3313d8817e4Smiod   link_info.pei386_auto_import = -1;
3323d8817e4Smiod   link_info.pei386_runtime_pseudo_reloc = FALSE;
3333d8817e4Smiod   link_info.spare_dynamic_tags = 5;
3343d8817e4Smiod   link_info.flags = 0;
3353d8817e4Smiod   link_info.flags_1 = 0;
3363d8817e4Smiod   link_info.relax_pass = 1;
3373d8817e4Smiod   link_info.warn_shared_textrel = FALSE;
3383d8817e4Smiod   link_info.gc_sections = FALSE;
339b8417449Sstefan   link_info.reduce_memory_overheads = FALSE;
3403d8817e4Smiod 
3413d8817e4Smiod   ldfile_add_arch ("");
3423d8817e4Smiod 
3433d8817e4Smiod   config.make_executable = TRUE;
3443d8817e4Smiod   force_make_executable = FALSE;
3453d8817e4Smiod   config.magic_demand_paged = TRUE;
3463d8817e4Smiod   config.text_read_only = TRUE;
347d2386abeSmiod   config.data_bss_contig = FALSE;
3483d8817e4Smiod 
3493d8817e4Smiod   emulation = get_emulation (argc, argv);
3503d8817e4Smiod   ldemul_choose_mode (emulation);
3513d8817e4Smiod   default_target = ldemul_choose_target (argc, argv);
3523d8817e4Smiod   lang_init ();
3533d8817e4Smiod   ldemul_before_parse ();
3543d8817e4Smiod   lang_has_input_file = FALSE;
3553d8817e4Smiod   parse_args (argc, argv);
3563d8817e4Smiod 
3573d8817e4Smiod   if (config.hash_table_size != 0)
3583d8817e4Smiod     bfd_hash_set_default_size (config.hash_table_size);
3593d8817e4Smiod 
3603d8817e4Smiod   ldemul_set_symbols ();
3613d8817e4Smiod 
3629622a78fSpascal   if (! link_info.shared && link_info.pie)
3639622a78fSpascal     {
3649622a78fSpascal       if (link_info.relocatable)
3659622a78fSpascal         link_info.pie = FALSE;
3669622a78fSpascal       else
3679622a78fSpascal         link_info.shared = TRUE;
3689622a78fSpascal     }
3699622a78fSpascal 
3703d8817e4Smiod   if (link_info.relocatable)
3713d8817e4Smiod     {
3723d8817e4Smiod       if (link_info.gc_sections)
3733d8817e4Smiod 	einfo ("%P%F: --gc-sections and -r may not be used together\n");
3743d8817e4Smiod       else if (command_line.relax)
3753d8817e4Smiod 	einfo (_("%P%F: --relax and -r may not be used together\n"));
3763d8817e4Smiod       if (link_info.shared)
3773d8817e4Smiod 	einfo (_("%P%F: -r and -shared may not be used together\n"));
3783d8817e4Smiod     }
3793d8817e4Smiod 
3803d8817e4Smiod   if (! link_info.shared)
3813d8817e4Smiod     {
3823d8817e4Smiod       if (command_line.filter_shlib)
3833d8817e4Smiod 	einfo (_("%P%F: -F may not be used without -shared\n"));
3843d8817e4Smiod       if (command_line.auxiliary_filters)
3853d8817e4Smiod 	einfo (_("%P%F: -f may not be used without -shared\n"));
3863d8817e4Smiod     }
3873d8817e4Smiod 
3883d8817e4Smiod   if (! link_info.shared || link_info.pie)
3893d8817e4Smiod     link_info.executable = TRUE;
3903d8817e4Smiod 
391ebca08eeSkettenis   if (! config.dynamic_link && link_info.pie)
392ebca08eeSkettenis     link_info.static_link = TRUE;
393ebca08eeSkettenis 
3943d8817e4Smiod   /* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols).  I
3953d8817e4Smiod      don't see how else this can be handled, since in this case we
3963d8817e4Smiod      must preserve all externally visible symbols.  */
3973d8817e4Smiod   if (link_info.relocatable && link_info.strip == strip_all)
3983d8817e4Smiod     {
3993d8817e4Smiod       link_info.strip = strip_debugger;
4003d8817e4Smiod       if (link_info.discard == discard_sec_merge)
4013d8817e4Smiod 	link_info.discard = discard_all;
4023d8817e4Smiod     }
4033d8817e4Smiod 
4043d8817e4Smiod   /* This essentially adds another -L directory so this must be done after
4053d8817e4Smiod      the -L's in argv have been processed.  */
4063d8817e4Smiod   set_scripts_dir ();
4073d8817e4Smiod 
4083d8817e4Smiod   /* If we have not already opened and parsed a linker script
4093d8817e4Smiod      read the emulation's appropriate default script.  */
4103d8817e4Smiod   if (saved_script_handle == NULL)
4113d8817e4Smiod     {
4123d8817e4Smiod       int isfile;
4133d8817e4Smiod       char *s = ldemul_get_script (&isfile);
4143d8817e4Smiod 
4153d8817e4Smiod       if (isfile)
4163d8817e4Smiod 	ldfile_open_command_file (s);
4173d8817e4Smiod       else
4183d8817e4Smiod 	{
4193d8817e4Smiod 	  lex_string = s;
4203d8817e4Smiod 	  lex_redirect (s);
4213d8817e4Smiod 	}
4223d8817e4Smiod       parser_input = input_script;
4233d8817e4Smiod       yyparse ();
4243d8817e4Smiod       lex_string = NULL;
4253d8817e4Smiod     }
4263d8817e4Smiod 
4273d8817e4Smiod   if (trace_file_tries)
4283d8817e4Smiod     {
4293d8817e4Smiod       if (saved_script_handle)
4303d8817e4Smiod 	info_msg (_("using external linker script:"));
4313d8817e4Smiod       else
4323d8817e4Smiod 	info_msg (_("using internal linker script:"));
4333d8817e4Smiod       info_msg ("\n==================================================\n");
4343d8817e4Smiod 
4353d8817e4Smiod       if (saved_script_handle)
4363d8817e4Smiod 	{
4373d8817e4Smiod 	  static const int ld_bufsz = 8193;
4383d8817e4Smiod 	  size_t n;
4393d8817e4Smiod 	  char *buf = xmalloc (ld_bufsz);
4403d8817e4Smiod 
4413d8817e4Smiod 	  rewind (saved_script_handle);
4423d8817e4Smiod 	  while ((n = fread (buf, 1, ld_bufsz - 1, saved_script_handle)) > 0)
4433d8817e4Smiod 	    {
4443d8817e4Smiod 	      buf[n] = 0;
4453d8817e4Smiod 	      info_msg (buf);
4463d8817e4Smiod 	    }
4473d8817e4Smiod 	  rewind (saved_script_handle);
4483d8817e4Smiod 	  free (buf);
4493d8817e4Smiod 	}
4503d8817e4Smiod       else
4513d8817e4Smiod 	{
4523d8817e4Smiod 	  int isfile;
4533d8817e4Smiod 
4543d8817e4Smiod 	  info_msg (ldemul_get_script (&isfile));
4553d8817e4Smiod 	}
4563d8817e4Smiod 
4573d8817e4Smiod       info_msg ("\n==================================================\n");
4583d8817e4Smiod     }
4593d8817e4Smiod 
4603d8817e4Smiod   lang_final ();
4613d8817e4Smiod 
4623d8817e4Smiod   if (!lang_has_input_file)
4633d8817e4Smiod     {
4643d8817e4Smiod       if (version_printed)
4653d8817e4Smiod 	xexit (0);
4663d8817e4Smiod       einfo (_("%P%F: no input files\n"));
4673d8817e4Smiod     }
4683d8817e4Smiod 
4693d8817e4Smiod   if (trace_files)
4703d8817e4Smiod     info_msg (_("%P: mode %s\n"), emulation);
4713d8817e4Smiod 
4723d8817e4Smiod   ldemul_after_parse ();
4733d8817e4Smiod 
4743d8817e4Smiod   if (config.map_filename)
4753d8817e4Smiod     {
4763d8817e4Smiod       if (strcmp (config.map_filename, "-") == 0)
4773d8817e4Smiod 	{
4783d8817e4Smiod 	  config.map_file = stdout;
4793d8817e4Smiod 	}
4803d8817e4Smiod       else
4813d8817e4Smiod 	{
4823d8817e4Smiod 	  config.map_file = fopen (config.map_filename, FOPEN_WT);
4833d8817e4Smiod 	  if (config.map_file == (FILE *) NULL)
4843d8817e4Smiod 	    {
4853d8817e4Smiod 	      bfd_set_error (bfd_error_system_call);
4863d8817e4Smiod 	      einfo (_("%P%F: cannot open map file %s: %E\n"),
4873d8817e4Smiod 		     config.map_filename);
4883d8817e4Smiod 	    }
4893d8817e4Smiod 	}
4903d8817e4Smiod     }
4913d8817e4Smiod 
4923d8817e4Smiod   lang_process ();
4933d8817e4Smiod 
4943d8817e4Smiod   /* Print error messages for any missing symbols, for any warning
4953d8817e4Smiod      symbols, and possibly multiple definitions.  */
4963d8817e4Smiod   if (link_info.relocatable)
4973d8817e4Smiod     output_bfd->flags &= ~EXEC_P;
4983d8817e4Smiod   else
4993d8817e4Smiod     output_bfd->flags |= EXEC_P;
5003d8817e4Smiod 
5013d8817e4Smiod   ldwrite ();
5023d8817e4Smiod 
5033d8817e4Smiod   if (config.map_file != NULL)
5043d8817e4Smiod     lang_map ();
5053d8817e4Smiod   if (command_line.cref)
5063d8817e4Smiod     output_cref (config.map_file != NULL ? config.map_file : stdout);
5073d8817e4Smiod   if (nocrossref_list != NULL)
5083d8817e4Smiod     check_nocrossrefs ();
5093d8817e4Smiod 
5103d8817e4Smiod   lang_finish ();
5113d8817e4Smiod 
5123d8817e4Smiod   /* Even if we're producing relocatable output, some non-fatal errors should
5133d8817e4Smiod      be reported in the exit status.  (What non-fatal errors, if any, do we
5143d8817e4Smiod      want to ignore for relocatable output?)  */
5153d8817e4Smiod   if (!config.make_executable && !force_make_executable)
5163d8817e4Smiod     {
5173d8817e4Smiod       if (trace_files)
5183d8817e4Smiod 	einfo (_("%P: link errors found, deleting executable `%s'\n"),
5193d8817e4Smiod 	       output_filename);
5203d8817e4Smiod 
5213d8817e4Smiod       /* The file will be removed by remove_output.  */
5223d8817e4Smiod       xexit (1);
5233d8817e4Smiod     }
5243d8817e4Smiod   else
5253d8817e4Smiod     {
5263d8817e4Smiod       if (! bfd_close (output_bfd))
5273d8817e4Smiod 	einfo (_("%F%B: final close failed: %E\n"), output_bfd);
5283d8817e4Smiod 
5293d8817e4Smiod       /* If the --force-exe-suffix is enabled, and we're making an
5303d8817e4Smiod 	 executable file and it doesn't end in .exe, copy it to one
5313d8817e4Smiod 	 which does.  */
5323d8817e4Smiod       if (! link_info.relocatable && command_line.force_exe_suffix)
5333d8817e4Smiod 	{
5343d8817e4Smiod 	  int len = strlen (output_filename);
5353d8817e4Smiod 
5363d8817e4Smiod 	  if (len < 4
5373d8817e4Smiod 	      || (strcasecmp (output_filename + len - 4, ".exe") != 0
5383d8817e4Smiod 		  && strcasecmp (output_filename + len - 4, ".dll") != 0))
5393d8817e4Smiod 	    {
5403d8817e4Smiod 	      FILE *src;
5413d8817e4Smiod 	      FILE *dst;
5423d8817e4Smiod 	      const int bsize = 4096;
5433d8817e4Smiod 	      char *buf = xmalloc (bsize);
5443d8817e4Smiod 	      int l;
5453d8817e4Smiod 	      char *dst_name = xmalloc (len + 5);
5463d8817e4Smiod 
5473d8817e4Smiod 	      strcpy (dst_name, output_filename);
5483d8817e4Smiod 	      strcat (dst_name, ".exe");
5493d8817e4Smiod 	      src = fopen (output_filename, FOPEN_RB);
5503d8817e4Smiod 	      dst = fopen (dst_name, FOPEN_WB);
5513d8817e4Smiod 
5523d8817e4Smiod 	      if (!src)
5533d8817e4Smiod 		einfo (_("%X%P: unable to open for source of copy `%s'\n"),
5543d8817e4Smiod 		       output_filename);
5553d8817e4Smiod 	      if (!dst)
5563d8817e4Smiod 		einfo (_("%X%P: unable to open for destination of copy `%s'\n"),
5573d8817e4Smiod 		       dst_name);
5583d8817e4Smiod 	      while ((l = fread (buf, 1, bsize, src)) > 0)
5593d8817e4Smiod 		{
5603d8817e4Smiod 		  int done = fwrite (buf, 1, l, dst);
5613d8817e4Smiod 
5623d8817e4Smiod 		  if (done != l)
5633d8817e4Smiod 		    einfo (_("%P: Error writing file `%s'\n"), dst_name);
5643d8817e4Smiod 		}
5653d8817e4Smiod 
5663d8817e4Smiod 	      fclose (src);
5673d8817e4Smiod 	      if (fclose (dst) == EOF)
5683d8817e4Smiod 		einfo (_("%P: Error closing file `%s'\n"), dst_name);
5693d8817e4Smiod 	      free (dst_name);
5703d8817e4Smiod 	      free (buf);
5713d8817e4Smiod 	    }
5723d8817e4Smiod 	}
5733d8817e4Smiod     }
5743d8817e4Smiod 
5753d8817e4Smiod   END_PROGRESS (program_name);
5763d8817e4Smiod 
5773d8817e4Smiod   if (config.stats)
5783d8817e4Smiod     {
5793d8817e4Smiod #ifdef HAVE_SBRK
5803d8817e4Smiod       char *lim = sbrk (0);
5813d8817e4Smiod #endif
5823d8817e4Smiod       long run_time = get_run_time () - start_time;
5833d8817e4Smiod 
5843d8817e4Smiod       fprintf (stderr, _("%s: total time in link: %ld.%06ld\n"),
5853d8817e4Smiod 	       program_name, run_time / 1000000, run_time % 1000000);
5863d8817e4Smiod #ifdef HAVE_SBRK
5873d8817e4Smiod       fprintf (stderr, _("%s: data size %ld\n"), program_name,
5883d8817e4Smiod 	       (long) (lim - (char *) &environ));
5893d8817e4Smiod #endif
5903d8817e4Smiod     }
5913d8817e4Smiod 
5923d8817e4Smiod   /* Prevent remove_output from doing anything, after a successful link.  */
5933d8817e4Smiod   output_filename = NULL;
5943d8817e4Smiod 
5953d8817e4Smiod   xexit (0);
5963d8817e4Smiod   return 0;
5973d8817e4Smiod }
5983d8817e4Smiod 
5993d8817e4Smiod /* If the configured sysroot is relocatable, try relocating it based on
6003d8817e4Smiod    default prefix FROM.  Return the relocated directory if it exists,
6013d8817e4Smiod    otherwise return null.  */
6023d8817e4Smiod 
6033d8817e4Smiod static char *
get_relative_sysroot(const char * from ATTRIBUTE_UNUSED)6043d8817e4Smiod get_relative_sysroot (const char *from ATTRIBUTE_UNUSED)
6053d8817e4Smiod {
6063d8817e4Smiod #ifdef TARGET_SYSTEM_ROOT_RELOCATABLE
6073d8817e4Smiod   char *path;
6083d8817e4Smiod   struct stat s;
6093d8817e4Smiod 
6103d8817e4Smiod   path = make_relative_prefix (program_name, from, TARGET_SYSTEM_ROOT);
6113d8817e4Smiod   if (path)
6123d8817e4Smiod     {
6133d8817e4Smiod       if (stat (path, &s) == 0 && S_ISDIR (s.st_mode))
6143d8817e4Smiod 	return path;
6153d8817e4Smiod       free (path);
6163d8817e4Smiod     }
6173d8817e4Smiod #endif
6183d8817e4Smiod   return 0;
6193d8817e4Smiod }
6203d8817e4Smiod 
6213d8817e4Smiod /* Return the sysroot directory.  Return "" if no sysroot is being used.  */
6223d8817e4Smiod 
6233d8817e4Smiod static const char *
get_sysroot(int argc,char ** argv)6243d8817e4Smiod get_sysroot (int argc, char **argv)
6253d8817e4Smiod {
6263d8817e4Smiod   int i;
6273d8817e4Smiod   const char *path;
6283d8817e4Smiod 
6293d8817e4Smiod   for (i = 1; i < argc; i++)
6303d8817e4Smiod     if (strncmp (argv[i], "--sysroot=", strlen ("--sysroot=")) == 0)
6313d8817e4Smiod       return argv[i] + strlen ("--sysroot=");
6323d8817e4Smiod 
6333d8817e4Smiod   path = get_relative_sysroot (BINDIR);
6343d8817e4Smiod   if (path)
6353d8817e4Smiod     return path;
6363d8817e4Smiod 
6373d8817e4Smiod   path = get_relative_sysroot (TOOLBINDIR);
6383d8817e4Smiod   if (path)
6393d8817e4Smiod     return path;
6403d8817e4Smiod 
6413d8817e4Smiod   return TARGET_SYSTEM_ROOT;
6423d8817e4Smiod }
6433d8817e4Smiod 
6443d8817e4Smiod /* We need to find any explicitly given emulation in order to initialize the
6453d8817e4Smiod    state that's needed by the lex&yacc argument parser (parse_args).  */
6463d8817e4Smiod 
6473d8817e4Smiod static char *
get_emulation(int argc,char ** argv)6483d8817e4Smiod get_emulation (int argc, char **argv)
6493d8817e4Smiod {
6503d8817e4Smiod   char *emulation;
6513d8817e4Smiod   int i;
6523d8817e4Smiod 
6533d8817e4Smiod   emulation = getenv (EMULATION_ENVIRON);
6543d8817e4Smiod   if (emulation == NULL)
6553d8817e4Smiod     emulation = DEFAULT_EMULATION;
6563d8817e4Smiod 
6573d8817e4Smiod   for (i = 1; i < argc; i++)
6583d8817e4Smiod     {
6593d8817e4Smiod       if (!strncmp (argv[i], "-m", 2))
6603d8817e4Smiod 	{
6613d8817e4Smiod 	  if (argv[i][2] == '\0')
6623d8817e4Smiod 	    {
6633d8817e4Smiod 	      /* -m EMUL */
6643d8817e4Smiod 	      if (i < argc - 1)
6653d8817e4Smiod 		{
6663d8817e4Smiod 		  emulation = argv[i + 1];
6673d8817e4Smiod 		  i++;
6683d8817e4Smiod 		}
6693d8817e4Smiod 	      else
6703d8817e4Smiod 		einfo (_("%P%F: missing argument to -m\n"));
6713d8817e4Smiod 	    }
6723d8817e4Smiod 	  else if (strcmp (argv[i], "-mips1") == 0
6733d8817e4Smiod 		   || strcmp (argv[i], "-mips2") == 0
6743d8817e4Smiod 		   || strcmp (argv[i], "-mips3") == 0
6753d8817e4Smiod 		   || strcmp (argv[i], "-mips4") == 0
6763d8817e4Smiod 		   || strcmp (argv[i], "-mips5") == 0
6773d8817e4Smiod 		   || strcmp (argv[i], "-mips32") == 0
6783d8817e4Smiod 		   || strcmp (argv[i], "-mips32r2") == 0
6793d8817e4Smiod 		   || strcmp (argv[i], "-mips64") == 0
6803d8817e4Smiod 		   || strcmp (argv[i], "-mips64r2") == 0)
6813d8817e4Smiod 	    {
6823d8817e4Smiod 	      /* FIXME: The arguments -mips1, -mips2, -mips3, etc. are
6833d8817e4Smiod 		 passed to the linker by some MIPS compilers.  They
6843d8817e4Smiod 		 generally tell the linker to use a slightly different
6853d8817e4Smiod 		 library path.  Perhaps someday these should be
6863d8817e4Smiod 		 implemented as emulations; until then, we just ignore
6873d8817e4Smiod 		 the arguments and hope that nobody ever creates
6883d8817e4Smiod 		 emulations named ips1, ips2 or ips3.  */
6893d8817e4Smiod 	    }
6903d8817e4Smiod 	  else if (strcmp (argv[i], "-m486") == 0)
6913d8817e4Smiod 	    {
6923d8817e4Smiod 	      /* FIXME: The argument -m486 is passed to the linker on
6933d8817e4Smiod 		 some Linux systems.  Hope that nobody creates an
6943d8817e4Smiod 		 emulation named 486.  */
6953d8817e4Smiod 	    }
6963d8817e4Smiod 	  else
6973d8817e4Smiod 	    {
6983d8817e4Smiod 	      /* -mEMUL */
6993d8817e4Smiod 	      emulation = &argv[i][2];
7003d8817e4Smiod 	    }
7013d8817e4Smiod 	}
7023d8817e4Smiod     }
7033d8817e4Smiod 
7043d8817e4Smiod   return emulation;
7053d8817e4Smiod }
7063d8817e4Smiod 
7073d8817e4Smiod /* If directory DIR contains an "ldscripts" subdirectory,
7083d8817e4Smiod    add DIR to the library search path and return TRUE,
7093d8817e4Smiod    else return FALSE.  */
7103d8817e4Smiod 
7113d8817e4Smiod static bfd_boolean
check_for_scripts_dir(char * dir)7123d8817e4Smiod check_for_scripts_dir (char *dir)
7133d8817e4Smiod {
7143d8817e4Smiod   size_t dirlen;
7153d8817e4Smiod   char *buf;
7163d8817e4Smiod   struct stat s;
7173d8817e4Smiod   bfd_boolean res;
7183d8817e4Smiod 
7193d8817e4Smiod   dirlen = strlen (dir);
7203d8817e4Smiod   /* sizeof counts the terminating NUL.  */
7213d8817e4Smiod   buf = xmalloc (dirlen + sizeof ("/ldscripts"));
7223d8817e4Smiod   sprintf (buf, "%s/ldscripts", dir);
7233d8817e4Smiod 
7243d8817e4Smiod   res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode);
7253d8817e4Smiod   free (buf);
7263d8817e4Smiod   if (res)
7273d8817e4Smiod     ldfile_add_library_path (dir, FALSE);
7283d8817e4Smiod   return res;
7293d8817e4Smiod }
7303d8817e4Smiod 
7313d8817e4Smiod /* Set the default directory for finding script files.
7323d8817e4Smiod    Libraries will be searched for here too, but that's ok.
7333d8817e4Smiod    We look for the "ldscripts" directory in:
7343d8817e4Smiod 
7353d8817e4Smiod    SCRIPTDIR (passed from Makefile)
7363d8817e4Smiod 	     (adjusted according to the current location of the binary)
7373d8817e4Smiod    SCRIPTDIR (passed from Makefile)
7383d8817e4Smiod    the dir where this program is (for using it from the build tree)
7393d8817e4Smiod    the dir where this program is/../lib
7403d8817e4Smiod 	     (for installing the tool suite elsewhere).  */
7413d8817e4Smiod 
7423d8817e4Smiod static void
set_scripts_dir(void)7433d8817e4Smiod set_scripts_dir (void)
7443d8817e4Smiod {
7453d8817e4Smiod   char *end, *dir;
7463d8817e4Smiod   size_t dirlen;
7473d8817e4Smiod   bfd_boolean found;
7483d8817e4Smiod 
7493d8817e4Smiod   dir = make_relative_prefix (program_name, BINDIR, SCRIPTDIR);
7503d8817e4Smiod   if (dir)
7513d8817e4Smiod     {
7523d8817e4Smiod       found = check_for_scripts_dir (dir);
7533d8817e4Smiod       free (dir);
7543d8817e4Smiod       if (found)
7553d8817e4Smiod 	return;
7563d8817e4Smiod     }
7573d8817e4Smiod 
7583d8817e4Smiod   dir = make_relative_prefix (program_name, TOOLBINDIR, SCRIPTDIR);
7593d8817e4Smiod   if (dir)
7603d8817e4Smiod     {
7613d8817e4Smiod       found = check_for_scripts_dir (dir);
7623d8817e4Smiod       free (dir);
7633d8817e4Smiod       if (found)
7643d8817e4Smiod 	return;
7653d8817e4Smiod     }
7663d8817e4Smiod 
7673d8817e4Smiod   if (check_for_scripts_dir (SCRIPTDIR))
7683d8817e4Smiod     /* We've been installed normally.  */
7693d8817e4Smiod     return;
7703d8817e4Smiod 
7713d8817e4Smiod   /* Look for "ldscripts" in the dir where our binary is.  */
7723d8817e4Smiod   end = strrchr (program_name, '/');
7733d8817e4Smiod #ifdef HAVE_DOS_BASED_FILE_SYSTEM
7743d8817e4Smiod   {
7753d8817e4Smiod     /* We could have \foo\bar, or /foo\bar.  */
7763d8817e4Smiod     char *bslash = strrchr (program_name, '\\');
7773d8817e4Smiod 
7783d8817e4Smiod     if (end == NULL || (bslash != NULL && bslash > end))
7793d8817e4Smiod       end = bslash;
7803d8817e4Smiod   }
7813d8817e4Smiod #endif
7823d8817e4Smiod 
7833d8817e4Smiod   if (end == NULL)
7843d8817e4Smiod     /* Don't look for ldscripts in the current directory.  There is
7853d8817e4Smiod        too much potential for confusion.  */
7863d8817e4Smiod     return;
7873d8817e4Smiod 
7883d8817e4Smiod   dirlen = end - program_name;
7893d8817e4Smiod   /* Make a copy of program_name in dir.
7903d8817e4Smiod      Leave room for later "/../lib".  */
7913d8817e4Smiod   dir = xmalloc (dirlen + 8);
7923d8817e4Smiod   strncpy (dir, program_name, dirlen);
7933d8817e4Smiod   dir[dirlen] = '\0';
7943d8817e4Smiod 
7953d8817e4Smiod   if (check_for_scripts_dir (dir))
7963d8817e4Smiod     {
7973d8817e4Smiod       free (dir);
7983d8817e4Smiod       return;
7993d8817e4Smiod     }
8003d8817e4Smiod 
8013d8817e4Smiod   /* Look for "ldscripts" in <the dir where our binary is>/../lib.  */
8023d8817e4Smiod   strcpy (dir + dirlen, "/../lib");
8033d8817e4Smiod   check_for_scripts_dir (dir);
8043d8817e4Smiod   free (dir);
8053d8817e4Smiod }
8063d8817e4Smiod 
8073d8817e4Smiod void
add_ysym(const char * name)8083d8817e4Smiod add_ysym (const char *name)
8093d8817e4Smiod {
8103d8817e4Smiod   if (link_info.notice_hash == NULL)
8113d8817e4Smiod     {
8123d8817e4Smiod       link_info.notice_hash = xmalloc (sizeof (struct bfd_hash_table));
8133d8817e4Smiod       if (!bfd_hash_table_init_n (link_info.notice_hash,
8143d8817e4Smiod 				  bfd_hash_newfunc,
8153d8817e4Smiod 				  sizeof (struct bfd_hash_entry),
8163d8817e4Smiod 				  61))
8173d8817e4Smiod 	einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
8183d8817e4Smiod     }
8193d8817e4Smiod 
8203d8817e4Smiod   if (bfd_hash_lookup (link_info.notice_hash, name, TRUE, TRUE) == NULL)
8213d8817e4Smiod     einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));
8223d8817e4Smiod }
8233d8817e4Smiod 
8243d8817e4Smiod /* Record a symbol to be wrapped, from the --wrap option.  */
8253d8817e4Smiod 
8263d8817e4Smiod void
add_wrap(const char * name)8273d8817e4Smiod add_wrap (const char *name)
8283d8817e4Smiod {
8293d8817e4Smiod   if (link_info.wrap_hash == NULL)
8303d8817e4Smiod     {
8313d8817e4Smiod       link_info.wrap_hash = xmalloc (sizeof (struct bfd_hash_table));
8323d8817e4Smiod       if (!bfd_hash_table_init_n (link_info.wrap_hash,
8333d8817e4Smiod 				  bfd_hash_newfunc,
8343d8817e4Smiod 				  sizeof (struct bfd_hash_entry),
8353d8817e4Smiod 				  61))
8363d8817e4Smiod 	einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
8373d8817e4Smiod     }
8383d8817e4Smiod 
8393d8817e4Smiod   if (bfd_hash_lookup (link_info.wrap_hash, name, TRUE, TRUE) == NULL)
8403d8817e4Smiod     einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));
8413d8817e4Smiod }
8423d8817e4Smiod 
8433d8817e4Smiod /* Handle the -retain-symbols-file option.  */
8443d8817e4Smiod 
8453d8817e4Smiod void
add_keepsyms_file(const char * filename)8463d8817e4Smiod add_keepsyms_file (const char *filename)
8473d8817e4Smiod {
8483d8817e4Smiod   FILE *file;
8493d8817e4Smiod   char *buf;
8503d8817e4Smiod   size_t bufsize;
8513d8817e4Smiod   int c;
8523d8817e4Smiod 
8533d8817e4Smiod   if (link_info.strip == strip_some)
8543d8817e4Smiod     einfo (_("%X%P: error: duplicate retain-symbols-file\n"));
8553d8817e4Smiod 
8563d8817e4Smiod   file = fopen (filename, "r");
8573d8817e4Smiod   if (file == NULL)
8583d8817e4Smiod     {
8593d8817e4Smiod       bfd_set_error (bfd_error_system_call);
8603d8817e4Smiod       einfo ("%X%P: %s: %E\n", filename);
8613d8817e4Smiod       return;
8623d8817e4Smiod     }
8633d8817e4Smiod 
8643d8817e4Smiod   link_info.keep_hash = xmalloc (sizeof (struct bfd_hash_table));
8653d8817e4Smiod   if (!bfd_hash_table_init (link_info.keep_hash, bfd_hash_newfunc,
8663d8817e4Smiod 			    sizeof (struct bfd_hash_entry)))
8673d8817e4Smiod     einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
8683d8817e4Smiod 
8693d8817e4Smiod   bufsize = 100;
8703d8817e4Smiod   buf = xmalloc (bufsize);
8713d8817e4Smiod 
8723d8817e4Smiod   c = getc (file);
8733d8817e4Smiod   while (c != EOF)
8743d8817e4Smiod     {
8753d8817e4Smiod       while (ISSPACE (c))
8763d8817e4Smiod 	c = getc (file);
8773d8817e4Smiod 
8783d8817e4Smiod       if (c != EOF)
8793d8817e4Smiod 	{
8803d8817e4Smiod 	  size_t len = 0;
8813d8817e4Smiod 
8823d8817e4Smiod 	  while (! ISSPACE (c) && c != EOF)
8833d8817e4Smiod 	    {
8843d8817e4Smiod 	      buf[len] = c;
8853d8817e4Smiod 	      ++len;
8863d8817e4Smiod 	      if (len >= bufsize)
8873d8817e4Smiod 		{
8883d8817e4Smiod 		  bufsize *= 2;
8893d8817e4Smiod 		  buf = xrealloc (buf, bufsize);
8903d8817e4Smiod 		}
8913d8817e4Smiod 	      c = getc (file);
8923d8817e4Smiod 	    }
8933d8817e4Smiod 
8943d8817e4Smiod 	  buf[len] = '\0';
8953d8817e4Smiod 
8963d8817e4Smiod 	  if (bfd_hash_lookup (link_info.keep_hash, buf, TRUE, TRUE) == NULL)
8973d8817e4Smiod 	    einfo (_("%P%F: bfd_hash_lookup for insertion failed: %E\n"));
8983d8817e4Smiod 	}
8993d8817e4Smiod     }
9003d8817e4Smiod 
9013d8817e4Smiod   if (link_info.strip != strip_none)
9023d8817e4Smiod     einfo (_("%P: `-retain-symbols-file' overrides `-s' and `-S'\n"));
9033d8817e4Smiod 
9043d8817e4Smiod   free (buf);
9053d8817e4Smiod   link_info.strip = strip_some;
9063d8817e4Smiod }
9073d8817e4Smiod 
9083d8817e4Smiod /* Callbacks from the BFD linker routines.  */
9093d8817e4Smiod 
9103d8817e4Smiod /* This is called when BFD has decided to include an archive member in
9113d8817e4Smiod    a link.  */
9123d8817e4Smiod 
9133d8817e4Smiod static bfd_boolean
add_archive_element(struct bfd_link_info * info,bfd * abfd,const char * name)9143d8817e4Smiod add_archive_element (struct bfd_link_info *info,
9153d8817e4Smiod 		     bfd *abfd,
9163d8817e4Smiod 		     const char *name)
9173d8817e4Smiod {
9183d8817e4Smiod   lang_input_statement_type *input;
9193d8817e4Smiod 
9203d8817e4Smiod   input = xmalloc (sizeof (lang_input_statement_type));
9213d8817e4Smiod   input->filename = abfd->filename;
9223d8817e4Smiod   input->local_sym_name = abfd->filename;
9233d8817e4Smiod   input->the_bfd = abfd;
9243d8817e4Smiod   input->asymbols = NULL;
9253d8817e4Smiod   input->next = NULL;
9263d8817e4Smiod   input->just_syms_flag = FALSE;
9273d8817e4Smiod   input->loaded = FALSE;
9283d8817e4Smiod   input->search_dirs_flag = FALSE;
9293d8817e4Smiod 
9303d8817e4Smiod   /* FIXME: The following fields are not set: header.next,
9313d8817e4Smiod      header.type, closed, passive_position, symbol_count,
9323d8817e4Smiod      next_real_file, is_archive, target, real.  This bit of code is
9333d8817e4Smiod      from the old decode_library_subfile function.  I don't know
9343d8817e4Smiod      whether any of those fields matters.  */
9353d8817e4Smiod 
9363d8817e4Smiod   ldlang_add_file (input);
9373d8817e4Smiod 
9383d8817e4Smiod   if (config.map_file != NULL)
9393d8817e4Smiod     {
9403d8817e4Smiod       static bfd_boolean header_printed;
9413d8817e4Smiod       struct bfd_link_hash_entry *h;
9423d8817e4Smiod       bfd *from;
9433d8817e4Smiod       int len;
9443d8817e4Smiod 
9453d8817e4Smiod       h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
9463d8817e4Smiod 
9473d8817e4Smiod       if (h == NULL)
9483d8817e4Smiod 	from = NULL;
9493d8817e4Smiod       else
9503d8817e4Smiod 	{
9513d8817e4Smiod 	  switch (h->type)
9523d8817e4Smiod 	    {
9533d8817e4Smiod 	    default:
9543d8817e4Smiod 	      from = NULL;
9553d8817e4Smiod 	      break;
9563d8817e4Smiod 
9573d8817e4Smiod 	    case bfd_link_hash_defined:
9583d8817e4Smiod 	    case bfd_link_hash_defweak:
9593d8817e4Smiod 	      from = h->u.def.section->owner;
9603d8817e4Smiod 	      break;
9613d8817e4Smiod 
9623d8817e4Smiod 	    case bfd_link_hash_undefined:
9633d8817e4Smiod 	    case bfd_link_hash_undefweak:
9643d8817e4Smiod 	      from = h->u.undef.abfd;
9653d8817e4Smiod 	      break;
9663d8817e4Smiod 
9673d8817e4Smiod 	    case bfd_link_hash_common:
9683d8817e4Smiod 	      from = h->u.c.p->section->owner;
9693d8817e4Smiod 	      break;
9703d8817e4Smiod 	    }
9713d8817e4Smiod 	}
9723d8817e4Smiod 
9733d8817e4Smiod       if (! header_printed)
9743d8817e4Smiod 	{
9753d8817e4Smiod 	  char buf[100];
9763d8817e4Smiod 
9773d8817e4Smiod 	  sprintf (buf, _("Archive member included because of file (symbol)\n\n"));
9783d8817e4Smiod 	  minfo ("%s", buf);
9793d8817e4Smiod 	  header_printed = TRUE;
9803d8817e4Smiod 	}
9813d8817e4Smiod 
9823d8817e4Smiod       if (bfd_my_archive (abfd) == NULL)
9833d8817e4Smiod 	{
9843d8817e4Smiod 	  minfo ("%s", bfd_get_filename (abfd));
9853d8817e4Smiod 	  len = strlen (bfd_get_filename (abfd));
9863d8817e4Smiod 	}
9873d8817e4Smiod       else
9883d8817e4Smiod 	{
9893d8817e4Smiod 	  minfo ("%s(%s)", bfd_get_filename (bfd_my_archive (abfd)),
9903d8817e4Smiod 		 bfd_get_filename (abfd));
9913d8817e4Smiod 	  len = (strlen (bfd_get_filename (bfd_my_archive (abfd)))
9923d8817e4Smiod 		 + strlen (bfd_get_filename (abfd))
9933d8817e4Smiod 		 + 2);
9943d8817e4Smiod 	}
9953d8817e4Smiod 
9963d8817e4Smiod       if (len >= 29)
9973d8817e4Smiod 	{
9983d8817e4Smiod 	  print_nl ();
9993d8817e4Smiod 	  len = 0;
10003d8817e4Smiod 	}
10013d8817e4Smiod       while (len < 30)
10023d8817e4Smiod 	{
10033d8817e4Smiod 	  print_space ();
10043d8817e4Smiod 	  ++len;
10053d8817e4Smiod 	}
10063d8817e4Smiod 
10073d8817e4Smiod       if (from != NULL)
10083d8817e4Smiod 	minfo ("%B ", from);
10093d8817e4Smiod       if (h != NULL)
10103d8817e4Smiod 	minfo ("(%T)\n", h->root.string);
10113d8817e4Smiod       else
10123d8817e4Smiod 	minfo ("(%s)\n", name);
10133d8817e4Smiod     }
10143d8817e4Smiod 
10153d8817e4Smiod   if (trace_files || trace_file_tries)
10163d8817e4Smiod     info_msg ("%I\n", input);
10173d8817e4Smiod 
10183d8817e4Smiod   return TRUE;
10193d8817e4Smiod }
10203d8817e4Smiod 
10213d8817e4Smiod /* This is called when BFD has discovered a symbol which is defined
10223d8817e4Smiod    multiple times.  */
10233d8817e4Smiod 
10243d8817e4Smiod static bfd_boolean
multiple_definition(struct bfd_link_info * info ATTRIBUTE_UNUSED,const char * name,bfd * obfd,asection * osec,bfd_vma oval,bfd * nbfd,asection * nsec,bfd_vma nval)10253d8817e4Smiod multiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED,
10263d8817e4Smiod 		     const char *name,
10273d8817e4Smiod 		     bfd *obfd,
10283d8817e4Smiod 		     asection *osec,
10293d8817e4Smiod 		     bfd_vma oval,
10303d8817e4Smiod 		     bfd *nbfd,
10313d8817e4Smiod 		     asection *nsec,
10323d8817e4Smiod 		     bfd_vma nval)
10333d8817e4Smiod {
10343d8817e4Smiod   /* If either section has the output_section field set to
10353d8817e4Smiod      bfd_abs_section_ptr, it means that the section is being
10363d8817e4Smiod      discarded, and this is not really a multiple definition at all.
10373d8817e4Smiod      FIXME: It would be cleaner to somehow ignore symbols defined in
10383d8817e4Smiod      sections which are being discarded.  */
10393d8817e4Smiod   if ((osec->output_section != NULL
10403d8817e4Smiod        && ! bfd_is_abs_section (osec)
10413d8817e4Smiod        && bfd_is_abs_section (osec->output_section))
10423d8817e4Smiod       || (nsec->output_section != NULL
10433d8817e4Smiod 	  && ! bfd_is_abs_section (nsec)
10443d8817e4Smiod 	  && bfd_is_abs_section (nsec->output_section)))
10453d8817e4Smiod     return TRUE;
10463d8817e4Smiod 
10473d8817e4Smiod   einfo (_("%X%C: multiple definition of `%T'\n"),
10483d8817e4Smiod 	 nbfd, nsec, nval, name);
10493d8817e4Smiod   if (obfd != NULL)
10503d8817e4Smiod     einfo (_("%D: first defined here\n"), obfd, osec, oval);
10513d8817e4Smiod 
10523d8817e4Smiod   if (command_line.relax)
10533d8817e4Smiod     {
10543d8817e4Smiod       einfo (_("%P: Disabling relaxation: it will not work with multiple definitions\n"));
10553d8817e4Smiod       command_line.relax = 0;
10563d8817e4Smiod     }
10573d8817e4Smiod 
10583d8817e4Smiod   return TRUE;
10593d8817e4Smiod }
10603d8817e4Smiod 
10613d8817e4Smiod /* This is called when there is a definition of a common symbol, or
10623d8817e4Smiod    when a common symbol is found for a symbol that is already defined,
10633d8817e4Smiod    or when two common symbols are found.  We only do something if
10643d8817e4Smiod    -warn-common was used.  */
10653d8817e4Smiod 
10663d8817e4Smiod static bfd_boolean
multiple_common(struct bfd_link_info * info ATTRIBUTE_UNUSED,const char * name,bfd * obfd,enum bfd_link_hash_type otype,bfd_vma osize,bfd * nbfd,enum bfd_link_hash_type ntype,bfd_vma nsize)10673d8817e4Smiod multiple_common (struct bfd_link_info *info ATTRIBUTE_UNUSED,
10683d8817e4Smiod 		 const char *name,
10693d8817e4Smiod 		 bfd *obfd,
10703d8817e4Smiod 		 enum bfd_link_hash_type otype,
10713d8817e4Smiod 		 bfd_vma osize,
10723d8817e4Smiod 		 bfd *nbfd,
10733d8817e4Smiod 		 enum bfd_link_hash_type ntype,
10743d8817e4Smiod 		 bfd_vma nsize)
10753d8817e4Smiod {
10763d8817e4Smiod   if (! config.warn_common)
10773d8817e4Smiod     return TRUE;
10783d8817e4Smiod 
10793d8817e4Smiod   if (ntype == bfd_link_hash_defined
10803d8817e4Smiod       || ntype == bfd_link_hash_defweak
10813d8817e4Smiod       || ntype == bfd_link_hash_indirect)
10823d8817e4Smiod     {
10833d8817e4Smiod       ASSERT (otype == bfd_link_hash_common);
10843d8817e4Smiod       einfo (_("%B: warning: definition of `%T' overriding common\n"),
10853d8817e4Smiod 	     nbfd, name);
10863d8817e4Smiod       if (obfd != NULL)
10873d8817e4Smiod 	einfo (_("%B: warning: common is here\n"), obfd);
10883d8817e4Smiod     }
10893d8817e4Smiod   else if (otype == bfd_link_hash_defined
10903d8817e4Smiod 	   || otype == bfd_link_hash_defweak
10913d8817e4Smiod 	   || otype == bfd_link_hash_indirect)
10923d8817e4Smiod     {
10933d8817e4Smiod       ASSERT (ntype == bfd_link_hash_common);
10943d8817e4Smiod       einfo (_("%B: warning: common of `%T' overridden by definition\n"),
10953d8817e4Smiod 	     nbfd, name);
10963d8817e4Smiod       if (obfd != NULL)
10973d8817e4Smiod 	einfo (_("%B: warning: defined here\n"), obfd);
10983d8817e4Smiod     }
10993d8817e4Smiod   else
11003d8817e4Smiod     {
11013d8817e4Smiod       ASSERT (otype == bfd_link_hash_common && ntype == bfd_link_hash_common);
11023d8817e4Smiod       if (osize > nsize)
11033d8817e4Smiod 	{
11043d8817e4Smiod 	  einfo (_("%B: warning: common of `%T' overridden by larger common\n"),
11053d8817e4Smiod 		 nbfd, name);
11063d8817e4Smiod 	  if (obfd != NULL)
11073d8817e4Smiod 	    einfo (_("%B: warning: larger common is here\n"), obfd);
11083d8817e4Smiod 	}
11093d8817e4Smiod       else if (nsize > osize)
11103d8817e4Smiod 	{
11113d8817e4Smiod 	  einfo (_("%B: warning: common of `%T' overriding smaller common\n"),
11123d8817e4Smiod 		 nbfd, name);
11133d8817e4Smiod 	  if (obfd != NULL)
11143d8817e4Smiod 	    einfo (_("%B: warning: smaller common is here\n"), obfd);
11153d8817e4Smiod 	}
11163d8817e4Smiod       else
11173d8817e4Smiod 	{
11183d8817e4Smiod 	  einfo (_("%B: warning: multiple common of `%T'\n"), nbfd, name);
11193d8817e4Smiod 	  if (obfd != NULL)
11203d8817e4Smiod 	    einfo (_("%B: warning: previous common is here\n"), obfd);
11213d8817e4Smiod 	}
11223d8817e4Smiod     }
11233d8817e4Smiod 
11243d8817e4Smiod   return TRUE;
11253d8817e4Smiod }
11263d8817e4Smiod 
11273d8817e4Smiod /* This is called when BFD has discovered a set element.  H is the
11283d8817e4Smiod    entry in the linker hash table for the set.  SECTION and VALUE
11293d8817e4Smiod    represent a value which should be added to the set.  */
11303d8817e4Smiod 
11313d8817e4Smiod static bfd_boolean
add_to_set(struct bfd_link_info * info ATTRIBUTE_UNUSED,struct bfd_link_hash_entry * h,bfd_reloc_code_real_type reloc,bfd * abfd,asection * section,bfd_vma value)11323d8817e4Smiod add_to_set (struct bfd_link_info *info ATTRIBUTE_UNUSED,
11333d8817e4Smiod 	    struct bfd_link_hash_entry *h,
11343d8817e4Smiod 	    bfd_reloc_code_real_type reloc,
11353d8817e4Smiod 	    bfd *abfd,
11363d8817e4Smiod 	    asection *section,
11373d8817e4Smiod 	    bfd_vma value)
11383d8817e4Smiod {
11393d8817e4Smiod   if (config.warn_constructors)
11403d8817e4Smiod     einfo (_("%P: warning: global constructor %s used\n"),
11413d8817e4Smiod 	   h->root.string);
11423d8817e4Smiod 
11433d8817e4Smiod   if (! config.build_constructors)
11443d8817e4Smiod     return TRUE;
11453d8817e4Smiod 
11463d8817e4Smiod   ldctor_add_set_entry (h, reloc, NULL, section, value);
11473d8817e4Smiod 
11483d8817e4Smiod   if (h->type == bfd_link_hash_new)
11493d8817e4Smiod     {
11503d8817e4Smiod       h->type = bfd_link_hash_undefined;
11513d8817e4Smiod       h->u.undef.abfd = abfd;
11523d8817e4Smiod       /* We don't call bfd_link_add_undef to add this to the list of
11533d8817e4Smiod 	 undefined symbols because we are going to define it
11543d8817e4Smiod 	 ourselves.  */
11553d8817e4Smiod     }
11563d8817e4Smiod 
11573d8817e4Smiod   return TRUE;
11583d8817e4Smiod }
11593d8817e4Smiod 
11603d8817e4Smiod /* This is called when BFD has discovered a constructor.  This is only
11613d8817e4Smiod    called for some object file formats--those which do not handle
11623d8817e4Smiod    constructors in some more clever fashion.  This is similar to
11633d8817e4Smiod    adding an element to a set, but less general.  */
11643d8817e4Smiod 
11653d8817e4Smiod static bfd_boolean
constructor_callback(struct bfd_link_info * info,bfd_boolean constructor,const char * name,bfd * abfd,asection * section,bfd_vma value)11663d8817e4Smiod constructor_callback (struct bfd_link_info *info,
11673d8817e4Smiod 		      bfd_boolean constructor,
11683d8817e4Smiod 		      const char *name,
11693d8817e4Smiod 		      bfd *abfd,
11703d8817e4Smiod 		      asection *section,
11713d8817e4Smiod 		      bfd_vma value)
11723d8817e4Smiod {
11733d8817e4Smiod   char *s;
11743d8817e4Smiod   struct bfd_link_hash_entry *h;
11753d8817e4Smiod   char set_name[1 + sizeof "__CTOR_LIST__"];
11763d8817e4Smiod 
11773d8817e4Smiod   if (config.warn_constructors)
11783d8817e4Smiod     einfo (_("%P: warning: global constructor %s used\n"), name);
11793d8817e4Smiod 
11803d8817e4Smiod   if (! config.build_constructors)
11813d8817e4Smiod     return TRUE;
11823d8817e4Smiod 
11833d8817e4Smiod   /* Ensure that BFD_RELOC_CTOR exists now, so that we can give a
11843d8817e4Smiod      useful error message.  */
11853d8817e4Smiod   if (bfd_reloc_type_lookup (output_bfd, BFD_RELOC_CTOR) == NULL
11863d8817e4Smiod       && (info->relocatable
11873d8817e4Smiod 	  || bfd_reloc_type_lookup (abfd, BFD_RELOC_CTOR) == NULL))
11883d8817e4Smiod     einfo (_("%P%F: BFD backend error: BFD_RELOC_CTOR unsupported\n"));
11893d8817e4Smiod 
11903d8817e4Smiod   s = set_name;
11913d8817e4Smiod   if (bfd_get_symbol_leading_char (abfd) != '\0')
11923d8817e4Smiod     *s++ = bfd_get_symbol_leading_char (abfd);
11933d8817e4Smiod   if (constructor)
11943d8817e4Smiod     strcpy (s, "__CTOR_LIST__");
11953d8817e4Smiod   else
11963d8817e4Smiod     strcpy (s, "__DTOR_LIST__");
11973d8817e4Smiod 
11983d8817e4Smiod   h = bfd_link_hash_lookup (info->hash, set_name, TRUE, TRUE, TRUE);
11993d8817e4Smiod   if (h == (struct bfd_link_hash_entry *) NULL)
12003d8817e4Smiod     einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
12013d8817e4Smiod   if (h->type == bfd_link_hash_new)
12023d8817e4Smiod     {
12033d8817e4Smiod       h->type = bfd_link_hash_undefined;
12043d8817e4Smiod       h->u.undef.abfd = abfd;
12053d8817e4Smiod       /* We don't call bfd_link_add_undef to add this to the list of
12063d8817e4Smiod 	 undefined symbols because we are going to define it
12073d8817e4Smiod 	 ourselves.  */
12083d8817e4Smiod     }
12093d8817e4Smiod 
12103d8817e4Smiod   ldctor_add_set_entry (h, BFD_RELOC_CTOR, name, section, value);
12113d8817e4Smiod   return TRUE;
12123d8817e4Smiod }
12133d8817e4Smiod 
12143d8817e4Smiod /* A structure used by warning_callback to pass information through
12153d8817e4Smiod    bfd_map_over_sections.  */
12163d8817e4Smiod 
12173d8817e4Smiod struct warning_callback_info
12183d8817e4Smiod {
12193d8817e4Smiod   bfd_boolean found;
12203d8817e4Smiod   const char *warning;
12213d8817e4Smiod   const char *symbol;
12223d8817e4Smiod   asymbol **asymbols;
12233d8817e4Smiod };
12243d8817e4Smiod 
12253d8817e4Smiod /* This is called when there is a reference to a warning symbol.  */
12263d8817e4Smiod 
12273d8817e4Smiod static bfd_boolean
warning_callback(struct bfd_link_info * info ATTRIBUTE_UNUSED,const char * warning,const char * symbol,bfd * abfd,asection * section,bfd_vma address)12283d8817e4Smiod warning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED,
12293d8817e4Smiod 		  const char *warning,
12303d8817e4Smiod 		  const char *symbol,
12313d8817e4Smiod 		  bfd *abfd,
12323d8817e4Smiod 		  asection *section,
12333d8817e4Smiod 		  bfd_vma address)
12343d8817e4Smiod {
12353d8817e4Smiod   /* This is a hack to support warn_multiple_gp.  FIXME: This should
12363d8817e4Smiod      have a cleaner interface, but what?  */
12373d8817e4Smiod   if (! config.warn_multiple_gp
12383d8817e4Smiod       && strcmp (warning, "using multiple gp values") == 0)
12393d8817e4Smiod     return TRUE;
12403d8817e4Smiod 
12413d8817e4Smiod   if (section != NULL)
12423d8817e4Smiod     einfo ("%C: %s%s\n", abfd, section, address, _("warning: "), warning);
12433d8817e4Smiod   else if (abfd == NULL)
12443d8817e4Smiod     einfo ("%P: %s%s\n", _("warning: "), warning);
12453d8817e4Smiod   else if (symbol == NULL)
12463d8817e4Smiod     einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
12473d8817e4Smiod   else
12483d8817e4Smiod     {
12493d8817e4Smiod       lang_input_statement_type *entry;
12503d8817e4Smiod       asymbol **asymbols;
12513d8817e4Smiod       struct warning_callback_info info;
12523d8817e4Smiod 
12533d8817e4Smiod       /* Look through the relocs to see if we can find a plausible
12543d8817e4Smiod 	 address.  */
12553d8817e4Smiod       entry = (lang_input_statement_type *) abfd->usrdata;
12563d8817e4Smiod       if (entry != NULL && entry->asymbols != NULL)
12573d8817e4Smiod 	asymbols = entry->asymbols;
12583d8817e4Smiod       else
12593d8817e4Smiod 	{
12603d8817e4Smiod 	  long symsize;
12613d8817e4Smiod 	  long symbol_count;
12623d8817e4Smiod 
12633d8817e4Smiod 	  symsize = bfd_get_symtab_upper_bound (abfd);
12643d8817e4Smiod 	  if (symsize < 0)
12653d8817e4Smiod 	    einfo (_("%B%F: could not read symbols: %E\n"), abfd);
12663d8817e4Smiod 	  asymbols = xmalloc (symsize);
12673d8817e4Smiod 	  symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
12683d8817e4Smiod 	  if (symbol_count < 0)
12693d8817e4Smiod 	    einfo (_("%B%F: could not read symbols: %E\n"), abfd);
12703d8817e4Smiod 	  if (entry != NULL)
12713d8817e4Smiod 	    {
12723d8817e4Smiod 	      entry->asymbols = asymbols;
12733d8817e4Smiod 	      entry->symbol_count = symbol_count;
12743d8817e4Smiod 	    }
12753d8817e4Smiod 	}
12763d8817e4Smiod 
12773d8817e4Smiod       info.found = FALSE;
12783d8817e4Smiod       info.warning = warning;
12793d8817e4Smiod       info.symbol = symbol;
12803d8817e4Smiod       info.asymbols = asymbols;
12813d8817e4Smiod       bfd_map_over_sections (abfd, warning_find_reloc, &info);
12823d8817e4Smiod 
12833d8817e4Smiod       if (! info.found)
12843d8817e4Smiod 	einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
12853d8817e4Smiod 
12863d8817e4Smiod       if (entry == NULL)
12873d8817e4Smiod 	free (asymbols);
12883d8817e4Smiod     }
12893d8817e4Smiod 
12903d8817e4Smiod   return TRUE;
12913d8817e4Smiod }
12923d8817e4Smiod 
12933d8817e4Smiod /* This is called by warning_callback for each section.  It checks the
12943d8817e4Smiod    relocs of the section to see if it can find a reference to the
12953d8817e4Smiod    symbol which triggered the warning.  If it can, it uses the reloc
12963d8817e4Smiod    to give an error message with a file and line number.  */
12973d8817e4Smiod 
12983d8817e4Smiod static void
warning_find_reloc(bfd * abfd,asection * sec,void * iarg)12993d8817e4Smiod warning_find_reloc (bfd *abfd, asection *sec, void *iarg)
13003d8817e4Smiod {
13013d8817e4Smiod   struct warning_callback_info *info = iarg;
13023d8817e4Smiod   long relsize;
13033d8817e4Smiod   arelent **relpp;
13043d8817e4Smiod   long relcount;
13053d8817e4Smiod   arelent **p, **pend;
13063d8817e4Smiod 
13073d8817e4Smiod   if (info->found)
13083d8817e4Smiod     return;
13093d8817e4Smiod 
13103d8817e4Smiod   relsize = bfd_get_reloc_upper_bound (abfd, sec);
13113d8817e4Smiod   if (relsize < 0)
13123d8817e4Smiod     einfo (_("%B%F: could not read relocs: %E\n"), abfd);
13133d8817e4Smiod   if (relsize == 0)
13143d8817e4Smiod     return;
13153d8817e4Smiod 
13163d8817e4Smiod   relpp = xmalloc (relsize);
13173d8817e4Smiod   relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
13183d8817e4Smiod   if (relcount < 0)
13193d8817e4Smiod     einfo (_("%B%F: could not read relocs: %E\n"), abfd);
13203d8817e4Smiod 
13213d8817e4Smiod   p = relpp;
13223d8817e4Smiod   pend = p + relcount;
13233d8817e4Smiod   for (; p < pend && *p != NULL; p++)
13243d8817e4Smiod     {
13253d8817e4Smiod       arelent *q = *p;
13263d8817e4Smiod 
13273d8817e4Smiod       if (q->sym_ptr_ptr != NULL
13283d8817e4Smiod 	  && *q->sym_ptr_ptr != NULL
13293d8817e4Smiod 	  && strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), info->symbol) == 0)
13303d8817e4Smiod 	{
13313d8817e4Smiod 	  /* We found a reloc for the symbol we are looking for.  */
13323d8817e4Smiod 	  einfo ("%C: %s%s\n", abfd, sec, q->address, _("warning: "),
13333d8817e4Smiod 		 info->warning);
13343d8817e4Smiod 	  info->found = TRUE;
13353d8817e4Smiod 	  break;
13363d8817e4Smiod 	}
13373d8817e4Smiod     }
13383d8817e4Smiod 
13393d8817e4Smiod   free (relpp);
13403d8817e4Smiod }
13413d8817e4Smiod 
13423d8817e4Smiod /* This is called when an undefined symbol is found.  */
13433d8817e4Smiod 
13443d8817e4Smiod static bfd_boolean
undefined_symbol(struct bfd_link_info * info ATTRIBUTE_UNUSED,const char * name,bfd * abfd,asection * section,bfd_vma address,bfd_boolean error)13453d8817e4Smiod undefined_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED,
13463d8817e4Smiod 		  const char *name,
13473d8817e4Smiod 		  bfd *abfd,
13483d8817e4Smiod 		  asection *section,
13493d8817e4Smiod 		  bfd_vma address,
13503d8817e4Smiod 		  bfd_boolean error)
13513d8817e4Smiod {
13523d8817e4Smiod   static char *error_name;
13533d8817e4Smiod   static unsigned int error_count;
13543d8817e4Smiod 
13553d8817e4Smiod #define MAX_ERRORS_IN_A_ROW 5
13563d8817e4Smiod 
13573d8817e4Smiod   if (config.warn_once)
13583d8817e4Smiod     {
13593d8817e4Smiod       static struct bfd_hash_table *hash;
13603d8817e4Smiod 
13613d8817e4Smiod       /* Only warn once about a particular undefined symbol.  */
13623d8817e4Smiod       if (hash == NULL)
13633d8817e4Smiod 	{
13643d8817e4Smiod 	  hash = xmalloc (sizeof (struct bfd_hash_table));
13653d8817e4Smiod 	  if (!bfd_hash_table_init (hash, bfd_hash_newfunc,
13663d8817e4Smiod 				    sizeof (struct bfd_hash_entry)))
13673d8817e4Smiod 	    einfo (_("%F%P: bfd_hash_table_init failed: %E\n"));
13683d8817e4Smiod 	}
13693d8817e4Smiod 
13703d8817e4Smiod       if (bfd_hash_lookup (hash, name, FALSE, FALSE) != NULL)
13713d8817e4Smiod 	return TRUE;
13723d8817e4Smiod 
13733d8817e4Smiod       if (bfd_hash_lookup (hash, name, TRUE, TRUE) == NULL)
13743d8817e4Smiod 	einfo (_("%F%P: bfd_hash_lookup failed: %E\n"));
13753d8817e4Smiod     }
13763d8817e4Smiod 
13773d8817e4Smiod   /* We never print more than a reasonable number of errors in a row
13783d8817e4Smiod      for a single symbol.  */
13793d8817e4Smiod   if (error_name != NULL
13803d8817e4Smiod       && strcmp (name, error_name) == 0)
13813d8817e4Smiod     ++error_count;
13823d8817e4Smiod   else
13833d8817e4Smiod     {
13843d8817e4Smiod       error_count = 0;
13853d8817e4Smiod       if (error_name != NULL)
13863d8817e4Smiod 	free (error_name);
13873d8817e4Smiod       error_name = xstrdup (name);
13883d8817e4Smiod     }
13893d8817e4Smiod 
13903d8817e4Smiod   if (section != NULL)
13913d8817e4Smiod     {
13923d8817e4Smiod       if (error_count < MAX_ERRORS_IN_A_ROW)
13933d8817e4Smiod 	{
13943d8817e4Smiod 	  if (error)
13953d8817e4Smiod 	    einfo (_("%X%C: undefined reference to `%T'\n"),
13963d8817e4Smiod 		   abfd, section, address, name);
13973d8817e4Smiod 	  else
13983d8817e4Smiod 	    einfo (_("%C: warning: undefined reference to `%T'\n"),
13993d8817e4Smiod 		   abfd, section, address, name);
14003d8817e4Smiod 	}
14013d8817e4Smiod       else if (error_count == MAX_ERRORS_IN_A_ROW)
14023d8817e4Smiod 	{
14033d8817e4Smiod 	  if (error)
14043d8817e4Smiod 	    einfo (_("%X%D: more undefined references to `%T' follow\n"),
14053d8817e4Smiod 		   abfd, section, address, name);
14063d8817e4Smiod 	  else
14073d8817e4Smiod 	    einfo (_("%D: warning: more undefined references to `%T' follow\n"),
14083d8817e4Smiod 		   abfd, section, address, name);
14093d8817e4Smiod 	}
14103d8817e4Smiod       else if (error)
14113d8817e4Smiod 	einfo ("%X");
14123d8817e4Smiod     }
14133d8817e4Smiod   else
14143d8817e4Smiod     {
14153d8817e4Smiod       if (error_count < MAX_ERRORS_IN_A_ROW)
14163d8817e4Smiod 	{
14173d8817e4Smiod 	  if (error)
14183d8817e4Smiod 	    einfo (_("%X%B: undefined reference to `%T'\n"),
14193d8817e4Smiod 		   abfd, name);
14203d8817e4Smiod 	  else
14213d8817e4Smiod 	    einfo (_("%B: warning: undefined reference to `%T'\n"),
14223d8817e4Smiod 		   abfd, name);
14233d8817e4Smiod 	}
14243d8817e4Smiod       else if (error_count == MAX_ERRORS_IN_A_ROW)
14253d8817e4Smiod 	{
14263d8817e4Smiod 	  if (error)
14273d8817e4Smiod 	    einfo (_("%X%B: more undefined references to `%T' follow\n"),
14283d8817e4Smiod 		   abfd, name);
14293d8817e4Smiod 	  else
14303d8817e4Smiod 	    einfo (_("%B: warning: more undefined references to `%T' follow\n"),
14313d8817e4Smiod 		   abfd, name);
14323d8817e4Smiod 	}
14333d8817e4Smiod       else if (error)
14343d8817e4Smiod 	einfo ("%X");
14353d8817e4Smiod     }
14363d8817e4Smiod 
14373d8817e4Smiod   return TRUE;
14383d8817e4Smiod }
14393d8817e4Smiod 
14403d8817e4Smiod /* Counter to limit the number of relocation overflow error messages
14413d8817e4Smiod    to print.  Errors are printed as it is decremented.  When it's
14423d8817e4Smiod    called and the counter is zero, a final message is printed
14433d8817e4Smiod    indicating more relocations were omitted.  When it gets to -1, no
14443d8817e4Smiod    such errors are printed.  If it's initially set to a value less
14453d8817e4Smiod    than -1, all such errors will be printed (--verbose does this).  */
14463d8817e4Smiod 
14473d8817e4Smiod int overflow_cutoff_limit = 10;
14483d8817e4Smiod 
14493d8817e4Smiod /* This is called when a reloc overflows.  */
14503d8817e4Smiod 
14513d8817e4Smiod static bfd_boolean
reloc_overflow(struct bfd_link_info * info ATTRIBUTE_UNUSED,struct bfd_link_hash_entry * entry,const char * name,const char * reloc_name,bfd_vma addend,bfd * abfd,asection * section,bfd_vma address)14523d8817e4Smiod reloc_overflow (struct bfd_link_info *info ATTRIBUTE_UNUSED,
14533d8817e4Smiod 		struct bfd_link_hash_entry *entry,
14543d8817e4Smiod 		const char *name,
14553d8817e4Smiod 		const char *reloc_name,
14563d8817e4Smiod 		bfd_vma addend,
14573d8817e4Smiod 		bfd *abfd,
14583d8817e4Smiod 		asection *section,
14593d8817e4Smiod 		bfd_vma address)
14603d8817e4Smiod {
14613d8817e4Smiod   if (overflow_cutoff_limit == -1)
14623d8817e4Smiod     return TRUE;
14633d8817e4Smiod 
14643d8817e4Smiod   einfo ("%X%C:", abfd, section, address);
14653d8817e4Smiod 
14663d8817e4Smiod   if (overflow_cutoff_limit >= 0
14673d8817e4Smiod       && overflow_cutoff_limit-- == 0)
14683d8817e4Smiod     {
14693d8817e4Smiod       einfo (_(" additional relocation overflows omitted from the output\n"));
14703d8817e4Smiod       return TRUE;
14713d8817e4Smiod     }
14723d8817e4Smiod 
14733d8817e4Smiod   if (entry)
14743d8817e4Smiod     {
14753d8817e4Smiod       while (entry->type == bfd_link_hash_indirect
14763d8817e4Smiod 	     || entry->type == bfd_link_hash_warning)
14773d8817e4Smiod 	entry = entry->u.i.link;
14783d8817e4Smiod       switch (entry->type)
14793d8817e4Smiod 	{
14803d8817e4Smiod 	case bfd_link_hash_undefined:
14813d8817e4Smiod 	case bfd_link_hash_undefweak:
14823d8817e4Smiod 	  einfo (_(" relocation truncated to fit: %s against undefined symbol `%T'"),
14833d8817e4Smiod 		 reloc_name, entry->root.string);
14843d8817e4Smiod 	  break;
14853d8817e4Smiod 	case bfd_link_hash_defined:
14863d8817e4Smiod 	case bfd_link_hash_defweak:
14873d8817e4Smiod 	  einfo (_(" relocation truncated to fit: %s against symbol `%T' defined in %A section in %B"),
14883d8817e4Smiod 		 reloc_name, entry->root.string,
14893d8817e4Smiod 		 entry->u.def.section,
14903d8817e4Smiod 		 entry->u.def.section == bfd_abs_section_ptr
14913d8817e4Smiod 		 ? output_bfd : entry->u.def.section->owner);
14923d8817e4Smiod 	  break;
14933d8817e4Smiod 	default:
14943d8817e4Smiod 	  abort ();
14953d8817e4Smiod 	  break;
14963d8817e4Smiod 	}
14973d8817e4Smiod     }
14983d8817e4Smiod   else
14993d8817e4Smiod     einfo (_(" relocation truncated to fit: %s against `%T'"),
15003d8817e4Smiod 	   reloc_name, name);
15013d8817e4Smiod   if (addend != 0)
15023d8817e4Smiod     einfo ("+%v", addend);
15033d8817e4Smiod   einfo ("\n");
15043d8817e4Smiod   return TRUE;
15053d8817e4Smiod }
15063d8817e4Smiod 
15073d8817e4Smiod /* This is called when a dangerous relocation is made.  */
15083d8817e4Smiod 
15093d8817e4Smiod static bfd_boolean
reloc_dangerous(struct bfd_link_info * info ATTRIBUTE_UNUSED,const char * message,bfd * abfd,asection * section,bfd_vma address)15103d8817e4Smiod reloc_dangerous (struct bfd_link_info *info ATTRIBUTE_UNUSED,
15113d8817e4Smiod 		 const char *message,
15123d8817e4Smiod 		 bfd *abfd,
15133d8817e4Smiod 		 asection *section,
15143d8817e4Smiod 		 bfd_vma address)
15153d8817e4Smiod {
15163d8817e4Smiod   einfo (_("%X%C: dangerous relocation: %s\n"),
15173d8817e4Smiod 	 abfd, section, address, message);
15183d8817e4Smiod   return TRUE;
15193d8817e4Smiod }
15203d8817e4Smiod 
15213d8817e4Smiod /* This is called when a reloc is being generated attached to a symbol
15223d8817e4Smiod    that is not being output.  */
15233d8817e4Smiod 
15243d8817e4Smiod static bfd_boolean
unattached_reloc(struct bfd_link_info * info ATTRIBUTE_UNUSED,const char * name,bfd * abfd,asection * section,bfd_vma address)15253d8817e4Smiod unattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED,
15263d8817e4Smiod 		  const char *name,
15273d8817e4Smiod 		  bfd *abfd,
15283d8817e4Smiod 		  asection *section,
15293d8817e4Smiod 		  bfd_vma address)
15303d8817e4Smiod {
15313d8817e4Smiod   einfo (_("%X%C: reloc refers to symbol `%T' which is not being output\n"),
15323d8817e4Smiod 	 abfd, section, address, name);
15333d8817e4Smiod   return TRUE;
15343d8817e4Smiod }
15353d8817e4Smiod 
15363d8817e4Smiod /* This is called if link_info.notice_all is set, or when a symbol in
15373d8817e4Smiod    link_info.notice_hash is found.  Symbols are put in notice_hash
15383d8817e4Smiod    using the -y option.  */
15393d8817e4Smiod 
15403d8817e4Smiod static bfd_boolean
notice(struct bfd_link_info * info,const char * name,bfd * abfd,asection * section,bfd_vma value)15413d8817e4Smiod notice (struct bfd_link_info *info,
15423d8817e4Smiod 	const char *name,
15433d8817e4Smiod 	bfd *abfd,
15443d8817e4Smiod 	asection *section,
15453d8817e4Smiod 	bfd_vma value)
15463d8817e4Smiod {
15473d8817e4Smiod   if (! info->notice_all
15483d8817e4Smiod       || (info->notice_hash != NULL
15493d8817e4Smiod 	  && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
15503d8817e4Smiod     {
15513d8817e4Smiod       if (bfd_is_und_section (section))
15523d8817e4Smiod 	einfo ("%B: reference to %s\n", abfd, name);
15533d8817e4Smiod       else
15543d8817e4Smiod 	einfo ("%B: definition of %s\n", abfd, name);
15553d8817e4Smiod     }
15563d8817e4Smiod 
15573d8817e4Smiod   if (command_line.cref || nocrossref_list != NULL)
15583d8817e4Smiod     add_cref (name, abfd, section, value);
15593d8817e4Smiod 
15603d8817e4Smiod   return TRUE;
15613d8817e4Smiod }
1562