133965Sjdp/* Main program of GNU linker.
291041Sobrien   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3218822Sdim   2002, 2003, 2004, 2005, 2006, 2007
460484Sobrien   Free Software Foundation, Inc.
533965Sjdp   Written by Steve Chamberlain steve@cygnus.com
633965Sjdp
7130561Sobrien   This file is part of GLD, the Gnu Linker.
833965Sjdp
9130561Sobrien   GLD is free software; you can redistribute it and/or modify
10130561Sobrien   it under the terms of the GNU General Public License as published by
11130561Sobrien   the Free Software Foundation; either version 2, or (at your option)
12130561Sobrien   any later version.
1333965Sjdp
14130561Sobrien   GLD is distributed in the hope that it will be useful,
15130561Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
16130561Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17130561Sobrien   GNU General Public License for more details.
1833965Sjdp
19130561Sobrien   You should have received a copy of the GNU General Public License
20130561Sobrien   along with GLD; see the file COPYING.  If not, write to the Free
21218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
22218822Sdim   02110-1301, USA.  */
2333965Sjdp
24218822Sdim#include "sysdep.h"
2533965Sjdp#include "bfd.h"
2689857Sobrien#include "safe-ctype.h"
2733965Sjdp#include "libiberty.h"
2833965Sjdp#include "progress.h"
2933965Sjdp#include "bfdlink.h"
3061843Sobrien#include "filenames.h"
3133965Sjdp
3233965Sjdp#include "ld.h"
3333965Sjdp#include "ldmain.h"
3433965Sjdp#include "ldmisc.h"
3533965Sjdp#include "ldwrite.h"
3633965Sjdp#include "ldexp.h"
3733965Sjdp#include "ldlang.h"
38107492Sobrien#include <ldgram.h>
3933965Sjdp#include "ldlex.h"
4033965Sjdp#include "ldfile.h"
4177298Sobrien#include "ldemul.h"
4233965Sjdp#include "ldctor.h"
4333965Sjdp
44130561Sobrien/* Somewhere above, sys/stat.h got included.  */
4533965Sjdp#if !defined(S_ISDIR) && defined(S_IFDIR)
4633965Sjdp#define	S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
4733965Sjdp#endif
4833965Sjdp
4933965Sjdp#include <string.h>
5033965Sjdp
5133965Sjdp#ifdef HAVE_SBRK
52218822Sdim#if !HAVE_DECL_SBRK
53130561Sobrienextern void *sbrk ();
5433965Sjdp#endif
5533965Sjdp#endif
5633965Sjdp
57130561Sobrien#ifndef TARGET_SYSTEM_ROOT
58130561Sobrien#define TARGET_SYSTEM_ROOT ""
59130561Sobrien#endif
6091041Sobrien
6133965Sjdp/* EXPORTS */
6233965Sjdp
6333965Sjdpchar *default_target;
6433965Sjdpconst char *output_filename = "a.out";
6533965Sjdp
6633965Sjdp/* Name this program was invoked by.  */
6733965Sjdpchar *program_name;
6833965Sjdp
69130561Sobrien/* The prefix for system library directories.  */
70218822Sdimconst char *ld_sysroot;
71130561Sobrien
72130561Sobrien/* The canonical representation of ld_sysroot.  */
73130561Sobrienchar * ld_canon_sysroot;
74130561Sobrienint ld_canon_sysroot_len;
75130561Sobrien
7677298Sobrien/* The file that we're creating.  */
7733965Sjdpbfd *output_bfd = 0;
7833965Sjdp
7933965Sjdp/* Set by -G argument, for MIPS ECOFF target.  */
8033965Sjdpint g_switch_value = 8;
8133965Sjdp
8233965Sjdp/* Nonzero means print names of input files as processed.  */
83130561Sobrienbfd_boolean trace_files;
8433965Sjdp
8533965Sjdp/* Nonzero means same, but note open failures, too.  */
86130561Sobrienbfd_boolean trace_file_tries;
8733965Sjdp
8833965Sjdp/* Nonzero means version number was printed, so exit successfully
8933965Sjdp   instead of complaining if no input files are given.  */
90130561Sobrienbfd_boolean version_printed;
9133965Sjdp
9233965Sjdp/* Nonzero means link in every member of an archive.  */
93130561Sobrienbfd_boolean whole_archive;
9433965Sjdp
95130561Sobrien/* Nonzero means create DT_NEEDED entries only if a dynamic library
96130561Sobrien   actually satisfies some reference in a regular object.  */
97130561Sobrienbfd_boolean as_needed;
9860484Sobrien
99218822Sdim/* Nonzero means never create DT_NEEDED entries for dynamic libraries
100218822Sdim   in DT_NEEDED tags.  */
101253839Sbaptbfd_boolean add_needed = FALSE;
102218822Sdim
103130561Sobrien/* TRUE if we should demangle symbol names.  */
104130561Sobrienbfd_boolean demangling;
105130561Sobrien
10633965Sjdpargs_type command_line;
10733965Sjdp
10833965Sjdpld_config_type config;
10933965Sjdp
110218822Sdimsort_type sort_section;
111218822Sdim
112218822Sdimstatic const char *get_sysroot
113218822Sdim  (int, char **);
114130561Sobrienstatic char *get_emulation
115130561Sobrien  (int, char **);
116130561Sobrienstatic void set_scripts_dir
117130561Sobrien  (void);
118130561Sobrienstatic bfd_boolean add_archive_element
119130561Sobrien  (struct bfd_link_info *, bfd *, const char *);
120130561Sobrienstatic bfd_boolean multiple_definition
121130561Sobrien  (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma,
122130561Sobrien   bfd *, asection *, bfd_vma);
123130561Sobrienstatic bfd_boolean multiple_common
124130561Sobrien  (struct bfd_link_info *, const char *, bfd *, enum bfd_link_hash_type,
125130561Sobrien   bfd_vma, bfd *, enum bfd_link_hash_type, bfd_vma);
126130561Sobrienstatic bfd_boolean add_to_set
127130561Sobrien  (struct bfd_link_info *, struct bfd_link_hash_entry *,
128130561Sobrien   bfd_reloc_code_real_type, bfd *, asection *, bfd_vma);
129130561Sobrienstatic bfd_boolean constructor_callback
130130561Sobrien  (struct bfd_link_info *, bfd_boolean, const char *, bfd *,
131130561Sobrien   asection *, bfd_vma);
132130561Sobrienstatic bfd_boolean warning_callback
133130561Sobrien  (struct bfd_link_info *, const char *, const char *, bfd *,
134130561Sobrien   asection *, bfd_vma);
135130561Sobrienstatic void warning_find_reloc
136130561Sobrien  (bfd *, asection *, void *);
137130561Sobrienstatic bfd_boolean undefined_symbol
138130561Sobrien  (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma,
139130561Sobrien   bfd_boolean);
140130561Sobrienstatic bfd_boolean reloc_overflow
141218822Sdim  (struct bfd_link_info *, struct bfd_link_hash_entry *, const char *,
142218822Sdim   const char *, bfd_vma, bfd *, asection *, bfd_vma);
143130561Sobrienstatic bfd_boolean reloc_dangerous
144130561Sobrien  (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
145130561Sobrienstatic bfd_boolean unattached_reloc
146130561Sobrien  (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
147130561Sobrienstatic bfd_boolean notice
148130561Sobrien  (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
14933965Sjdp
150130561Sobrienstatic struct bfd_link_callbacks link_callbacks =
151130561Sobrien{
15233965Sjdp  add_archive_element,
15333965Sjdp  multiple_definition,
15433965Sjdp  multiple_common,
15533965Sjdp  add_to_set,
15633965Sjdp  constructor_callback,
15733965Sjdp  warning_callback,
15833965Sjdp  undefined_symbol,
15933965Sjdp  reloc_overflow,
16033965Sjdp  reloc_dangerous,
16133965Sjdp  unattached_reloc,
162130561Sobrien  notice,
163218822Sdim  einfo,
164218822Sdim  info_msg,
165218822Sdim  minfo,
166218822Sdim  ldlang_override_segment_assignment
16733965Sjdp};
16833965Sjdp
16933965Sjdpstruct bfd_link_info link_info;
17033965Sjdp
17133965Sjdpstatic void
172130561Sobrienremove_output (void)
17333965Sjdp{
17477298Sobrien  if (output_filename)
17533965Sjdp    {
176130561Sobrien      if (output_bfd)
177130561Sobrien	bfd_cache_close (output_bfd);
17833965Sjdp      if (delete_output_file_on_failure)
179218822Sdim	unlink_if_ordinary (output_filename);
18033965Sjdp    }
18133965Sjdp}
18233965Sjdp
18333965Sjdpint
184130561Sobrienmain (int argc, char **argv)
18533965Sjdp{
18633965Sjdp  char *emulation;
18733965Sjdp  long start_time = get_run_time ();
18833965Sjdp
18960484Sobrien#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
19060484Sobrien  setlocale (LC_MESSAGES, "");
19160484Sobrien#endif
19289857Sobrien#if defined (HAVE_SETLOCALE)
19389857Sobrien  setlocale (LC_CTYPE, "");
19489857Sobrien#endif
19560484Sobrien  bindtextdomain (PACKAGE, LOCALEDIR);
19660484Sobrien  textdomain (PACKAGE);
19760484Sobrien
19833965Sjdp  program_name = argv[0];
19933965Sjdp  xmalloc_set_program_name (program_name);
20033965Sjdp
20133965Sjdp  START_PROGRESS (program_name, 0);
20233965Sjdp
203218822Sdim  expandargv (&argc, &argv);
204218822Sdim
20533965Sjdp  bfd_init ();
20633965Sjdp
20733965Sjdp  bfd_set_error_program_name (program_name);
20833965Sjdp
20933965Sjdp  xatexit (remove_output);
21033965Sjdp
211218822Sdim  /* Set up the sysroot directory.  */
212218822Sdim  ld_sysroot = get_sysroot (argc, argv);
213218822Sdim  if (*ld_sysroot)
214130561Sobrien    {
215218822Sdim      if (*TARGET_SYSTEM_ROOT == 0)
216130561Sobrien	{
217218822Sdim	  einfo ("%P%F: this linker was not configured to use sysroots\n");
218218822Sdim	  ld_sysroot = "";
219130561Sobrien	}
220218822Sdim      else
221218822Sdim	ld_canon_sysroot = lrealpath (ld_sysroot);
222130561Sobrien    }
223130561Sobrien  if (ld_canon_sysroot)
224130561Sobrien    ld_canon_sysroot_len = strlen (ld_canon_sysroot);
225130561Sobrien  else
226130561Sobrien    ld_canon_sysroot_len = -1;
227130561Sobrien
22833965Sjdp  /* Set the default BFD target based on the configured target.  Doing
22933965Sjdp     this permits the linker to be configured for a particular target,
23033965Sjdp     and linked against a shared BFD library which was configured for
23133965Sjdp     a different target.  The macro TARGET is defined by Makefile.  */
23233965Sjdp  if (! bfd_set_default_target (TARGET))
23333965Sjdp    {
23460484Sobrien      einfo (_("%X%P: can't set BFD default target to `%s': %E\n"), TARGET);
23533965Sjdp      xexit (1);
23633965Sjdp    }
23733965Sjdp
23889857Sobrien#if YYDEBUG
23989857Sobrien  {
24089857Sobrien    extern int yydebug;
24189857Sobrien    yydebug = 1;
24289857Sobrien  }
24389857Sobrien#endif
24489857Sobrien
245130561Sobrien  config.build_constructors = TRUE;
246218822Sdim  config.rpath_separator = ':';
24777298Sobrien  config.split_by_reloc = (unsigned) -1;
24877298Sobrien  config.split_by_file = (bfd_size_type) -1;
249218822Sdim  config.make_executable = TRUE;
250218822Sdim  config.magic_demand_paged = TRUE;
251218822Sdim  config.text_read_only = TRUE;
252218822Sdim
253130561Sobrien  command_line.warn_mismatch = TRUE;
254218822Sdim  command_line.warn_search_mismatch = TRUE;
255130561Sobrien  command_line.check_section_addresses = TRUE;
25633965Sjdp
25760484Sobrien  /* We initialize DEMANGLING based on the environment variable
25860484Sobrien     COLLECT_NO_DEMANGLE.  The gcc collect2 program will demangle the
25960484Sobrien     output of the linker, unless COLLECT_NO_DEMANGLE is set in the
26060484Sobrien     environment.  Acting the same way here lets us provide the same
26160484Sobrien     interface by default.  */
26260484Sobrien  demangling = getenv ("COLLECT_NO_DEMANGLE") == NULL;
26360484Sobrien
264130561Sobrien  link_info.allow_undefined_version = TRUE;
265130561Sobrien  link_info.keep_memory = TRUE;
266130561Sobrien  link_info.combreloc = TRUE;
267130561Sobrien  link_info.strip_discarded = TRUE;
268218822Sdim  link_info.emit_hash = TRUE;
269130561Sobrien  link_info.callbacks = &link_callbacks;
270218822Sdim  link_info.input_bfds_tail = &link_info.input_bfds;
27160484Sobrien  /* SVR4 linkers seem to set DT_INIT and DT_FINI based on magic _init
27260484Sobrien     and _fini symbols.  We are compatible.  */
27360484Sobrien  link_info.init_function = "_init";
27460484Sobrien  link_info.fini_function = "_fini";
275218822Sdim  link_info.relax_pass = 1;
276104834Sobrien  link_info.pei386_auto_import = -1;
27789857Sobrien  link_info.spare_dynamic_tags = 5;
27860484Sobrien
27933965Sjdp  ldfile_add_arch ("");
28033965Sjdp  emulation = get_emulation (argc, argv);
28133965Sjdp  ldemul_choose_mode (emulation);
28289857Sobrien  default_target = ldemul_choose_target (argc, argv);
28333965Sjdp  lang_init ();
28433965Sjdp  ldemul_before_parse ();
285130561Sobrien  lang_has_input_file = FALSE;
28633965Sjdp  parse_args (argc, argv);
28733965Sjdp
288218822Sdim  if (config.hash_table_size != 0)
289218822Sdim    bfd_hash_set_default_size (config.hash_table_size);
290218822Sdim
29133965Sjdp  ldemul_set_symbols ();
29233965Sjdp
293130561Sobrien  if (link_info.relocatable)
29433965Sjdp    {
295218822Sdim      if (link_info.gc_sections)
29660484Sobrien	einfo ("%P%F: --gc-sections and -r may not be used together\n");
29760484Sobrien      else if (command_line.relax)
29860484Sobrien	einfo (_("%P%F: --relax and -r may not be used together\n"));
29933965Sjdp      if (link_info.shared)
30060484Sobrien	einfo (_("%P%F: -r and -shared may not be used together\n"));
30133965Sjdp    }
30233965Sjdp
303218822Sdim  /* We may have -Bsymbolic, -Bsymbolic-functions, --dynamic-list-data,
304218822Sdim     --dynamic-list-cpp-new, --dynamic-list-cpp-typeinfo and
305218822Sdim     --dynamic-list FILE.  -Bsymbolic and -Bsymbolic-functions are
306218822Sdim     for shared libraries.  -Bsymbolic overrides all others and vice
307218822Sdim     versa.  */
308218822Sdim  switch (command_line.symbolic)
309218822Sdim    {
310218822Sdim    case symbolic_unset:
311218822Sdim      break;
312218822Sdim    case symbolic:
313218822Sdim      /* -Bsymbolic is for shared library only.  */
314218822Sdim      if (link_info.shared)
315218822Sdim	{
316218822Sdim	  link_info.symbolic = TRUE;
317218822Sdim	  /* Should we free the unused memory?  */
318218822Sdim	  link_info.dynamic_list = NULL;
319218822Sdim	  command_line.dynamic_list = dynamic_list_unset;
320218822Sdim	}
321218822Sdim      break;
322218822Sdim    case symbolic_functions:
323218822Sdim      /* -Bsymbolic-functions is for shared library only.  */
324218822Sdim      if (link_info.shared)
325218822Sdim	command_line.dynamic_list = dynamic_list_data;
326218822Sdim      break;
327218822Sdim    }
328218822Sdim
329218822Sdim  switch (command_line.dynamic_list)
330218822Sdim    {
331218822Sdim    case dynamic_list_unset:
332218822Sdim      break;
333218822Sdim    case dynamic_list_data:
334218822Sdim      link_info.dynamic_data = TRUE;
335218822Sdim    case dynamic_list:
336218822Sdim      link_info.dynamic = TRUE;
337218822Sdim      break;
338218822Sdim    }
339218822Sdim
34089857Sobrien  if (! link_info.shared)
34189857Sobrien    {
34289857Sobrien      if (command_line.filter_shlib)
34389857Sobrien	einfo (_("%P%F: -F may not be used without -shared\n"));
34489857Sobrien      if (command_line.auxiliary_filters)
34589857Sobrien	einfo (_("%P%F: -f may not be used without -shared\n"));
34689857Sobrien    }
34789857Sobrien
348130561Sobrien  if (! link_info.shared || link_info.pie)
349130561Sobrien    link_info.executable = TRUE;
350130561Sobrien
35133965Sjdp  /* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols).  I
35233965Sjdp     don't see how else this can be handled, since in this case we
35333965Sjdp     must preserve all externally visible symbols.  */
354130561Sobrien  if (link_info.relocatable && link_info.strip == strip_all)
35533965Sjdp    {
35633965Sjdp      link_info.strip = strip_debugger;
35789857Sobrien      if (link_info.discard == discard_sec_merge)
35833965Sjdp	link_info.discard = discard_all;
35933965Sjdp    }
36033965Sjdp
36133965Sjdp  /* This essentially adds another -L directory so this must be done after
36233965Sjdp     the -L's in argv have been processed.  */
36333965Sjdp  set_scripts_dir ();
36433965Sjdp
365218822Sdim  /* If we have not already opened and parsed a linker script,
366218822Sdim     try the default script from command line first.  */
367218822Sdim  if (saved_script_handle == NULL
368218822Sdim      && command_line.default_script != NULL)
369218822Sdim    {
370218822Sdim      ldfile_open_command_file (command_line.default_script);
371218822Sdim      parser_input = input_script;
372218822Sdim      yyparse ();
373218822Sdim    }
374218822Sdim
37589857Sobrien  /* If we have not already opened and parsed a linker script
37689857Sobrien     read the emulation's appropriate default script.  */
37789857Sobrien  if (saved_script_handle == NULL)
37833965Sjdp    {
37933965Sjdp      int isfile;
380104834Sobrien      char *s = ldemul_get_script (&isfile);
38133965Sjdp
38233965Sjdp      if (isfile)
38333965Sjdp	ldfile_open_command_file (s);
38433965Sjdp      else
385104834Sobrien	{
38633965Sjdp	  lex_string = s;
38733965Sjdp	  lex_redirect (s);
38833965Sjdp	}
38933965Sjdp      parser_input = input_script;
39033965Sjdp      yyparse ();
39133965Sjdp      lex_string = NULL;
39233965Sjdp    }
39333965Sjdp
39489857Sobrien  if (trace_file_tries)
39589857Sobrien    {
39689857Sobrien      if (saved_script_handle)
39789857Sobrien	info_msg (_("using external linker script:"));
39889857Sobrien      else
39989857Sobrien	info_msg (_("using internal linker script:"));
40089857Sobrien      info_msg ("\n==================================================\n");
40189857Sobrien
40289857Sobrien      if (saved_script_handle)
40389857Sobrien	{
40489857Sobrien	  static const int ld_bufsz = 8193;
40589857Sobrien	  size_t n;
40689857Sobrien	  char *buf = xmalloc (ld_bufsz);
40789857Sobrien
40889857Sobrien	  rewind (saved_script_handle);
40989857Sobrien	  while ((n = fread (buf, 1, ld_bufsz - 1, saved_script_handle)) > 0)
41089857Sobrien	    {
411104834Sobrien	      buf[n] = 0;
41289857Sobrien	      info_msg (buf);
41389857Sobrien	    }
41489857Sobrien	  rewind (saved_script_handle);
41589857Sobrien	  free (buf);
41689857Sobrien	}
41789857Sobrien      else
41889857Sobrien	{
41989857Sobrien	  int isfile;
42089857Sobrien
421104834Sobrien	  info_msg (ldemul_get_script (&isfile));
42289857Sobrien	}
423104834Sobrien
42489857Sobrien      info_msg ("\n==================================================\n");
42589857Sobrien    }
42689857Sobrien
42733965Sjdp  lang_final ();
42833965Sjdp
429130561Sobrien  if (!lang_has_input_file)
43033965Sjdp    {
43133965Sjdp      if (version_printed)
43233965Sjdp	xexit (0);
43360484Sobrien      einfo (_("%P%F: no input files\n"));
43433965Sjdp    }
43533965Sjdp
43633965Sjdp  if (trace_files)
437130561Sobrien    info_msg (_("%P: mode %s\n"), emulation);
43833965Sjdp
43933965Sjdp  ldemul_after_parse ();
44033965Sjdp
44133965Sjdp  if (config.map_filename)
44233965Sjdp    {
44333965Sjdp      if (strcmp (config.map_filename, "-") == 0)
44433965Sjdp	{
44533965Sjdp	  config.map_file = stdout;
44633965Sjdp	}
44733965Sjdp      else
44833965Sjdp	{
44933965Sjdp	  config.map_file = fopen (config.map_filename, FOPEN_WT);
45033965Sjdp	  if (config.map_file == (FILE *) NULL)
45133965Sjdp	    {
45233965Sjdp	      bfd_set_error (bfd_error_system_call);
45360484Sobrien	      einfo (_("%P%F: cannot open map file %s: %E\n"),
45433965Sjdp		     config.map_filename);
45533965Sjdp	    }
45633965Sjdp	}
45733965Sjdp    }
45833965Sjdp
45933965Sjdp  lang_process ();
46033965Sjdp
46133965Sjdp  /* Print error messages for any missing symbols, for any warning
46277298Sobrien     symbols, and possibly multiple definitions.  */
463130561Sobrien  if (link_info.relocatable)
46433965Sjdp    output_bfd->flags &= ~EXEC_P;
46533965Sjdp  else
46633965Sjdp    output_bfd->flags |= EXEC_P;
46733965Sjdp
46833965Sjdp  ldwrite ();
46933965Sjdp
47033965Sjdp  if (config.map_file != NULL)
47133965Sjdp    lang_map ();
47233965Sjdp  if (command_line.cref)
47333965Sjdp    output_cref (config.map_file != NULL ? config.map_file : stdout);
47433965Sjdp  if (nocrossref_list != NULL)
47533965Sjdp    check_nocrossrefs ();
47633965Sjdp
477218822Sdim  lang_finish ();
478218822Sdim
479130561Sobrien  /* Even if we're producing relocatable output, some non-fatal errors should
48033965Sjdp     be reported in the exit status.  (What non-fatal errors, if any, do we
481130561Sobrien     want to ignore for relocatable output?)  */
482130561Sobrien  if (!config.make_executable && !force_make_executable)
48333965Sjdp    {
484130561Sobrien      if (trace_files)
485130561Sobrien	einfo (_("%P: link errors found, deleting executable `%s'\n"),
486130561Sobrien	       output_filename);
48733965Sjdp
48833965Sjdp      /* The file will be removed by remove_output.  */
48933965Sjdp      xexit (1);
49033965Sjdp    }
49133965Sjdp  else
49233965Sjdp    {
49333965Sjdp      if (! bfd_close (output_bfd))
49460484Sobrien	einfo (_("%F%B: final close failed: %E\n"), output_bfd);
49533965Sjdp
49633965Sjdp      /* If the --force-exe-suffix is enabled, and we're making an
49777298Sobrien	 executable file and it doesn't end in .exe, copy it to one
49877298Sobrien	 which does.  */
499130561Sobrien      if (! link_info.relocatable && command_line.force_exe_suffix)
50033965Sjdp	{
50133965Sjdp	  int len = strlen (output_filename);
502130561Sobrien
50377298Sobrien	  if (len < 4
50433965Sjdp	      || (strcasecmp (output_filename + len - 4, ".exe") != 0
50533965Sjdp		  && strcasecmp (output_filename + len - 4, ".dll") != 0))
50633965Sjdp	    {
50733965Sjdp	      FILE *src;
50833965Sjdp	      FILE *dst;
50933965Sjdp	      const int bsize = 4096;
51033965Sjdp	      char *buf = xmalloc (bsize);
51133965Sjdp	      int l;
51233965Sjdp	      char *dst_name = xmalloc (len + 5);
513130561Sobrien
51433965Sjdp	      strcpy (dst_name, output_filename);
51533965Sjdp	      strcat (dst_name, ".exe");
51633965Sjdp	      src = fopen (output_filename, FOPEN_RB);
51733965Sjdp	      dst = fopen (dst_name, FOPEN_WB);
51833965Sjdp
51933965Sjdp	      if (!src)
520130561Sobrien		einfo (_("%X%P: unable to open for source of copy `%s'\n"),
521130561Sobrien		       output_filename);
52233965Sjdp	      if (!dst)
523130561Sobrien		einfo (_("%X%P: unable to open for destination of copy `%s'\n"),
524130561Sobrien		       dst_name);
52533965Sjdp	      while ((l = fread (buf, 1, bsize, src)) > 0)
52633965Sjdp		{
52733965Sjdp		  int done = fwrite (buf, 1, l, dst);
528130561Sobrien
52933965Sjdp		  if (done != l)
530130561Sobrien		    einfo (_("%P: Error writing file `%s'\n"), dst_name);
53133965Sjdp		}
532130561Sobrien
53333965Sjdp	      fclose (src);
53433965Sjdp	      if (fclose (dst) == EOF)
535130561Sobrien		einfo (_("%P: Error closing file `%s'\n"), dst_name);
53633965Sjdp	      free (dst_name);
53733965Sjdp	      free (buf);
53833965Sjdp	    }
53933965Sjdp	}
54033965Sjdp    }
54133965Sjdp
54233965Sjdp  END_PROGRESS (program_name);
54333965Sjdp
54433965Sjdp  if (config.stats)
54533965Sjdp    {
54633965Sjdp#ifdef HAVE_SBRK
547130561Sobrien      char *lim = sbrk (0);
54833965Sjdp#endif
54933965Sjdp      long run_time = get_run_time () - start_time;
55033965Sjdp
55160484Sobrien      fprintf (stderr, _("%s: total time in link: %ld.%06ld\n"),
55233965Sjdp	       program_name, run_time / 1000000, run_time % 1000000);
55333965Sjdp#ifdef HAVE_SBRK
55460484Sobrien      fprintf (stderr, _("%s: data size %ld\n"), program_name,
55533965Sjdp	       (long) (lim - (char *) &environ));
55633965Sjdp#endif
55733965Sjdp    }
55833965Sjdp
55933965Sjdp  /* Prevent remove_output from doing anything, after a successful link.  */
56033965Sjdp  output_filename = NULL;
56133965Sjdp
56233965Sjdp  xexit (0);
56333965Sjdp  return 0;
56433965Sjdp}
56533965Sjdp
566218822Sdim/* If the configured sysroot is relocatable, try relocating it based on
567218822Sdim   default prefix FROM.  Return the relocated directory if it exists,
568218822Sdim   otherwise return null.  */
569218822Sdim
570218822Sdimstatic char *
571218822Sdimget_relative_sysroot (const char *from ATTRIBUTE_UNUSED)
572218822Sdim{
573218822Sdim#ifdef TARGET_SYSTEM_ROOT_RELOCATABLE
574218822Sdim  char *path;
575218822Sdim  struct stat s;
576218822Sdim
577218822Sdim  path = make_relative_prefix (program_name, from, TARGET_SYSTEM_ROOT);
578218822Sdim  if (path)
579218822Sdim    {
580218822Sdim      if (stat (path, &s) == 0 && S_ISDIR (s.st_mode))
581218822Sdim	return path;
582218822Sdim      free (path);
583218822Sdim    }
584218822Sdim#endif
585218822Sdim  return 0;
586218822Sdim}
587218822Sdim
588218822Sdim/* Return the sysroot directory.  Return "" if no sysroot is being used.  */
589218822Sdim
590218822Sdimstatic const char *
591218822Sdimget_sysroot (int argc, char **argv)
592218822Sdim{
593218822Sdim  int i;
594218822Sdim  const char *path;
595218822Sdim
596218822Sdim  for (i = 1; i < argc; i++)
597218822Sdim    if (CONST_STRNEQ (argv[i], "--sysroot="))
598218822Sdim      return argv[i] + strlen ("--sysroot=");
599218822Sdim
600218822Sdim  path = get_relative_sysroot (BINDIR);
601218822Sdim  if (path)
602218822Sdim    return path;
603218822Sdim
604218822Sdim  path = get_relative_sysroot (TOOLBINDIR);
605218822Sdim  if (path)
606218822Sdim    return path;
607218822Sdim
608218822Sdim  return TARGET_SYSTEM_ROOT;
609218822Sdim}
610218822Sdim
61133965Sjdp/* We need to find any explicitly given emulation in order to initialize the
61233965Sjdp   state that's needed by the lex&yacc argument parser (parse_args).  */
61333965Sjdp
61433965Sjdpstatic char *
615130561Sobrienget_emulation (int argc, char **argv)
61633965Sjdp{
61733965Sjdp  char *emulation;
61833965Sjdp  int i;
61933965Sjdp
62033965Sjdp  emulation = getenv (EMULATION_ENVIRON);
62133965Sjdp  if (emulation == NULL)
62233965Sjdp    emulation = DEFAULT_EMULATION;
62333965Sjdp
62433965Sjdp  for (i = 1; i < argc; i++)
62533965Sjdp    {
626218822Sdim      if (CONST_STRNEQ (argv[i], "-m"))
62733965Sjdp	{
62833965Sjdp	  if (argv[i][2] == '\0')
62933965Sjdp	    {
63033965Sjdp	      /* -m EMUL */
63133965Sjdp	      if (i < argc - 1)
63233965Sjdp		{
63333965Sjdp		  emulation = argv[i + 1];
63433965Sjdp		  i++;
63533965Sjdp		}
63633965Sjdp	      else
637130561Sobrien		einfo (_("%P%F: missing argument to -m\n"));
63833965Sjdp	    }
63933965Sjdp	  else if (strcmp (argv[i], "-mips1") == 0
64033965Sjdp		   || strcmp (argv[i], "-mips2") == 0
64133965Sjdp		   || strcmp (argv[i], "-mips3") == 0
642130561Sobrien		   || strcmp (argv[i], "-mips4") == 0
643130561Sobrien		   || strcmp (argv[i], "-mips5") == 0
64489857Sobrien		   || strcmp (argv[i], "-mips32") == 0
645130561Sobrien		   || strcmp (argv[i], "-mips32r2") == 0
64689857Sobrien		   || strcmp (argv[i], "-mips64") == 0
647130561Sobrien		   || strcmp (argv[i], "-mips64r2") == 0)
64833965Sjdp	    {
64989857Sobrien	      /* FIXME: The arguments -mips1, -mips2, -mips3, etc. are
65033965Sjdp		 passed to the linker by some MIPS compilers.  They
65133965Sjdp		 generally tell the linker to use a slightly different
65233965Sjdp		 library path.  Perhaps someday these should be
65333965Sjdp		 implemented as emulations; until then, we just ignore
65433965Sjdp		 the arguments and hope that nobody ever creates
65533965Sjdp		 emulations named ips1, ips2 or ips3.  */
65633965Sjdp	    }
65733965Sjdp	  else if (strcmp (argv[i], "-m486") == 0)
65833965Sjdp	    {
65933965Sjdp	      /* FIXME: The argument -m486 is passed to the linker on
66033965Sjdp		 some Linux systems.  Hope that nobody creates an
66133965Sjdp		 emulation named 486.  */
66233965Sjdp	    }
66333965Sjdp	  else
66433965Sjdp	    {
66533965Sjdp	      /* -mEMUL */
66633965Sjdp	      emulation = &argv[i][2];
66733965Sjdp	    }
66833965Sjdp	}
66933965Sjdp    }
67033965Sjdp
67133965Sjdp  return emulation;
67233965Sjdp}
67333965Sjdp
67433965Sjdp/* If directory DIR contains an "ldscripts" subdirectory,
675130561Sobrien   add DIR to the library search path and return TRUE,
676130561Sobrien   else return FALSE.  */
67733965Sjdp
678130561Sobrienstatic bfd_boolean
679130561Sobriencheck_for_scripts_dir (char *dir)
68033965Sjdp{
68133965Sjdp  size_t dirlen;
68233965Sjdp  char *buf;
68333965Sjdp  struct stat s;
684130561Sobrien  bfd_boolean res;
68533965Sjdp
68633965Sjdp  dirlen = strlen (dir);
68733965Sjdp  /* sizeof counts the terminating NUL.  */
688130561Sobrien  buf = xmalloc (dirlen + sizeof ("/ldscripts"));
68933965Sjdp  sprintf (buf, "%s/ldscripts", dir);
69033965Sjdp
69133965Sjdp  res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode);
69233965Sjdp  free (buf);
69333965Sjdp  if (res)
694130561Sobrien    ldfile_add_library_path (dir, FALSE);
69533965Sjdp  return res;
69633965Sjdp}
69733965Sjdp
69833965Sjdp/* Set the default directory for finding script files.
69933965Sjdp   Libraries will be searched for here too, but that's ok.
70033965Sjdp   We look for the "ldscripts" directory in:
70133965Sjdp
70233965Sjdp   SCRIPTDIR (passed from Makefile)
703130561Sobrien	     (adjusted according to the current location of the binary)
704130561Sobrien   SCRIPTDIR (passed from Makefile)
70533965Sjdp   the dir where this program is (for using it from the build tree)
706130561Sobrien   the dir where this program is/../lib
707130561Sobrien	     (for installing the tool suite elsewhere).  */
70833965Sjdp
70933965Sjdpstatic void
710130561Sobrienset_scripts_dir (void)
71133965Sjdp{
71233965Sjdp  char *end, *dir;
71333965Sjdp  size_t dirlen;
714130561Sobrien  bfd_boolean found;
71533965Sjdp
716130561Sobrien  dir = make_relative_prefix (program_name, BINDIR, SCRIPTDIR);
717130561Sobrien  if (dir)
718130561Sobrien    {
719130561Sobrien      found = check_for_scripts_dir (dir);
720130561Sobrien      free (dir);
721130561Sobrien      if (found)
722130561Sobrien	return;
723130561Sobrien    }
724130561Sobrien
725130561Sobrien  dir = make_relative_prefix (program_name, TOOLBINDIR, SCRIPTDIR);
726130561Sobrien  if (dir)
727130561Sobrien    {
728130561Sobrien      found = check_for_scripts_dir (dir);
729130561Sobrien      free (dir);
730130561Sobrien      if (found)
731130561Sobrien	return;
732130561Sobrien    }
733130561Sobrien
73433965Sjdp  if (check_for_scripts_dir (SCRIPTDIR))
73577298Sobrien    /* We've been installed normally.  */
73677298Sobrien    return;
73733965Sjdp
73833965Sjdp  /* Look for "ldscripts" in the dir where our binary is.  */
73933965Sjdp  end = strrchr (program_name, '/');
74061843Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM
74161843Sobrien  {
74261843Sobrien    /* We could have \foo\bar, or /foo\bar.  */
74361843Sobrien    char *bslash = strrchr (program_name, '\\');
744130561Sobrien
74577298Sobrien    if (end == NULL || (bslash != NULL && bslash > end))
74661843Sobrien      end = bslash;
74761843Sobrien  }
74861843Sobrien#endif
74933965Sjdp
75033965Sjdp  if (end == NULL)
751130561Sobrien    /* Don't look for ldscripts in the current directory.  There is
752130561Sobrien       too much potential for confusion.  */
753130561Sobrien    return;
75433965Sjdp
75533965Sjdp  dirlen = end - program_name;
75633965Sjdp  /* Make a copy of program_name in dir.
75733965Sjdp     Leave room for later "/../lib".  */
758130561Sobrien  dir = xmalloc (dirlen + 8);
75933965Sjdp  strncpy (dir, program_name, dirlen);
76033965Sjdp  dir[dirlen] = '\0';
76133965Sjdp
76233965Sjdp  if (check_for_scripts_dir (dir))
763130561Sobrien    {
764130561Sobrien      free (dir);
765130561Sobrien      return;
766130561Sobrien    }
76733965Sjdp
76833965Sjdp  /* Look for "ldscripts" in <the dir where our binary is>/../lib.  */
76933965Sjdp  strcpy (dir + dirlen, "/../lib");
770130561Sobrien  check_for_scripts_dir (dir);
77177298Sobrien  free (dir);
77233965Sjdp}
77333965Sjdp
77433965Sjdpvoid
775130561Sobrienadd_ysym (const char *name)
77633965Sjdp{
777130561Sobrien  if (link_info.notice_hash == NULL)
77833965Sjdp    {
779130561Sobrien      link_info.notice_hash = xmalloc (sizeof (struct bfd_hash_table));
780218822Sdim      if (!bfd_hash_table_init_n (link_info.notice_hash,
781218822Sdim				  bfd_hash_newfunc,
782218822Sdim				  sizeof (struct bfd_hash_entry),
783218822Sdim				  61))
78460484Sobrien	einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
78577298Sobrien    }
78633965Sjdp
787130561Sobrien  if (bfd_hash_lookup (link_info.notice_hash, name, TRUE, TRUE) == NULL)
78860484Sobrien    einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));
78933965Sjdp}
79033965Sjdp
79133965Sjdp/* Record a symbol to be wrapped, from the --wrap option.  */
79233965Sjdp
79333965Sjdpvoid
794130561Sobrienadd_wrap (const char *name)
79533965Sjdp{
79633965Sjdp  if (link_info.wrap_hash == NULL)
79733965Sjdp    {
798130561Sobrien      link_info.wrap_hash = xmalloc (sizeof (struct bfd_hash_table));
799218822Sdim      if (!bfd_hash_table_init_n (link_info.wrap_hash,
800218822Sdim				  bfd_hash_newfunc,
801218822Sdim				  sizeof (struct bfd_hash_entry),
802218822Sdim				  61))
80360484Sobrien	einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
80433965Sjdp    }
805130561Sobrien
806130561Sobrien  if (bfd_hash_lookup (link_info.wrap_hash, name, TRUE, TRUE) == NULL)
80760484Sobrien    einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));
80833965Sjdp}
80933965Sjdp
81033965Sjdp/* Handle the -retain-symbols-file option.  */
81133965Sjdp
81233965Sjdpvoid
813130561Sobrienadd_keepsyms_file (const char *filename)
81433965Sjdp{
81533965Sjdp  FILE *file;
81633965Sjdp  char *buf;
81733965Sjdp  size_t bufsize;
81833965Sjdp  int c;
81933965Sjdp
82033965Sjdp  if (link_info.strip == strip_some)
82160484Sobrien    einfo (_("%X%P: error: duplicate retain-symbols-file\n"));
82233965Sjdp
82333965Sjdp  file = fopen (filename, "r");
824130561Sobrien  if (file == NULL)
82533965Sjdp    {
82633965Sjdp      bfd_set_error (bfd_error_system_call);
82733965Sjdp      einfo ("%X%P: %s: %E\n", filename);
82833965Sjdp      return;
82933965Sjdp    }
83033965Sjdp
831130561Sobrien  link_info.keep_hash = xmalloc (sizeof (struct bfd_hash_table));
832218822Sdim  if (!bfd_hash_table_init (link_info.keep_hash, bfd_hash_newfunc,
833218822Sdim			    sizeof (struct bfd_hash_entry)))
83460484Sobrien    einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
83533965Sjdp
83633965Sjdp  bufsize = 100;
837130561Sobrien  buf = xmalloc (bufsize);
83833965Sjdp
83933965Sjdp  c = getc (file);
84033965Sjdp  while (c != EOF)
84133965Sjdp    {
84289857Sobrien      while (ISSPACE (c))
84333965Sjdp	c = getc (file);
84433965Sjdp
84533965Sjdp      if (c != EOF)
84633965Sjdp	{
84733965Sjdp	  size_t len = 0;
84833965Sjdp
84989857Sobrien	  while (! ISSPACE (c) && c != EOF)
85033965Sjdp	    {
85133965Sjdp	      buf[len] = c;
85233965Sjdp	      ++len;
85333965Sjdp	      if (len >= bufsize)
85433965Sjdp		{
85533965Sjdp		  bufsize *= 2;
85633965Sjdp		  buf = xrealloc (buf, bufsize);
85733965Sjdp		}
85833965Sjdp	      c = getc (file);
85933965Sjdp	    }
86033965Sjdp
86133965Sjdp	  buf[len] = '\0';
86233965Sjdp
863130561Sobrien	  if (bfd_hash_lookup (link_info.keep_hash, buf, TRUE, TRUE) == NULL)
86460484Sobrien	    einfo (_("%P%F: bfd_hash_lookup for insertion failed: %E\n"));
86533965Sjdp	}
86633965Sjdp    }
86733965Sjdp
86833965Sjdp  if (link_info.strip != strip_none)
86960484Sobrien    einfo (_("%P: `-retain-symbols-file' overrides `-s' and `-S'\n"));
87033965Sjdp
871130561Sobrien  free (buf);
87233965Sjdp  link_info.strip = strip_some;
87333965Sjdp}
87433965Sjdp
87533965Sjdp/* Callbacks from the BFD linker routines.  */
87633965Sjdp
87733965Sjdp/* This is called when BFD has decided to include an archive member in
87833965Sjdp   a link.  */
87933965Sjdp
880130561Sobrienstatic bfd_boolean
881218822Sdimadd_archive_element (struct bfd_link_info *info,
882130561Sobrien		     bfd *abfd,
883130561Sobrien		     const char *name)
88433965Sjdp{
88533965Sjdp  lang_input_statement_type *input;
88633965Sjdp
887130561Sobrien  input = xmalloc (sizeof (lang_input_statement_type));
88833965Sjdp  input->filename = abfd->filename;
88933965Sjdp  input->local_sym_name = abfd->filename;
89033965Sjdp  input->the_bfd = abfd;
89133965Sjdp  input->asymbols = NULL;
89233965Sjdp  input->next = NULL;
893130561Sobrien  input->just_syms_flag = FALSE;
894130561Sobrien  input->loaded = FALSE;
895130561Sobrien  input->search_dirs_flag = FALSE;
89633965Sjdp
89733965Sjdp  /* FIXME: The following fields are not set: header.next,
89833965Sjdp     header.type, closed, passive_position, symbol_count,
89933965Sjdp     next_real_file, is_archive, target, real.  This bit of code is
90033965Sjdp     from the old decode_library_subfile function.  I don't know
90133965Sjdp     whether any of those fields matters.  */
90233965Sjdp
90333965Sjdp  ldlang_add_file (input);
90433965Sjdp
905130561Sobrien  if (config.map_file != NULL)
90633965Sjdp    {
907130561Sobrien      static bfd_boolean header_printed;
90833965Sjdp      struct bfd_link_hash_entry *h;
90933965Sjdp      bfd *from;
91033965Sjdp      int len;
91133965Sjdp
912218822Sdim      h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
91333965Sjdp
91433965Sjdp      if (h == NULL)
91533965Sjdp	from = NULL;
91633965Sjdp      else
91733965Sjdp	{
91833965Sjdp	  switch (h->type)
91933965Sjdp	    {
92033965Sjdp	    default:
92133965Sjdp	      from = NULL;
92233965Sjdp	      break;
92333965Sjdp
92433965Sjdp	    case bfd_link_hash_defined:
92533965Sjdp	    case bfd_link_hash_defweak:
92633965Sjdp	      from = h->u.def.section->owner;
92733965Sjdp	      break;
92833965Sjdp
92933965Sjdp	    case bfd_link_hash_undefined:
93033965Sjdp	    case bfd_link_hash_undefweak:
93133965Sjdp	      from = h->u.undef.abfd;
93233965Sjdp	      break;
93333965Sjdp
93433965Sjdp	    case bfd_link_hash_common:
93533965Sjdp	      from = h->u.c.p->section->owner;
93633965Sjdp	      break;
93733965Sjdp	    }
93833965Sjdp	}
93933965Sjdp
94033965Sjdp      if (! header_printed)
94133965Sjdp	{
94233965Sjdp	  char buf[100];
94333965Sjdp
94489857Sobrien	  sprintf (buf, _("Archive member included because of file (symbol)\n\n"));
94533965Sjdp	  minfo ("%s", buf);
946130561Sobrien	  header_printed = TRUE;
94733965Sjdp	}
94833965Sjdp
94933965Sjdp      if (bfd_my_archive (abfd) == NULL)
95033965Sjdp	{
95133965Sjdp	  minfo ("%s", bfd_get_filename (abfd));
95233965Sjdp	  len = strlen (bfd_get_filename (abfd));
95333965Sjdp	}
95433965Sjdp      else
95533965Sjdp	{
95633965Sjdp	  minfo ("%s(%s)", bfd_get_filename (bfd_my_archive (abfd)),
95733965Sjdp		 bfd_get_filename (abfd));
95833965Sjdp	  len = (strlen (bfd_get_filename (bfd_my_archive (abfd)))
95933965Sjdp		 + strlen (bfd_get_filename (abfd))
96033965Sjdp		 + 2);
96133965Sjdp	}
96233965Sjdp
96333965Sjdp      if (len >= 29)
96433965Sjdp	{
96533965Sjdp	  print_nl ();
96633965Sjdp	  len = 0;
96733965Sjdp	}
96833965Sjdp      while (len < 30)
96933965Sjdp	{
97033965Sjdp	  print_space ();
97133965Sjdp	  ++len;
97233965Sjdp	}
97333965Sjdp
97433965Sjdp      if (from != NULL)
97533965Sjdp	minfo ("%B ", from);
97633965Sjdp      if (h != NULL)
97733965Sjdp	minfo ("(%T)\n", h->root.string);
97833965Sjdp      else
97933965Sjdp	minfo ("(%s)\n", name);
98033965Sjdp    }
98133965Sjdp
98233965Sjdp  if (trace_files || trace_file_tries)
98333965Sjdp    info_msg ("%I\n", input);
98433965Sjdp
985130561Sobrien  return TRUE;
98633965Sjdp}
98733965Sjdp
98833965Sjdp/* This is called when BFD has discovered a symbol which is defined
98933965Sjdp   multiple times.  */
99033965Sjdp
991130561Sobrienstatic bfd_boolean
992130561Sobrienmultiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED,
993130561Sobrien		     const char *name,
994130561Sobrien		     bfd *obfd,
995130561Sobrien		     asection *osec,
996130561Sobrien		     bfd_vma oval,
997130561Sobrien		     bfd *nbfd,
998130561Sobrien		     asection *nsec,
999130561Sobrien		     bfd_vma nval)
100033965Sjdp{
100133965Sjdp  /* If either section has the output_section field set to
100233965Sjdp     bfd_abs_section_ptr, it means that the section is being
100333965Sjdp     discarded, and this is not really a multiple definition at all.
100433965Sjdp     FIXME: It would be cleaner to somehow ignore symbols defined in
100533965Sjdp     sections which are being discarded.  */
100633965Sjdp  if ((osec->output_section != NULL
100733965Sjdp       && ! bfd_is_abs_section (osec)
100833965Sjdp       && bfd_is_abs_section (osec->output_section))
100933965Sjdp      || (nsec->output_section != NULL
101033965Sjdp	  && ! bfd_is_abs_section (nsec)
101133965Sjdp	  && bfd_is_abs_section (nsec->output_section)))
1012130561Sobrien    return TRUE;
101333965Sjdp
101460484Sobrien  einfo (_("%X%C: multiple definition of `%T'\n"),
101533965Sjdp	 nbfd, nsec, nval, name);
1016130561Sobrien  if (obfd != NULL)
101760484Sobrien    einfo (_("%D: first defined here\n"), obfd, osec, oval);
101877298Sobrien
101977298Sobrien  if (command_line.relax)
102077298Sobrien    {
102177298Sobrien      einfo (_("%P: Disabling relaxation: it will not work with multiple definitions\n"));
102277298Sobrien      command_line.relax = 0;
102377298Sobrien    }
102477298Sobrien
1025130561Sobrien  return TRUE;
102633965Sjdp}
102733965Sjdp
102833965Sjdp/* This is called when there is a definition of a common symbol, or
102933965Sjdp   when a common symbol is found for a symbol that is already defined,
103033965Sjdp   or when two common symbols are found.  We only do something if
103133965Sjdp   -warn-common was used.  */
103233965Sjdp
1033130561Sobrienstatic bfd_boolean
1034130561Sobrienmultiple_common (struct bfd_link_info *info ATTRIBUTE_UNUSED,
1035130561Sobrien		 const char *name,
1036130561Sobrien		 bfd *obfd,
1037130561Sobrien		 enum bfd_link_hash_type otype,
1038130561Sobrien		 bfd_vma osize,
1039130561Sobrien		 bfd *nbfd,
1040130561Sobrien		 enum bfd_link_hash_type ntype,
1041130561Sobrien		 bfd_vma nsize)
104233965Sjdp{
104333965Sjdp  if (! config.warn_common)
1044130561Sobrien    return TRUE;
104533965Sjdp
104633965Sjdp  if (ntype == bfd_link_hash_defined
104733965Sjdp      || ntype == bfd_link_hash_defweak
104833965Sjdp      || ntype == bfd_link_hash_indirect)
104933965Sjdp    {
105033965Sjdp      ASSERT (otype == bfd_link_hash_common);
105160484Sobrien      einfo (_("%B: warning: definition of `%T' overriding common\n"),
105233965Sjdp	     nbfd, name);
105333965Sjdp      if (obfd != NULL)
105460484Sobrien	einfo (_("%B: warning: common is here\n"), obfd);
105533965Sjdp    }
105633965Sjdp  else if (otype == bfd_link_hash_defined
105733965Sjdp	   || otype == bfd_link_hash_defweak
105833965Sjdp	   || otype == bfd_link_hash_indirect)
105933965Sjdp    {
106033965Sjdp      ASSERT (ntype == bfd_link_hash_common);
106160484Sobrien      einfo (_("%B: warning: common of `%T' overridden by definition\n"),
106233965Sjdp	     nbfd, name);
106333965Sjdp      if (obfd != NULL)
106460484Sobrien	einfo (_("%B: warning: defined here\n"), obfd);
106533965Sjdp    }
106633965Sjdp  else
106733965Sjdp    {
106833965Sjdp      ASSERT (otype == bfd_link_hash_common && ntype == bfd_link_hash_common);
106933965Sjdp      if (osize > nsize)
107033965Sjdp	{
107160484Sobrien	  einfo (_("%B: warning: common of `%T' overridden by larger common\n"),
107233965Sjdp		 nbfd, name);
107333965Sjdp	  if (obfd != NULL)
107460484Sobrien	    einfo (_("%B: warning: larger common is here\n"), obfd);
107533965Sjdp	}
107633965Sjdp      else if (nsize > osize)
107733965Sjdp	{
107860484Sobrien	  einfo (_("%B: warning: common of `%T' overriding smaller common\n"),
107933965Sjdp		 nbfd, name);
108033965Sjdp	  if (obfd != NULL)
108160484Sobrien	    einfo (_("%B: warning: smaller common is here\n"), obfd);
108233965Sjdp	}
108333965Sjdp      else
108433965Sjdp	{
108560484Sobrien	  einfo (_("%B: warning: multiple common of `%T'\n"), nbfd, name);
108633965Sjdp	  if (obfd != NULL)
108760484Sobrien	    einfo (_("%B: warning: previous common is here\n"), obfd);
108833965Sjdp	}
108933965Sjdp    }
109033965Sjdp
1091130561Sobrien  return TRUE;
109233965Sjdp}
109333965Sjdp
109433965Sjdp/* This is called when BFD has discovered a set element.  H is the
109533965Sjdp   entry in the linker hash table for the set.  SECTION and VALUE
109633965Sjdp   represent a value which should be added to the set.  */
109733965Sjdp
1098130561Sobrienstatic bfd_boolean
1099130561Sobrienadd_to_set (struct bfd_link_info *info ATTRIBUTE_UNUSED,
1100130561Sobrien	    struct bfd_link_hash_entry *h,
1101130561Sobrien	    bfd_reloc_code_real_type reloc,
1102130561Sobrien	    bfd *abfd,
1103130561Sobrien	    asection *section,
1104130561Sobrien	    bfd_vma value)
110533965Sjdp{
110633965Sjdp  if (config.warn_constructors)
110760484Sobrien    einfo (_("%P: warning: global constructor %s used\n"),
110833965Sjdp	   h->root.string);
110933965Sjdp
111033965Sjdp  if (! config.build_constructors)
1111130561Sobrien    return TRUE;
111233965Sjdp
1113130561Sobrien  ldctor_add_set_entry (h, reloc, NULL, section, value);
111433965Sjdp
111533965Sjdp  if (h->type == bfd_link_hash_new)
111633965Sjdp    {
111733965Sjdp      h->type = bfd_link_hash_undefined;
111833965Sjdp      h->u.undef.abfd = abfd;
111933965Sjdp      /* We don't call bfd_link_add_undef to add this to the list of
112033965Sjdp	 undefined symbols because we are going to define it
112133965Sjdp	 ourselves.  */
112233965Sjdp    }
112333965Sjdp
1124130561Sobrien  return TRUE;
112533965Sjdp}
112633965Sjdp
112733965Sjdp/* This is called when BFD has discovered a constructor.  This is only
112833965Sjdp   called for some object file formats--those which do not handle
112933965Sjdp   constructors in some more clever fashion.  This is similar to
113033965Sjdp   adding an element to a set, but less general.  */
113133965Sjdp
1132130561Sobrienstatic bfd_boolean
1133130561Sobrienconstructor_callback (struct bfd_link_info *info,
1134130561Sobrien		      bfd_boolean constructor,
1135130561Sobrien		      const char *name,
1136130561Sobrien		      bfd *abfd,
1137130561Sobrien		      asection *section,
1138130561Sobrien		      bfd_vma value)
113933965Sjdp{
114033965Sjdp  char *s;
114133965Sjdp  struct bfd_link_hash_entry *h;
114233965Sjdp  char set_name[1 + sizeof "__CTOR_LIST__"];
114333965Sjdp
114433965Sjdp  if (config.warn_constructors)
114560484Sobrien    einfo (_("%P: warning: global constructor %s used\n"), name);
114633965Sjdp
114733965Sjdp  if (! config.build_constructors)
1148130561Sobrien    return TRUE;
114933965Sjdp
115033965Sjdp  /* Ensure that BFD_RELOC_CTOR exists now, so that we can give a
115133965Sjdp     useful error message.  */
115233965Sjdp  if (bfd_reloc_type_lookup (output_bfd, BFD_RELOC_CTOR) == NULL
1153218822Sdim      && (info->relocatable
115433965Sjdp	  || bfd_reloc_type_lookup (abfd, BFD_RELOC_CTOR) == NULL))
115560484Sobrien    einfo (_("%P%F: BFD backend error: BFD_RELOC_CTOR unsupported\n"));
115633965Sjdp
115733965Sjdp  s = set_name;
115833965Sjdp  if (bfd_get_symbol_leading_char (abfd) != '\0')
115933965Sjdp    *s++ = bfd_get_symbol_leading_char (abfd);
116033965Sjdp  if (constructor)
116133965Sjdp    strcpy (s, "__CTOR_LIST__");
116233965Sjdp  else
116333965Sjdp    strcpy (s, "__DTOR_LIST__");
116433965Sjdp
1165130561Sobrien  h = bfd_link_hash_lookup (info->hash, set_name, TRUE, TRUE, TRUE);
116633965Sjdp  if (h == (struct bfd_link_hash_entry *) NULL)
116760484Sobrien    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
116833965Sjdp  if (h->type == bfd_link_hash_new)
116933965Sjdp    {
117033965Sjdp      h->type = bfd_link_hash_undefined;
117133965Sjdp      h->u.undef.abfd = abfd;
117233965Sjdp      /* We don't call bfd_link_add_undef to add this to the list of
117333965Sjdp	 undefined symbols because we are going to define it
117433965Sjdp	 ourselves.  */
117533965Sjdp    }
117633965Sjdp
117733965Sjdp  ldctor_add_set_entry (h, BFD_RELOC_CTOR, name, section, value);
1178130561Sobrien  return TRUE;
117933965Sjdp}
118033965Sjdp
118133965Sjdp/* A structure used by warning_callback to pass information through
118233965Sjdp   bfd_map_over_sections.  */
118333965Sjdp
1184130561Sobrienstruct warning_callback_info
1185130561Sobrien{
1186130561Sobrien  bfd_boolean found;
118733965Sjdp  const char *warning;
118833965Sjdp  const char *symbol;
118933965Sjdp  asymbol **asymbols;
119033965Sjdp};
119133965Sjdp
119233965Sjdp/* This is called when there is a reference to a warning symbol.  */
119333965Sjdp
1194130561Sobrienstatic bfd_boolean
1195130561Sobrienwarning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED,
1196130561Sobrien		  const char *warning,
1197130561Sobrien		  const char *symbol,
1198130561Sobrien		  bfd *abfd,
1199130561Sobrien		  asection *section,
1200130561Sobrien		  bfd_vma address)
120133965Sjdp{
120233965Sjdp  /* This is a hack to support warn_multiple_gp.  FIXME: This should
120333965Sjdp     have a cleaner interface, but what?  */
120433965Sjdp  if (! config.warn_multiple_gp
120533965Sjdp      && strcmp (warning, "using multiple gp values") == 0)
1206130561Sobrien    return TRUE;
120733965Sjdp
120833965Sjdp  if (section != NULL)
1209218822Sdim    einfo ("%C: %s%s\n", abfd, section, address, _("warning: "), warning);
121033965Sjdp  else if (abfd == NULL)
1211218822Sdim    einfo ("%P: %s%s\n", _("warning: "), warning);
121233965Sjdp  else if (symbol == NULL)
1213218822Sdim    einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
121433965Sjdp  else
121533965Sjdp    {
121633965Sjdp      lang_input_statement_type *entry;
121733965Sjdp      asymbol **asymbols;
121833965Sjdp      struct warning_callback_info info;
121933965Sjdp
122033965Sjdp      /* Look through the relocs to see if we can find a plausible
122133965Sjdp	 address.  */
122233965Sjdp      entry = (lang_input_statement_type *) abfd->usrdata;
122333965Sjdp      if (entry != NULL && entry->asymbols != NULL)
122433965Sjdp	asymbols = entry->asymbols;
122533965Sjdp      else
122633965Sjdp	{
122733965Sjdp	  long symsize;
122833965Sjdp	  long symbol_count;
122933965Sjdp
123033965Sjdp	  symsize = bfd_get_symtab_upper_bound (abfd);
123133965Sjdp	  if (symsize < 0)
123260484Sobrien	    einfo (_("%B%F: could not read symbols: %E\n"), abfd);
1233130561Sobrien	  asymbols = xmalloc (symsize);
123433965Sjdp	  symbol_count = bfd_canonicalize_symtab (abfd, asymbols);
123533965Sjdp	  if (symbol_count < 0)
123660484Sobrien	    einfo (_("%B%F: could not read symbols: %E\n"), abfd);
123733965Sjdp	  if (entry != NULL)
123833965Sjdp	    {
123933965Sjdp	      entry->asymbols = asymbols;
124033965Sjdp	      entry->symbol_count = symbol_count;
124133965Sjdp	    }
124233965Sjdp	}
124333965Sjdp
1244130561Sobrien      info.found = FALSE;
124533965Sjdp      info.warning = warning;
124633965Sjdp      info.symbol = symbol;
124733965Sjdp      info.asymbols = asymbols;
1248130561Sobrien      bfd_map_over_sections (abfd, warning_find_reloc, &info);
124933965Sjdp
125033965Sjdp      if (! info.found)
1251218822Sdim	einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
125233965Sjdp
125333965Sjdp      if (entry == NULL)
125433965Sjdp	free (asymbols);
125533965Sjdp    }
125633965Sjdp
1257130561Sobrien  return TRUE;
125833965Sjdp}
125933965Sjdp
126033965Sjdp/* This is called by warning_callback for each section.  It checks the
126133965Sjdp   relocs of the section to see if it can find a reference to the
126233965Sjdp   symbol which triggered the warning.  If it can, it uses the reloc
126333965Sjdp   to give an error message with a file and line number.  */
126433965Sjdp
126533965Sjdpstatic void
1266130561Sobrienwarning_find_reloc (bfd *abfd, asection *sec, void *iarg)
126733965Sjdp{
1268130561Sobrien  struct warning_callback_info *info = iarg;
126933965Sjdp  long relsize;
127033965Sjdp  arelent **relpp;
127133965Sjdp  long relcount;
127233965Sjdp  arelent **p, **pend;
127333965Sjdp
127433965Sjdp  if (info->found)
127533965Sjdp    return;
127633965Sjdp
127733965Sjdp  relsize = bfd_get_reloc_upper_bound (abfd, sec);
127833965Sjdp  if (relsize < 0)
127960484Sobrien    einfo (_("%B%F: could not read relocs: %E\n"), abfd);
128033965Sjdp  if (relsize == 0)
128133965Sjdp    return;
128233965Sjdp
1283130561Sobrien  relpp = xmalloc (relsize);
128433965Sjdp  relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
128533965Sjdp  if (relcount < 0)
128660484Sobrien    einfo (_("%B%F: could not read relocs: %E\n"), abfd);
128733965Sjdp
128833965Sjdp  p = relpp;
128933965Sjdp  pend = p + relcount;
129033965Sjdp  for (; p < pend && *p != NULL; p++)
129133965Sjdp    {
129233965Sjdp      arelent *q = *p;
129333965Sjdp
129433965Sjdp      if (q->sym_ptr_ptr != NULL
129533965Sjdp	  && *q->sym_ptr_ptr != NULL
129633965Sjdp	  && strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), info->symbol) == 0)
129733965Sjdp	{
129833965Sjdp	  /* We found a reloc for the symbol we are looking for.  */
1299218822Sdim	  einfo ("%C: %s%s\n", abfd, sec, q->address, _("warning: "),
1300218822Sdim		 info->warning);
1301130561Sobrien	  info->found = TRUE;
130233965Sjdp	  break;
130333965Sjdp	}
130433965Sjdp    }
130533965Sjdp
130633965Sjdp  free (relpp);
130733965Sjdp}
130833965Sjdp
130933965Sjdp/* This is called when an undefined symbol is found.  */
131033965Sjdp
1311130561Sobrienstatic bfd_boolean
1312130561Sobrienundefined_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED,
1313130561Sobrien		  const char *name,
1314130561Sobrien		  bfd *abfd,
1315130561Sobrien		  asection *section,
1316130561Sobrien		  bfd_vma address,
1317130561Sobrien		  bfd_boolean error)
131833965Sjdp{
131933965Sjdp  static char *error_name;
132033965Sjdp  static unsigned int error_count;
132133965Sjdp
132233965Sjdp#define MAX_ERRORS_IN_A_ROW 5
132333965Sjdp
132433965Sjdp  if (config.warn_once)
132533965Sjdp    {
132633965Sjdp      static struct bfd_hash_table *hash;
132733965Sjdp
132833965Sjdp      /* Only warn once about a particular undefined symbol.  */
132933965Sjdp      if (hash == NULL)
133033965Sjdp	{
1331130561Sobrien	  hash = xmalloc (sizeof (struct bfd_hash_table));
1332218822Sdim	  if (!bfd_hash_table_init (hash, bfd_hash_newfunc,
1333218822Sdim				    sizeof (struct bfd_hash_entry)))
133460484Sobrien	    einfo (_("%F%P: bfd_hash_table_init failed: %E\n"));
133533965Sjdp	}
133633965Sjdp
1337130561Sobrien      if (bfd_hash_lookup (hash, name, FALSE, FALSE) != NULL)
1338130561Sobrien	return TRUE;
133933965Sjdp
1340130561Sobrien      if (bfd_hash_lookup (hash, name, TRUE, TRUE) == NULL)
134160484Sobrien	einfo (_("%F%P: bfd_hash_lookup failed: %E\n"));
134233965Sjdp    }
134333965Sjdp
134433965Sjdp  /* We never print more than a reasonable number of errors in a row
134533965Sjdp     for a single symbol.  */
1346130561Sobrien  if (error_name != NULL
134733965Sjdp      && strcmp (name, error_name) == 0)
134833965Sjdp    ++error_count;
134933965Sjdp  else
135033965Sjdp    {
135133965Sjdp      error_count = 0;
1352130561Sobrien      if (error_name != NULL)
135333965Sjdp	free (error_name);
135478828Sobrien      error_name = xstrdup (name);
135533965Sjdp    }
135633965Sjdp
135733965Sjdp  if (section != NULL)
135833965Sjdp    {
135933965Sjdp      if (error_count < MAX_ERRORS_IN_A_ROW)
136060484Sobrien	{
1361130561Sobrien	  if (error)
1362130561Sobrien	    einfo (_("%X%C: undefined reference to `%T'\n"),
1363130561Sobrien		   abfd, section, address, name);
1364130561Sobrien	  else
1365130561Sobrien	    einfo (_("%C: warning: undefined reference to `%T'\n"),
1366130561Sobrien		   abfd, section, address, name);
136760484Sobrien	}
136833965Sjdp      else if (error_count == MAX_ERRORS_IN_A_ROW)
1369130561Sobrien	{
1370130561Sobrien	  if (error)
1371130561Sobrien	    einfo (_("%X%D: more undefined references to `%T' follow\n"),
1372130561Sobrien		   abfd, section, address, name);
1373130561Sobrien	  else
1374130561Sobrien	    einfo (_("%D: warning: more undefined references to `%T' follow\n"),
1375130561Sobrien		   abfd, section, address, name);
1376130561Sobrien	}
1377130561Sobrien      else if (error)
1378130561Sobrien	einfo ("%X");
137933965Sjdp    }
138033965Sjdp  else
138133965Sjdp    {
138233965Sjdp      if (error_count < MAX_ERRORS_IN_A_ROW)
138360484Sobrien	{
1384130561Sobrien	  if (error)
1385130561Sobrien	    einfo (_("%X%B: undefined reference to `%T'\n"),
1386130561Sobrien		   abfd, name);
1387130561Sobrien	  else
1388130561Sobrien	    einfo (_("%B: warning: undefined reference to `%T'\n"),
1389130561Sobrien		   abfd, name);
139060484Sobrien	}
139133965Sjdp      else if (error_count == MAX_ERRORS_IN_A_ROW)
1392130561Sobrien	{
1393130561Sobrien	  if (error)
1394130561Sobrien	    einfo (_("%X%B: more undefined references to `%T' follow\n"),
1395130561Sobrien		   abfd, name);
1396130561Sobrien	  else
1397130561Sobrien	    einfo (_("%B: warning: more undefined references to `%T' follow\n"),
1398130561Sobrien		   abfd, name);
1399130561Sobrien	}
1400130561Sobrien      else if (error)
1401130561Sobrien	einfo ("%X");
140233965Sjdp    }
140333965Sjdp
1404130561Sobrien  return TRUE;
140533965Sjdp}
140633965Sjdp
1407130561Sobrien/* Counter to limit the number of relocation overflow error messages
1408130561Sobrien   to print.  Errors are printed as it is decremented.  When it's
1409130561Sobrien   called and the counter is zero, a final message is printed
1410130561Sobrien   indicating more relocations were omitted.  When it gets to -1, no
1411130561Sobrien   such errors are printed.  If it's initially set to a value less
1412130561Sobrien   than -1, all such errors will be printed (--verbose does this).  */
1413130561Sobrien
1414130561Sobrienint overflow_cutoff_limit = 10;
1415130561Sobrien
141633965Sjdp/* This is called when a reloc overflows.  */
141733965Sjdp
1418130561Sobrienstatic bfd_boolean
1419130561Sobrienreloc_overflow (struct bfd_link_info *info ATTRIBUTE_UNUSED,
1420218822Sdim		struct bfd_link_hash_entry *entry,
1421130561Sobrien		const char *name,
1422130561Sobrien		const char *reloc_name,
1423130561Sobrien		bfd_vma addend,
1424130561Sobrien		bfd *abfd,
1425130561Sobrien		asection *section,
1426130561Sobrien		bfd_vma address)
142733965Sjdp{
1428130561Sobrien  if (overflow_cutoff_limit == -1)
1429130561Sobrien    return TRUE;
1430130561Sobrien
1431218822Sdim  einfo ("%X%C:", abfd, section, address);
1432130561Sobrien
1433130561Sobrien  if (overflow_cutoff_limit >= 0
1434130561Sobrien      && overflow_cutoff_limit-- == 0)
1435130561Sobrien    {
1436130561Sobrien      einfo (_(" additional relocation overflows omitted from the output\n"));
1437130561Sobrien      return TRUE;
1438130561Sobrien    }
1439130561Sobrien
1440218822Sdim  if (entry)
1441218822Sdim    {
1442218822Sdim      while (entry->type == bfd_link_hash_indirect
1443218822Sdim	     || entry->type == bfd_link_hash_warning)
1444218822Sdim	entry = entry->u.i.link;
1445218822Sdim      switch (entry->type)
1446218822Sdim	{
1447218822Sdim	case bfd_link_hash_undefined:
1448218822Sdim	case bfd_link_hash_undefweak:
1449218822Sdim	  einfo (_(" relocation truncated to fit: %s against undefined symbol `%T'"),
1450218822Sdim		 reloc_name, entry->root.string);
1451218822Sdim	  break;
1452218822Sdim	case bfd_link_hash_defined:
1453218822Sdim	case bfd_link_hash_defweak:
1454218822Sdim	  einfo (_(" relocation truncated to fit: %s against symbol `%T' defined in %A section in %B"),
1455218822Sdim		 reloc_name, entry->root.string,
1456218822Sdim		 entry->u.def.section,
1457218822Sdim		 entry->u.def.section == bfd_abs_section_ptr
1458218822Sdim		 ? output_bfd : entry->u.def.section->owner);
1459218822Sdim	  break;
1460218822Sdim	default:
1461218822Sdim	  abort ();
1462218822Sdim	  break;
1463218822Sdim	}
1464218822Sdim    }
1465218822Sdim  else
1466218822Sdim    einfo (_(" relocation truncated to fit: %s against `%T'"),
1467218822Sdim	   reloc_name, name);
146833965Sjdp  if (addend != 0)
146933965Sjdp    einfo ("+%v", addend);
147033965Sjdp  einfo ("\n");
1471130561Sobrien  return TRUE;
147233965Sjdp}
147333965Sjdp
147433965Sjdp/* This is called when a dangerous relocation is made.  */
147533965Sjdp
1476130561Sobrienstatic bfd_boolean
1477130561Sobrienreloc_dangerous (struct bfd_link_info *info ATTRIBUTE_UNUSED,
1478130561Sobrien		 const char *message,
1479130561Sobrien		 bfd *abfd,
1480130561Sobrien		 asection *section,
1481130561Sobrien		 bfd_vma address)
148233965Sjdp{
1483218822Sdim  einfo (_("%X%C: dangerous relocation: %s\n"),
1484218822Sdim	 abfd, section, address, message);
1485130561Sobrien  return TRUE;
148633965Sjdp}
148733965Sjdp
148833965Sjdp/* This is called when a reloc is being generated attached to a symbol
148933965Sjdp   that is not being output.  */
149033965Sjdp
1491130561Sobrienstatic bfd_boolean
1492130561Sobrienunattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED,
1493130561Sobrien		  const char *name,
1494130561Sobrien		  bfd *abfd,
1495130561Sobrien		  asection *section,
1496130561Sobrien		  bfd_vma address)
149733965Sjdp{
1498218822Sdim  einfo (_("%X%C: reloc refers to symbol `%T' which is not being output\n"),
1499218822Sdim	 abfd, section, address, name);
1500130561Sobrien  return TRUE;
150133965Sjdp}
150233965Sjdp
150333965Sjdp/* This is called if link_info.notice_all is set, or when a symbol in
150433965Sjdp   link_info.notice_hash is found.  Symbols are put in notice_hash
150533965Sjdp   using the -y option.  */
150633965Sjdp
1507130561Sobrienstatic bfd_boolean
1508130561Sobriennotice (struct bfd_link_info *info,
1509130561Sobrien	const char *name,
1510130561Sobrien	bfd *abfd,
1511130561Sobrien	asection *section,
1512130561Sobrien	bfd_vma value)
151333965Sjdp{
1514218822Sdim  if (name == NULL)
1515218822Sdim    {
1516218822Sdim      if (command_line.cref || nocrossref_list != NULL)
1517218822Sdim	return handle_asneeded_cref (abfd, value);
1518218822Sdim      return TRUE;
1519218822Sdim    }
1520218822Sdim
152133965Sjdp  if (! info->notice_all
152233965Sjdp      || (info->notice_hash != NULL
1523130561Sobrien	  && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
152460484Sobrien    {
152560484Sobrien      if (bfd_is_und_section (section))
152660484Sobrien	einfo ("%B: reference to %s\n", abfd, name);
152760484Sobrien      else
152860484Sobrien	einfo ("%B: definition of %s\n", abfd, name);
152960484Sobrien    }
153033965Sjdp
153133965Sjdp  if (command_line.cref || nocrossref_list != NULL)
153233965Sjdp    add_cref (name, abfd, section, value);
153333965Sjdp
1534130561Sobrien  return TRUE;
153533965Sjdp}
1536