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