/* linker.c -- BFD linker routines
- Copyright (C) 1993-2014 Free Software Foundation, Inc.
+ Copyright (C) 1993-2015 Free Software Foundation, Inc.
Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
This file is part of BFD, the Binary File Descriptor library.
{
enum link_row row;
struct bfd_link_hash_entry *h;
+ struct bfd_link_hash_entry *inh = NULL;
bfd_boolean cycle;
BFD_ASSERT (section != NULL);
if (bfd_is_ind_section (section)
|| (flags & BSF_INDIRECT) != 0)
- row = INDR_ROW;
+ {
+ row = INDR_ROW;
+ /* Create the indirect symbol here. This is for the benefit of
+ the plugin "notice" function.
+ STRING is the name of the symbol we want to indirect to. */
+ inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
+ copy, FALSE);
+ if (inh == NULL)
+ return FALSE;
+ }
else if ((flags & BSF_WARNING) != 0)
row = WARN_ROW;
else if ((flags & BSF_CONSTRUCTOR) != 0)
|| (info->notice_hash != NULL
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
{
- if (! (*info->callbacks->notice) (info, h,
- abfd, section, value, flags, string))
+ if (! (*info->callbacks->notice) (info, h, inh,
+ abfd, section, value, flags))
return FALSE;
}
h->type = bfd_link_hash_defined;
h->u.def.section = section;
h->u.def.value = value;
+ h->linker_def = 0;
/* If we have been asked to, we act like collect2 and
identify all functions that might be global
}
else
h->u.c.p->section = section;
+ h->linker_def = 0;
break;
case REF:
return FALSE;
/* Fall through. */
case IND:
- /* Create an indirect symbol. */
- {
- struct bfd_link_hash_entry *inh;
-
- /* STRING is the name of the symbol we want to indirect
- to. */
- inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
- copy, FALSE);
- if (inh == NULL)
+ if (inh->type == bfd_link_hash_indirect
+ && inh->u.i.link == h)
+ {
+ (*_bfd_error_handler)
+ (_("%B: indirect symbol `%s' to `%s' is a loop"),
+ abfd, name, string);
+ bfd_set_error (bfd_error_invalid_operation);
return FALSE;
- if (inh->type == bfd_link_hash_indirect
- && inh->u.i.link == h)
- {
- (*_bfd_error_handler)
- (_("%B: indirect symbol `%s' to `%s' is a loop"),
- abfd, name, string);
- bfd_set_error (bfd_error_invalid_operation);
- return FALSE;
- }
- if (inh->type == bfd_link_hash_new)
- {
- inh->type = bfd_link_hash_undefined;
- inh->u.undef.abfd = abfd;
- bfd_link_add_undef (info->hash, inh);
- }
+ }
+ if (inh->type == bfd_link_hash_new)
+ {
+ inh->type = bfd_link_hash_undefined;
+ inh->u.undef.abfd = abfd;
+ bfd_link_add_undef (info->hash, inh);
+ }
- /* If the indirect symbol has been referenced, we need to
- push the reference down to the symbol we are
- referencing. */
- if (h->type != bfd_link_hash_new)
- {
- row = UNDEF_ROW;
- cycle = TRUE;
- }
+ /* If the indirect symbol has been referenced, we need to
+ push the reference down to the symbol we are referencing. */
+ if (h->type != bfd_link_hash_new)
+ {
+ /* ??? If inh->type == bfd_link_hash_undefweak this
+ converts inh to bfd_link_hash_undefined. */
+ row = UNDEF_ROW;
+ cycle = TRUE;
+ }
- h->type = bfd_link_hash_indirect;
- h->u.i.link = inh;
- }
+ h->type = bfd_link_hash_indirect;
+ h->u.i.link = inh;
+ /* Not setting h = h->u.i.link here means that when cycle is
+ set above we'll always go to REFC, and then cycle again
+ to the indirected symbol. This means that any successful
+ change of an existing symbol to indirect counts as a
+ reference. ??? That may not be correct when the existing
+ symbol was defweak. */
break;
case SET:
case WARN:
/* Warn if this symbol has been referenced already from non-IR,
otherwise add a warning. */
- if (h->non_ir_ref)
+ if ((!info->lto_plugin_active
+ && (h->u.undef.next != NULL || info->hash->undefs_tail == h))
+ || h->non_ir_ref)
{
if (! (*info->callbacks->warning) (info, string, h->root.string,
hash_entry_bfd (h), NULL, 0))
/* fall through */
case bfd_link_hash_defined:
sym->flags |= BSF_GLOBAL;
- sym->flags &=~ BSF_CONSTRUCTOR;
+ sym->flags &=~ (BSF_WEAK | BSF_CONSTRUCTOR);
sym->value = h->root.u.def.value;
sym->section = h->root.u.def.section;
break;
size = bfd_get_reloc_size (r->howto);
buf = (bfd_byte *) bfd_zmalloc (size);
- if (buf == NULL)
+ if (buf == NULL && size != 0)
return FALSE;
rstat = _bfd_relocate_contents (r->howto, abfd,
(bfd_vma) link_order->u.reloc.p->addend,
files over IR because the first pass may contain a
mix of LTO and normal objects and we must keep the
first match, be it IR or real. */
- if (info->loading_lto_outputs
+ if (sec->owner->lto_output
&& (l->sec->owner->flags & BFD_PLUGIN) != 0)
{
l->sec = sec;