/* Main program of GNU linker.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Written by Steve Chamberlain steve@cygnus.com
/* True means create DT_NEEDED entries for dynamic libraries that
are DT_NEEDED by dynamic libraries specifically mentioned on
the command line. */
-bfd_boolean add_DT_NEEDED_for_dynamic = TRUE;
+bfd_boolean add_DT_NEEDED_for_dynamic;
/* TRUE if we should demangle symbol names. */
bfd_boolean demangling;
static bfd_boolean add_archive_element
(struct bfd_link_info *, bfd *, const char *, bfd **);
static bfd_boolean multiple_definition
- (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma,
+ (struct bfd_link_info *, struct bfd_link_hash_entry *,
bfd *, asection *, bfd_vma);
static bfd_boolean multiple_common
- (struct bfd_link_info *, const char *, bfd *, enum bfd_link_hash_type,
- bfd_vma, bfd *, enum bfd_link_hash_type, bfd_vma);
+ (struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd *, enum bfd_link_hash_type, bfd_vma);
static bfd_boolean add_to_set
(struct bfd_link_info *, struct bfd_link_hash_entry *,
bfd_reloc_code_real_type, bfd *, asection *, bfd_vma);
static bfd_boolean unattached_reloc
(struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
static bfd_boolean notice
- (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
+ (struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd *, asection *, bfd_vma, flagword, const char *);
static struct bfd_link_callbacks link_callbacks =
{
struct bfd_link_info link_info;
\f
static void
-remove_output (void)
+ld_cleanup (void)
{
- if (output_filename)
- {
- if (link_info.output_bfd)
- bfd_cache_close (link_info.output_bfd);
- if (delete_output_file_on_failure)
- unlink_if_ordinary (output_filename);
- }
+ bfd_cache_close_all ();
+#ifdef ENABLE_PLUGINS
+ plugin_call_cleanup ();
+#endif
+ if (output_filename && delete_output_file_on_failure)
+ unlink_if_ordinary (output_filename);
}
int
bfd_set_error_program_name (program_name);
- xatexit (remove_output);
+ xatexit (ld_cleanup);
/* Set up the sysroot directory. */
ld_sysroot = get_sysroot (argc, argv);
if (config.hash_table_size != 0)
bfd_hash_set_default_size (config.hash_table_size);
- ldemul_set_symbols ();
-
- if (link_info.relocatable)
- {
- if (command_line.check_section_addresses < 0)
- command_line.check_section_addresses = 0;
- if (link_info.shared)
- einfo (_("%P%F: -r and -shared may not be used together\n"));
- }
-
- /* We may have -Bsymbolic, -Bsymbolic-functions, --dynamic-list-data,
- --dynamic-list-cpp-new, --dynamic-list-cpp-typeinfo and
- --dynamic-list FILE. -Bsymbolic and -Bsymbolic-functions are
- for shared libraries. -Bsymbolic overrides all others and vice
- versa. */
- switch (command_line.symbolic)
- {
- case symbolic_unset:
- break;
- case symbolic:
- /* -Bsymbolic is for shared library only. */
- if (link_info.shared)
- {
- link_info.symbolic = TRUE;
- /* Should we free the unused memory? */
- link_info.dynamic_list = NULL;
- command_line.dynamic_list = dynamic_list_unset;
- }
- break;
- case symbolic_functions:
- /* -Bsymbolic-functions is for shared library only. */
- if (link_info.shared)
- command_line.dynamic_list = dynamic_list_data;
- break;
- }
-
- switch (command_line.dynamic_list)
- {
- case dynamic_list_unset:
- break;
- case dynamic_list_data:
- link_info.dynamic_data = TRUE;
- case dynamic_list:
- link_info.dynamic = TRUE;
- break;
- }
-
- if (! link_info.shared)
- {
- if (command_line.filter_shlib)
- einfo (_("%P%F: -F may not be used without -shared\n"));
- if (command_line.auxiliary_filters)
- einfo (_("%P%F: -f may not be used without -shared\n"));
- }
-
- if (! link_info.shared || link_info.pie)
- link_info.executable = TRUE;
+#ifdef ENABLE_PLUGINS
+ /* Now all the plugin arguments have been gathered, we can load them. */
+ if (plugin_load_plugins ())
+ einfo (_("%P%F: %s: error loading plugin\n"), plugin_error_plugin ());
+#endif /* ENABLE_PLUGINS */
- /* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols). I
- don't see how else this can be handled, since in this case we
- must preserve all externally visible symbols. */
- if (link_info.relocatable && link_info.strip == strip_all)
- {
- link_info.strip = strip_debugger;
- if (link_info.discard == discard_sec_merge)
- link_info.discard = discard_all;
- }
+ ldemul_set_symbols ();
/* If we have not already opened and parsed a linker script,
try the default script from command line first. */
info_msg ("\n==================================================\n");
}
+ if (command_line.print_output_format)
+ info_msg ("%s\n", lang_get_output_target ());
+
lang_final ();
if (!lang_has_input_file)
{
- if (version_printed)
+ if (version_printed || command_line.print_output_format)
xexit (0);
einfo (_("%P%F: no input files\n"));
}
lang_finish ();
-#ifdef ENABLE_PLUGINS
- /* Now everything is finished, we can tell the plugins to clean up. */
- if (plugin_call_cleanup ())
- info_msg (_("%P: %s: error in plugin cleanup (ignored)\n"), plugin_error_plugin ());
-#endif /* ENABLE_PLUGINS */
-
/* Even if we're producing relocatable output, some non-fatal errors should
be reported in the exit status. (What non-fatal errors, if any, do we
want to ignore for relocatable output?) */
einfo (_("%P: link errors found, deleting executable `%s'\n"),
output_filename);
- /* The file will be removed by remove_output. */
+ /* The file will be removed by ld_cleanup. */
xexit (1);
}
else
#endif
long run_time = get_run_time () - start_time;
+ fflush (stdout);
fprintf (stderr, _("%s: total time in link: %ld.%06ld\n"),
program_name, run_time / 1000000, run_time % 1000000);
#ifdef HAVE_SBRK
fprintf (stderr, _("%s: data size %ld\n"), program_name,
(long) (lim - (char *) &environ));
#endif
+ fflush (stderr);
}
- /* Prevent remove_output from doing anything, after a successful link. */
+ /* Prevent ld_cleanup from doing anything, after a successful link. */
output_filename = NULL;
xexit (0);
BFD, but we still want to output the original BFD filename. */
orig_input = *input;
#ifdef ENABLE_PLUGINS
- if (bfd_my_archive (abfd) != NULL)
+ if (plugin_active_plugins_p () && !no_more_claiming)
{
/* We must offer this archive member to the plugins to claim. */
- int fd = open (bfd_my_archive (abfd)->filename, O_RDONLY | O_BINARY);
+ const char *filename = (bfd_my_archive (abfd) != NULL
+ ? bfd_my_archive (abfd)->filename : abfd->filename);
+ int fd = open (filename, O_RDONLY | O_BINARY);
if (fd >= 0)
{
struct ld_plugin_input_file file;
- int claimed = 0;
+
/* Offset and filesize must refer to the individual archive
member, not the whole file, and must exclude the header.
Fortunately for us, that is how the data is stored in the
origin field of the bfd and in the arelt_data. */
- file.name = bfd_my_archive (abfd)->filename;
+ file.name = filename;
file.offset = abfd->origin;
file.filesize = arelt_size (abfd);
file.fd = fd;
- /* We create a dummy BFD, initially empty, to house
- whatever symbols the plugin may want to add. */
- file.handle = plugin_get_ir_dummy_bfd (abfd->filename, abfd);
- if (plugin_call_claim_file (&file, &claimed))
- einfo (_("%P%F: %s: plugin reported error claiming file\n"),
- plugin_error_plugin ());
- if (claimed)
+ plugin_maybe_claim (&file, input);
+ if (input->claimed)
{
- /* Substitute the dummy BFD. */
- input->the_bfd = file.handle;
- input->claimed = TRUE;
- bfd_make_readable (input->the_bfd);
+ input->claim_archive = TRUE;
*subsbfd = input->the_bfd;
}
- else
- {
- /* Abandon the dummy BFD. */
- bfd_close_all_done (file.handle);
- close (fd);
- input->claimed = FALSE;
- }
}
}
#endif /* ENABLE_PLUGINS */
multiple times. */
static bfd_boolean
-multiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED,
- const char *name,
- bfd *obfd,
- asection *osec,
- bfd_vma oval,
+multiple_definition (struct bfd_link_info *info,
+ struct bfd_link_hash_entry *h,
bfd *nbfd,
asection *nsec,
bfd_vma nval)
{
-#ifdef ENABLE_PLUGINS
- /* We may get called back even when --allow-multiple-definition is in
- effect, as the plugin infrastructure needs to use this hook in
- order to swap out IR-only symbols for real ones. In that case,
- it will let us know not to continue by returning TRUE even if this
- is not an IR-only vs. non-IR symbol conflict. */
- if (plugin_multiple_definition (info, name, obfd, osec, oval, nbfd,
- nsec, nval))
+ const char *name;
+ bfd *obfd;
+ asection *osec;
+ bfd_vma oval;
+
+ if (info->allow_multiple_definition)
+ return TRUE;
+
+ switch (h->type)
+ {
+ case bfd_link_hash_defined:
+ osec = h->u.def.section;
+ oval = h->u.def.value;
+ obfd = h->u.def.section->owner;
+ break;
+ case bfd_link_hash_indirect:
+ osec = bfd_ind_section_ptr;
+ oval = 0;
+ obfd = NULL;
+ break;
+ default:
+ abort ();
+ }
+
+ /* Ignore a redefinition of an absolute symbol to the
+ same value; it's harmless. */
+ if (h->type == bfd_link_hash_defined
+ && bfd_is_abs_section (osec)
+ && bfd_is_abs_section (nsec)
+ && nval == oval)
return TRUE;
-#endif /* ENABLE_PLUGINS */
/* If either section has the output_section field set to
bfd_abs_section_ptr, it means that the section is being
&& bfd_is_abs_section (nsec->output_section)))
return TRUE;
+ name = h->root.string;
+ if (nbfd == NULL)
+ {
+ nbfd = obfd;
+ nsec = osec;
+ nval = oval;
+ obfd = NULL;
+ }
einfo (_("%X%C: multiple definition of `%T'\n"),
nbfd, nsec, nval, name);
if (obfd != NULL)
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,
+ struct bfd_link_hash_entry *h,
bfd *nbfd,
enum bfd_link_hash_type ntype,
bfd_vma nsize)
{
- if (! config.warn_common)
+ const char *name;
+ bfd *obfd;
+ enum bfd_link_hash_type otype;
+ bfd_vma osize;
+
+ if (!config.warn_common)
return TRUE;
+ name = h->root.string;
+ otype = h->type;
+ if (otype == bfd_link_hash_common)
+ {
+ obfd = h->u.c.p->section->owner;
+ osize = h->u.c.size;
+ }
+ else if (otype == bfd_link_hash_defined
+ || otype == bfd_link_hash_defweak)
+ {
+ obfd = h->u.def.section->owner;
+ osize = 0;
+ }
+ else
+ {
+ /* FIXME: It would nice if we could report the BFD which defined
+ an indirect symbol, but we don't have anywhere to store the
+ information. */
+ obfd = NULL;
+ osize = 0;
+ }
+
if (ntype == bfd_link_hash_defined
|| ntype == bfd_link_hash_defweak
|| ntype == bfd_link_hash_indirect)
if (overflow_cutoff_limit == -1)
return TRUE;
- einfo ("%X%C:", abfd, section, address);
+ einfo ("%X%H:", abfd, section, address);
if (overflow_cutoff_limit >= 0
&& overflow_cutoff_limit-- == 0)
asection *section,
bfd_vma address)
{
- einfo (_("%X%C: dangerous relocation: %s\n"),
+ einfo (_("%X%H: dangerous relocation: %s\n"),
abfd, section, address, message);
return TRUE;
}
asection *section,
bfd_vma address)
{
- einfo (_("%X%C: reloc refers to symbol `%T' which is not being output\n"),
+ einfo (_("%X%H: reloc refers to symbol `%T' which is not being output\n"),
abfd, section, address, name);
return TRUE;
}
static bfd_boolean
notice (struct bfd_link_info *info,
- const char *name,
+ struct bfd_link_hash_entry *h,
bfd *abfd,
asection *section,
- bfd_vma value)
+ bfd_vma value,
+ flagword flags ATTRIBUTE_UNUSED,
+ const char *string ATTRIBUTE_UNUSED)
{
- if (name == NULL)
+ const char *name;
+
+ if (h == NULL)
{
if (command_line.cref || nocrossref_list != NULL)
return handle_asneeded_cref (abfd, (enum notice_asneeded_action) value);
return TRUE;
}
-#ifdef ENABLE_PLUGINS
- /* We should hide symbols in the dummy IR BFDs from the nocrossrefs list
- and let the real object files that are generated and added later trip
- the error instead. Similarly would be better to trace the real symbol
- from the real file than the temporary dummy. */
- if (!plugin_notice (info, name, abfd, section, value))
- return TRUE;
-#endif /* ENABLE_PLUGINS */
-
+ name = h->root.string;
if (info->notice_hash != NULL
- && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
+ && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
{
if (bfd_is_und_section (section))
einfo ("%B: reference to %s\n", abfd, name);